From eda206f61125ec5e0985809c1cf0a853abca2ae7 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:31 -0400 Subject: [PATCH 1/6] fsck: suppress commit-graph output with `--no-progress` Since e0fd51e1d7 (fsck: verify commit-graph, 2018-06-27), `fsck` runs `git commit-graph verify` to check the integrity of any commit-graph(s). Originally, the `git commit-graph verify` step would always print to stdout/stderr, regardless of whether or not `fsck` was invoked with `--[no-]progress` or not. But in 7371612255 (commit-graph: add --[no-]progress to write and verify, 2019-08-26), the commit-graph machinery learned the `--[no-]progress` option, though `fsck` was not updated to pass this new flag (or not). This led to seeing output from running `git fsck`, even with `--no-progress` on repositories that have a commit-graph: $ git.compile fsck --connectivity-only --no-progress --no-dangling Verifying commits in commit graph: 100% (4356/4356), done. Verifying commits in commit graph: 100% (131912/131912), done. Ensure that `fsck` passes `--[no-]progress` as appropriate when calling `git commit-graph verify`. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- builtin/fsck.c | 4 ++++ t/t5318-commit-graph.sh | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/builtin/fsck.c b/builtin/fsck.c index dcc165bf0c..915dc8b9b3 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1072,6 +1072,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) commit_graph_verify.git_cmd = 1; strvec_pushl(&commit_graph_verify.args, "commit-graph", "verify", "--object-dir", odb->path, NULL); + if (show_progress) + strvec_push(&commit_graph_verify.args, "--progress"); + else + strvec_push(&commit_graph_verify.args, "--no-progress"); if (run_command(&commit_graph_verify)) errors_found |= ERROR_COMMIT_GRAPH; } diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index b6e1211578..bf8a92317b 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -684,6 +684,16 @@ test_expect_success 'git fsck (checks commit-graph when config unset)' ' test_must_fail git fsck ' +test_expect_success 'git fsck shows commit-graph output with --progress' ' + git -C "$TRASH_DIRECTORY/full" fsck --progress 2>err && + grep "Verifying commits in commit graph" err +' + +test_expect_success 'git fsck suppresses commit-graph output with --no-progress' ' + git -C "$TRASH_DIRECTORY/full" fsck --no-progress 2>err && + ! grep "Verifying commits in commit graph" err +' + test_expect_success 'setup non-the_repository tests' ' rm -rf repo && git init repo && From 39bdd30377c18cf52da08441bb2cf2a354f0e5bb Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:34 -0400 Subject: [PATCH 2/6] fsck: suppress MIDX output with `--no-progress` In a similar spirit as the previous commit, address a bug where `git fsck` produces output when calling `git multi-pack-index verify` even when invoked with `--no-progress`. $ git.compile fsck --connectivity-only --no-progress --no-dangling Verifying OID order in multi-pack-index: 100% (605677/605677), done. Sorting objects by packfile: 100% (605678/605678), done. Verifying object offsets: 100% (605678/605678), done. The three lines produced by `git fsck` come from `git multi-pack-index verify`, but should be squelched due to `--no-progress`. The MIDX machinery learned to generate these progress messages as early as 430efb8a74b (midx: add progress indicators in multi-pack-index verify, 2019-03-21), but did not respect `--progress` or `--no-progress` until ad60096d1c8 (midx: honor the MIDX_PROGRESS flag in verify_midx_file, 2019-10-21). But the `git multi-pack-index verify` step was added to fsck in 66ec0390e75 (fsck: verify multi-pack-index, 2018-09-13), pre-dating any of the above patches. Pass `--[no-]progress` as appropriate to ensure that we don't produce output when told not to. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- builtin/fsck.c | 4 ++++ t/t5319-multi-pack-index.sh | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/builtin/fsck.c b/builtin/fsck.c index 915dc8b9b3..35ce68308c 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -1090,6 +1090,10 @@ int cmd_fsck(int argc, const char **argv, const char *prefix) midx_verify.git_cmd = 1; strvec_pushl(&midx_verify.args, "multi-pack-index", "verify", "--object-dir", odb->path, NULL); + if (show_progress) + strvec_push(&midx_verify.args, "--progress"); + else + strvec_push(&midx_verify.args, "--no-progress"); if (run_command(&midx_verify)) errors_found |= ERROR_MULTI_PACK_INDEX; } diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 0883c7c6bd..1bcc02004d 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -485,6 +485,18 @@ test_expect_success 'git-fsck incorrect offset' ' git -c core.multiPackIndex=false fsck ' +test_expect_success 'git fsck shows MIDX output with --progress' ' + git fsck --progress 2>err && + grep "Verifying OID order in multi-pack-index" err && + grep "Verifying object offsets" err +' + +test_expect_success 'git fsck suppresses MIDX output with --no-progress' ' + git fsck --no-progress 2>err && + ! grep "Verifying OID order in multi-pack-index" err && + ! grep "Verifying object offsets" err +' + test_expect_success 'corrupt MIDX is not reused' ' corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \ "incorrect object offset" && From eb319d6771f5829dc26499af93050350083adc7d Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:36 -0400 Subject: [PATCH 3/6] commit-graph.c: extract `verify_one_commit_graph()` When the `verify_commit_graph()` function was extended to support commit-graph chains via 3da4b609bb1 (commit-graph: verify chains with --shallow mode, 2019-06-18), it did so by recursively calling itself on each layer of the commit-graph chain. In practice this poses no issues, since commit-graph chains do not loop, and there are few enough of them that adding additional frames to the stack is not a problem. A future commit will consolidate the progress output from `git commit-graph verify` when verifying chained commit-graphs to print a single line instead of one progress meter per commit-graph layer. Prepare for this by extracting a routine to verify a single layer of a commit-graph. Note that `verify_commit_graph()` is still recursive after this patch, but this will change in the subsequent patch. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- commit-graph.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index 843bdb458d..e846920935 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2543,18 +2543,14 @@ static int commit_graph_checksum_valid(struct commit_graph *g) return hashfile_checksum_valid(g->data, g->data_len); } -int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) +static int verify_one_commit_graph(struct repository *r, + struct commit_graph *g, + int flags) { uint32_t i, cur_fanout_pos = 0; struct object_id prev_oid, cur_oid; int generation_zero = 0; struct progress *progress = NULL; - int local_error = 0; - - if (!g) { - graph_report("no commit-graph file loaded"); - return 1; - } verify_commit_graph_error = verify_commit_graph_lite(g); if (verify_commit_graph_error) @@ -2700,7 +2696,19 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) } stop_progress(&progress); - local_error = verify_commit_graph_error; + return verify_commit_graph_error; +} + +int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) +{ + int local_error = 0; + + if (!g) { + graph_report("no commit-graph file loaded"); + return 1; + } + + local_error = verify_one_commit_graph(r, g, flags); if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW) && g->base_graph) local_error |= verify_commit_graph(r, g->base_graph, flags); From f5facaa4653d3bcdb5ad5508e47d0e9a03c2aaa5 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:39 -0400 Subject: [PATCH 4/6] commit-graph.c: iteratively verify commit-graph chains Now that we have a function which can verify a single layer of a commit-graph chain, implement `verify_commit_graph()` in terms of iterating over commit-graphs along their `->base_graph` pointers. This further prepares us to consolidate the progress output of `git commit-graph verify`. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- commit-graph.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index e846920935..bb56733d8c 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2708,10 +2708,11 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) return 1; } - local_error = verify_one_commit_graph(r, g, flags); - - if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW) && g->base_graph) - local_error |= verify_commit_graph(r, g->base_graph, flags); + for (; g; g = g->base_graph) { + local_error |= verify_one_commit_graph(r, g, flags); + if (flags & COMMIT_GRAPH_VERIFY_SHALLOW) + break; + } return local_error; } From 7248857b6e74bb989dd067d2ac53605e77764700 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:42 -0400 Subject: [PATCH 5/6] commit-graph.c: pass progress to `verify_one_commit_graph()` This is the final step to prepare for consolidating the output of `git commit-graph verify`. Instead of having each call to `verify_one_commit_graph()` initialize its own progress struct, have the caller pass one in instead. This patch does not alter the output of `git commit-graph verify`, but the next commit will consolidate the output. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- commit-graph.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index bb56733d8c..9e89952831 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2545,12 +2545,11 @@ static int commit_graph_checksum_valid(struct commit_graph *g) static int verify_one_commit_graph(struct repository *r, struct commit_graph *g, - int flags) + struct progress *progress) { uint32_t i, cur_fanout_pos = 0; struct object_id prev_oid, cur_oid; int generation_zero = 0; - struct progress *progress = NULL; verify_commit_graph_error = verify_commit_graph_lite(g); if (verify_commit_graph_error) @@ -2601,10 +2600,6 @@ static int verify_one_commit_graph(struct repository *r, if (verify_commit_graph_error & ~VERIFY_COMMIT_GRAPH_ERROR_HASH) return verify_commit_graph_error; - if (flags & COMMIT_GRAPH_WRITE_PROGRESS) - progress = start_progress(_("Verifying commits in commit graph"), - g->num_commits); - for (i = 0; i < g->num_commits; i++) { struct commit *graph_commit, *odb_commit; struct commit_list *graph_parents, *odb_parents; @@ -2694,7 +2689,6 @@ static int verify_one_commit_graph(struct repository *r, graph_commit->date, odb_commit->date); } - stop_progress(&progress); return verify_commit_graph_error; } @@ -2709,9 +2703,16 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) } for (; g; g = g->base_graph) { - local_error |= verify_one_commit_graph(r, g, flags); + struct progress *progress = NULL; + if (flags & COMMIT_GRAPH_WRITE_PROGRESS) + progress = start_progress(_("Verifying commits in commit graph"), + g->num_commits); + + local_error |= verify_one_commit_graph(r, g, progress); if (flags & COMMIT_GRAPH_VERIFY_SHALLOW) break; + + stop_progress(&progress); } return local_error; From 9281cd07f014263b5385f13b47ff8399282c7cdc Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Fri, 7 Jul 2023 20:31:45 -0400 Subject: [PATCH 6/6] commit-graph.c: avoid duplicated progress output during `verify` When `git commit-graph verify` was taught how to verify commit-graph chains in 3da4b609bb1 (commit-graph: verify chains with --shallow mode, 2019-06-18), it produced one line of progress per layer of the commit-graph chain. $ git.compile commit-graph verify Verifying commits in commit graph: 100% (4356/4356), done. Verifying commits in commit graph: 100% (131912/131912), done. This could be somewhat confusing to users, who may wonder why there are multiple occurrences of "Verifying commits in commit graph". There are likely good arguments on whether or not there should be one line of progress output per commit-graph layer. On the one hand, the existing output shows us verifying each individual layer of the chain. But on the other hand, the fact that a commit-graph may be stored among multiple layers is an implementation detail that the caller need not be aware of. Clarify this by showing a single progress meter regardless of the number of layers in the commit-graph chain. After this patch, the output reflects the logical contents of a commit-graph chain, instead of showing one line of output per commit-graph layer: $ git.compile commit-graph verify Verifying commits in commit graph: 100% (136268/136268), done. Signed-off-by: Taylor Blau Acked-by: Derrick Stolee Signed-off-by: Junio C Hamano --- commit-graph.c | 27 +++++++++++++++++---------- t/t5324-split-commit-graph.sh | 3 ++- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/commit-graph.c b/commit-graph.c index 9e89952831..fda4b6e14d 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -2545,7 +2545,8 @@ static int commit_graph_checksum_valid(struct commit_graph *g) static int verify_one_commit_graph(struct repository *r, struct commit_graph *g, - struct progress *progress) + struct progress *progress, + uint64_t *seen) { uint32_t i, cur_fanout_pos = 0; struct object_id prev_oid, cur_oid; @@ -2606,7 +2607,7 @@ static int verify_one_commit_graph(struct repository *r, timestamp_t max_generation = 0; timestamp_t generation; - display_progress(progress, i + 1); + display_progress(progress, ++(*seen)); oidread(&cur_oid, g->chunk_oid_lookup + g->hash_len * i); graph_commit = lookup_commit(r, &cur_oid); @@ -2695,26 +2696,32 @@ static int verify_one_commit_graph(struct repository *r, int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags) { + struct progress *progress = NULL; int local_error = 0; + uint64_t seen = 0; if (!g) { graph_report("no commit-graph file loaded"); return 1; } - for (; g; g = g->base_graph) { - struct progress *progress = NULL; - if (flags & COMMIT_GRAPH_WRITE_PROGRESS) - progress = start_progress(_("Verifying commits in commit graph"), - g->num_commits); + if (flags & COMMIT_GRAPH_WRITE_PROGRESS) { + uint64_t total = g->num_commits; + if (!(flags & COMMIT_GRAPH_VERIFY_SHALLOW)) + total += g->num_commits_in_base; - local_error |= verify_one_commit_graph(r, g, progress); + progress = start_progress(_("Verifying commits in commit graph"), + total); + } + + for (; g; g = g->base_graph) { + local_error |= verify_one_commit_graph(r, g, progress, &seen); if (flags & COMMIT_GRAPH_VERIFY_SHALLOW) break; - - stop_progress(&progress); } + stop_progress(&progress); + return local_error; } diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 669ddc645f..36c4141e67 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -351,7 +351,8 @@ test_expect_success 'add octopus merge' ' git branch merge/octopus && git commit-graph write --reachable --split && git commit-graph verify --progress 2>err && - test_line_count = 3 err && + test_line_count = 1 err && + grep "Verifying commits in commit graph: 100% (18/18)" err && test_i18ngrep ! warning err && test_line_count = 3 $graphdir/commit-graph-chain '