rev-list: add optional progress reporting

It's easy to ask rev-list to do a traversal that may takes many seconds (e.g., by calling "--objects --all"). In theory you can monitor its progress by the output you get to stdout, but this isn't always easy. Some operations, like "--count", don't make any output until the end. And some callers, like check_everything_connected(), are using it just for the error-checking of the traversal, and throw away stdout entirely. This patch adds a "--progress" option which can be used to give some eye-candy for a user waiting for a long traversal. This is just a rev-list option and not a regular traversal option, because it needs cooperation from the callbacks in builtin/rev-list.c to do the actual count. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jul 20, 2016 at 07:28 UTC 434ea3cdadf8c7592ba167ce122d3984e984a158
2 files changed +21
Documentation/rev-list-options.txt
+4
@@ -274,6 +274,10 @@ ifdef::git-rev-list[]
274 Try to speed up the traversal using the pack bitmap index (if
275 one is available). Note that when traversing with `--objects`,
276 trees and blobs will not have their associated path printed.
277 +
278 +--progress=<header>::
279 + Show progress reports on stderr as objects are considered. The
280 + `<header>` text will be printed with each progress update.
281 endif::git-rev-list[]
282
283 --
builtin/rev-list.c
+17
@@ -9,6 +9,7 @@
9 #include "log-tree.h"
10 #include "graph.h"
11 #include "bisect.h"
12 +#include "progress.h"
13
14 static const char rev_list_usage[] =
15 "git rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
@@ -49,12 +50,17 @@ static const char rev_list_usage[] =
50 " --bisect-all"
51 ;
52
53 +static struct progress *progress;
54 +static unsigned progress_counter;
55 +
56 static void finish_commit(struct commit *commit, void *data);
57 static void show_commit(struct commit *commit, void *data)
58 {
59 struct rev_list_info *info = data;
60 struct rev_info *revs = info->revs;
61
62 + display_progress(progress, ++progress_counter);
63 +
64 if (info->flags & REV_LIST_QUIET) {
65 finish_commit(commit, data);
66 return;
@@ -190,6 +196,7 @@ static void show_object(struct object *obj, const char *name, void *cb_data)
196 {
197 struct rev_list_info *info = cb_data;
198 finish_object(obj, name, cb_data);
199 + display_progress(progress, ++progress_counter);
200 if (info->flags & REV_LIST_QUIET)
201 return;
202 show_object_with_name(stdout, obj, name);
@@ -276,6 +283,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
283 int bisect_show_vars = 0;
284 int bisect_find_all = 0;
285 int use_bitmap_index = 0;
286 + const char *show_progress = NULL;
287
288 git_config(git_default_config, NULL);
289 init_revisions(&revs, prefix);
@@ -325,6 +333,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
333 test_bitmap_walk(&revs);
334 return 0;
335 }
336 + if (skip_prefix(arg, "--progress=", &arg)) {
337 + show_progress = arg;
338 + continue;
339 + }
340 usage(rev_list_usage);
341
342 }
@@ -355,6 +367,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
367 if (bisect_list)
368 revs.limited = 1;
369
370 + if (show_progress)
371 + progress = start_progress_delay(show_progress, 0, 0, 2);
372 +
373 if (use_bitmap_index && !revs.prune) {
374 if (revs.count && !revs.left_right && !revs.cherry_mark) {
375 uint32_t commit_count;
@@ -392,6 +407,8 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
407
408 traverse_commit_list(&revs, show_commit, show_object, &info);
409
410 + stop_progress(&progress);
411 +
412 if (revs.count) {
413 if (revs.left_right && revs.cherry_mark)
414 printf("%d\t%d\t%d\n", revs.count_left, revs.count_right, revs.count_same);