summaryrefslogtreecommitdiff
path: root/builtin-log.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2007-11-04 20:12:05 (GMT)
committerJunio C Hamano <gitster@pobox.com>2007-11-05 22:28:53 (GMT)
commit252a7c02354a3e2825cfde3c5053a04acc07be9c (patch)
tree0a0d349a0299800c1791a32771d664f87eee20ae /builtin-log.c
parentcdcefbc971d8fcdd293750af7571d4c715f86964 (diff)
downloadgit-252a7c02354a3e2825cfde3c5053a04acc07be9c.zip
git-252a7c02354a3e2825cfde3c5053a04acc07be9c.tar.gz
git-252a7c02354a3e2825cfde3c5053a04acc07be9c.tar.bz2
Enhance --early-output format
This makes --early-output a bit more advanced, and actually makes it generate multiple "Final output:" headers as it updates things asynchronously. I realize that the "Final output:" line is now illogical, since it's not really final until it also says "done", but It now _always_ generates a "Final output:" header in front of any commit list, and that output header gives you a *guess* at the maximum number of commits available. However, it should be noted that the guess can be completely off: I do a reasonable job estimating it, but it is not meant to be exact. So what happens is that you may get output like this: - at 0.1 seconds: Final output: 2 incomplete .. 2 commits listed .. - half a second later: Final output: 33 incomplete .. 33 commits listed .. - another half a second after that: Final output: 71 incomplete .. 71 commits listed .. - another half second later: Final output: 136 incomplete .. 100 commits listed: we hit the --early-output limit, and .. will only output 100 commits, and after this you'll not .. see an "incomplete" report any more since you got as much .. early output as you asked for! - .. and then finally: Final output: 73106 done .. all the commits .. The above is a real-life scenario on my current kernel tree after having flushed all the caches. Tested with the experimental gitk patch that Paul sent out, and by looking at the actual log output (and verifying that my commit count guesses actually match real life fairly well). Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'builtin-log.c')
-rw-r--r--builtin-log.c88
1 files changed, 75 insertions, 13 deletions
diff --git a/builtin-log.c b/builtin-log.c
index 4e9d0cb..981f388 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -77,17 +77,85 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
}
}
+/*
+ * This gives a rough estimate for how many commits we
+ * will print out in the list.
+ */
+static int estimate_commit_count(struct rev_info *rev, struct commit_list *list)
+{
+ int n = 0;
+
+ while (list) {
+ struct commit *commit = list->item;
+ unsigned int flags = commit->object.flags;
+
+ list = list->next;
+ if (flags & UNINTERESTING)
+ continue;
+ if (rev->prune_fn && rev->dense && !(flags & TREECHANGE)) {
+ if (commit->parents && !commit->parents->next)
+ continue;
+ }
+ n++;
+ }
+ return n;
+}
+
+static void show_early_header(struct rev_info *rev, const char *stage, int nr)
+{
+ if (rev->shown_one) {
+ rev->shown_one = 0;
+ if (rev->commit_format != CMIT_FMT_ONELINE)
+ putchar(rev->diffopt.line_termination);
+ }
+ printf("Final output: %d %s\n", nr, stage);
+}
+
+struct itimerval early_output_timer;
+
static void log_show_early(struct rev_info *revs, struct commit_list *list)
{
int i = revs->early_output;
+ int show_header = 1;
sort_in_topological_order(&list, revs->lifo);
while (list && i) {
struct commit *commit = list->item;
- log_tree_commit(revs, commit);
+ switch (simplify_commit(revs, commit)) {
+ case commit_show:
+ if (show_header) {
+ int n = estimate_commit_count(revs, list);
+ show_early_header(revs, "incomplete", n);
+ show_header = 0;
+ }
+ log_tree_commit(revs, commit);
+ i--;
+ break;
+ case commit_ignore:
+ break;
+ case commit_error:
+ return;
+ }
list = list->next;
- i--;
}
+
+ /* Did we already get enough commits for the early output? */
+ if (!i)
+ return;
+
+ /*
+ * ..if no, then repeat it twice a second until we
+ * do.
+ *
+ * NOTE! We don't use "it_interval", because if the
+ * reader isn't listening, we want our output to be
+ * throttled by the writing, and not have the timer
+ * trigger every second even if we're blocked on a
+ * reader!
+ */
+ early_output_timer.it_value.tv_sec = 0;
+ early_output_timer.it_value.tv_usec = 500000;
+ setitimer(ITIMER_REAL, &early_output_timer, NULL);
}
static void early_output(int signal)
@@ -98,7 +166,6 @@ static void early_output(int signal)
static void setup_early_output(struct rev_info *rev)
{
struct sigaction sa;
- struct itimerval v;
/*
* Set up the signal handler, minimally intrusively:
@@ -120,21 +187,16 @@ static void setup_early_output(struct rev_info *rev)
*
* 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);
+ early_output_timer.it_value.tv_sec = 0;
+ early_output_timer.it_value.tv_usec = 100000;
+ setitimer(ITIMER_REAL, &early_output_timer, NULL);
}
static void finish_early_output(struct rev_info *rev)
{
+ int n = estimate_commit_count(rev, rev->commits);
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");
+ show_early_header(rev, "done", n);
}
static int cmd_log_walk(struct rev_info *rev)