Skip to content

Commit 67d7d8e

Browse files
committed
builtin/repo: add progress meter for structure stats
When using the structure subcommand for git-repo(1), evaluating a repository may take some time depending on its shape. Add a progress meter to provide feedback to the user about what is happening. The progress meter is enabled by default when the command is executed from a tty. It can also be explicitly enabled/disabled via the --[no-]progress option. Signed-off-by: Justin Tobler <[email protected]>
1 parent 3d42929 commit 67d7d8e

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

builtin/repo.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "environment.h"
55
#include "parse-options.h"
66
#include "path-walk.h"
7+
#include "progress.h"
78
#include "quote.h"
89
#include "ref-filter.h"
910
#include "refs.h"
@@ -362,6 +363,7 @@ static void structure_keyvalue_print(struct repo_structure *stats,
362363
struct count_references_data {
363364
struct ref_stats *stats;
364365
struct rev_info *revs;
366+
struct progress *progress;
365367
};
366368

367369
static int count_references(const char *refname,
@@ -371,6 +373,7 @@ static int count_references(const char *refname,
371373
{
372374
struct count_references_data *data = cb_data;
373375
struct ref_stats *stats = data->stats;
376+
size_t ref_count;
374377

375378
switch (ref_kind_from_refname(refname)) {
376379
case FILTER_REFS_BRANCHES:
@@ -395,26 +398,41 @@ static int count_references(const char *refname,
395398
*/
396399
add_pending_oid(data->revs, NULL, oid, 0);
397400

401+
ref_count = get_total_reference_count(stats);
402+
display_progress(data->progress, ref_count);
403+
398404
return 0;
399405
}
400406

401407
static void structure_count_references(struct ref_stats *stats,
402408
struct rev_info *revs,
403-
struct repository *repo)
409+
struct repository *repo,
410+
int show_progress)
404411
{
405412
struct count_references_data data = {
406413
.stats = stats,
407414
.revs = revs,
408415
};
409416

417+
if (show_progress)
418+
data.progress = start_delayed_progress(repo,
419+
_("Counting references"), 0);
420+
410421
refs_for_each_ref(get_main_ref_store(repo), count_references, &data);
422+
stop_progress(&data.progress);
411423
}
412424

425+
struct count_objects_data {
426+
struct object_stats *stats;
427+
struct progress *progress;
428+
};
413429

414430
static int count_objects(const char *path UNUSED, struct oid_array *oids,
415431
enum object_type type, void *cb_data)
416432
{
417-
struct object_stats *stats = cb_data;
433+
struct count_objects_data *data = cb_data;
434+
struct object_stats *stats = data->stats;
435+
size_t object_count;
418436

419437
switch (type) {
420438
case OBJ_TAG:
@@ -433,20 +451,31 @@ static int count_objects(const char *path UNUSED, struct oid_array *oids,
433451
BUG("invalid object type");
434452
}
435453

454+
object_count = get_total_object_count(stats);
455+
display_progress(data->progress, object_count);
456+
436457
return 0;
437458
}
438459

439460
static void structure_count_objects(struct object_stats *stats,
440-
struct rev_info *revs)
461+
struct rev_info *revs,
462+
struct repository *repo, int show_progress)
441463
{
442464
struct path_walk_info info = PATH_WALK_INFO_INIT;
465+
struct count_objects_data data = {
466+
.stats = stats,
467+
};
443468

444469
info.revs = revs;
445470
info.path_fn = count_objects;
446-
info.path_fn_data = stats;
471+
info.path_fn_data = &data;
472+
473+
if (show_progress)
474+
data.progress = start_delayed_progress(repo, _("Counting objects"), 0);
447475

448476
walk_objects_by_path(&info);
449477
path_walk_info_clear(&info);
478+
stop_progress(&data.progress);
450479
}
451480

452481
static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
@@ -458,10 +487,12 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
458487
enum output_format format = FORMAT_TABLE;
459488
struct repo_structure stats = { 0 };
460489
struct rev_info revs;
490+
int show_progress = -1;
461491
struct option options[] = {
462492
OPT_CALLBACK_F(0, "format", &format, N_("format"),
463493
N_("output format"),
464494
PARSE_OPT_NONEG, parse_format_cb),
495+
OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
465496
OPT_END()
466497
};
467498

@@ -471,8 +502,11 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
471502

472503
repo_init_revisions(repo, &revs, prefix);
473504

474-
structure_count_references(&stats.refs, &revs, repo);
475-
structure_count_objects(&stats.objects, &revs);
505+
if (show_progress < 0)
506+
show_progress = isatty(2);
507+
508+
structure_count_references(&stats.refs, &revs, repo, show_progress);
509+
structure_count_objects(&stats.objects, &revs, repo, show_progress);
476510

477511
switch (format) {
478512
case FORMAT_TABLE:

t/t1901-repo-structure.sh

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,24 @@ test_expect_success 'keyvalue and nul format' '
106106
)
107107
'
108108

109+
test_expect_success 'progress meter option' '
110+
test_when_finished "rm -rf repo" &&
111+
git init repo &&
112+
(
113+
cd repo &&
114+
test_commit foo &&
115+
116+
GIT_PROGRESS_DELAY=0 git repo structure --progress >out 2>err &&
117+
118+
test_file_not_empty out &&
119+
test_grep "Counting references: 2, done." err &&
120+
test_grep "Counting objects: 3, done." err &&
121+
122+
GIT_PROGRESS_DELAY=0 git repo structure --no-progress >out 2>err &&
123+
124+
test_file_not_empty out &&
125+
test_line_count = 0 err
126+
)
127+
'
128+
109129
test_done

0 commit comments

Comments
 (0)