Skip to content

Commit

Permalink
Add "--early-output" log flag for interactive GUI use
Browse files Browse the repository at this point in the history
This adds support for "--early-output[=n]" as a flag to the "git log"
family of commands.  This allows GUI programs to state that they want to
get some output early, in order to be able to show at least something
quickly, even if the full output may take longer to generate.

If no count is specified, a default count of a hundred commits will be
used, although the actual numbr of commits output may be smaller
depending on how many commits were actually found in the first tenth of
a second (or if *everything* was found before that, in which case no
early output will be provided, and only the final list is made
available).

When the full list is generated, there will be a "Final output:" string
prepended to it, regardless of whether any early commits were shown or
not, so that the consumer can always know the difference between early
output and the final list.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Linus Torvalds authored and Junio C Hamano committed Nov 4, 2007
1 parent 23c17d4 commit cdcefbc
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
67 changes: 67 additions & 0 deletions builtin-log.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,78 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
}
}

static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
int i = revs->early_output;

sort_in_topological_order(&list, revs->lifo);
while (list && i) {
struct commit *commit = list->item;
log_tree_commit(revs, commit);
list = list->next;
i--;
}
}

static void early_output(int signal)
{
show_early_output = log_show_early;
}

static void setup_early_output(struct rev_info *rev)
{
struct sigaction sa;
struct itimerval v;

/*
* Set up the signal handler, minimally intrusively:
* we only set a single volatile integer word (not
* using sigatomic_t - trying to avoid unnecessary
* system dependencies and headers), and using
* SA_RESTART.
*/
memset(&sa, 0, sizeof(sa));
sa.sa_handler = early_output;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGALRM, &sa, NULL);

/*
* If we can get the whole output in less than a
* tenth of a second, don't even bother doing the
* early-output thing..
*
* This is a one-time-only trigger.
*/
memset(&v, 0, sizeof(v));
v.it_value.tv_sec = 0;
v.it_value.tv_usec = 100000;
setitimer(ITIMER_REAL, &v, NULL);
}

static void finish_early_output(struct rev_info *rev)
{
signal(SIGALRM, SIG_IGN);
if (rev->shown_one) {
rev->shown_one = 0;
if (rev->commit_format != CMIT_FMT_ONELINE)
putchar(rev->diffopt.line_termination);
}
printf("Final output:\n");
}

static int cmd_log_walk(struct rev_info *rev)
{
struct commit *commit;

if (rev->early_output)
setup_early_output(rev);

prepare_revision_walk(rev);

if (rev->early_output)
finish_early_output(rev);

while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
if (!rev->reflog_info) {
Expand Down
22 changes: 22 additions & 0 deletions revision.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "reflog-walk.h"
#include "patch-ids.h"

volatile show_early_output_fn_t show_early_output;

static char *path_name(struct name_path *path, const char *name)
{
struct name_path *p;
Expand Down Expand Up @@ -533,6 +535,7 @@ static int limit_list(struct rev_info *revs)
struct commit_list *entry = list;
struct commit *commit = list->item;
struct object *obj = &commit->object;
show_early_output_fn_t show;

list = list->next;
free(entry);
Expand All @@ -550,6 +553,13 @@ static int limit_list(struct rev_info *revs)
if (revs->min_age != -1 && (commit->date > revs->min_age))
continue;
p = &commit_list_insert(commit, p)->next;

show = show_early_output;
if (!show)
continue;

show(revs, newlist);
show_early_output = NULL;
}
if (revs->cherry_pick)
cherry_pick_list(newlist, revs);
Expand Down Expand Up @@ -991,6 +1001,18 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->topo_order = 1;
continue;
}
if (!prefixcmp(arg, "--early-output")) {
int count = 100;
switch (arg[14]) {
case '=':
count = atoi(arg+15);
/* Fallthrough */
case 0:
revs->topo_order = 1;
revs->early_output = count;
continue;
}
}
if (!strcmp(arg, "--parents")) {
revs->parents = 1;
continue;
Expand Down
4 changes: 4 additions & 0 deletions revision.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ struct rev_info {
void *prune_data;
prune_fn_t *prune_fn;

unsigned int early_output;

/* Traversal flags */
unsigned int dense:1,
no_merges:1,
Expand Down Expand Up @@ -105,6 +107,8 @@ struct rev_info {
#define REV_TREE_DIFFERENT 2

/* revision.c */
typedef void (*show_early_output_fn_t)(struct rev_info *, struct commit_list *);
volatile show_early_output_fn_t show_early_output;

extern void init_revisions(struct rev_info *revs, const char *prefix);
extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
Expand Down

0 comments on commit cdcefbc

Please sign in to comment.