diff options
-rw-r--r-- | Documentation/git.txt | 10 | ||||
-rw-r--r-- | commit-graph.c | 6 | ||||
-rw-r--r-- | commit-graph.h | 6 | ||||
-rwxr-xr-x | t/t5318-commit-graph.sh | 21 |
4 files changed, 42 insertions, 1 deletions
diff --git a/Documentation/git.txt b/Documentation/git.txt index 11228956cd..3bac24cf8a 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -911,6 +911,16 @@ for full details. should not normally need to set this to `0`, but it may be useful when trying to salvage data from a corrupted repository. +`GIT_COMMIT_GRAPH_PARANOIA`:: + When loading a commit object from the commit-graph, Git performs an + existence check on the object in the object database. This is done to + avoid issues with stale commit-graphs that contain references to + already-deleted commits, but comes with a performance penalty. ++ +The default is "true", which enables the aforementioned behavior. +Setting this to "false" disables the existence check. This can lead to +a performance improvement at the cost of consistency. + `GIT_ALLOW_PROTOCOL`:: If set to a colon-separated list of protocols, behave as if `protocol.allow` is set to `never`, and each of the listed diff --git a/commit-graph.c b/commit-graph.c index 0aa1640d15..b37fdcb214 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -907,14 +907,18 @@ int repo_find_commit_pos_in_graph(struct repository *r, struct commit *c, struct commit *lookup_commit_in_graph(struct repository *repo, const struct object_id *id) { + static int commit_graph_paranoia = -1; struct commit *commit; uint32_t pos; + if (commit_graph_paranoia == -1) + commit_graph_paranoia = git_env_bool(GIT_COMMIT_GRAPH_PARANOIA, 1); + if (!prepare_commit_graph(repo)) return NULL; if (!search_commit_pos_in_graph(id, repo->objects->commit_graph, &pos)) return NULL; - if (!has_object(repo, id, 0)) + if (commit_graph_paranoia && !has_object(repo, id, 0)) return NULL; commit = lookup_commit(repo, id); diff --git a/commit-graph.h b/commit-graph.h index 5e534f0fcc..3c86e8b05f 100644 --- a/commit-graph.h +++ b/commit-graph.h @@ -9,6 +9,12 @@ #define GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS "GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS" /* + * This environment variable controls whether commits looked up via the + * commit graph will be double checked to exist in the object database. + */ +#define GIT_COMMIT_GRAPH_PARANOIA "GIT_COMMIT_GRAPH_PARANOIA" + +/* * This method is only used to enhance coverage of the commit-graph * feature in the test suite with the GIT_TEST_COMMIT_GRAPH and * GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS environment variables. Do not diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 4df76173a8..087e6ac3b8 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -815,4 +815,25 @@ test_expect_success 'overflow during generation version upgrade' ' ) ' +test_expect_success 'stale commit cannot be parsed when given directly' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit B && + git commit-graph write --reachable && + + oid=$(git rev-parse B) && + rm .git/objects/"$(test_oid_to_path "$oid")" && + + # Verify that it is possible to read the commit from the + # commit graph when not being paranoid, ... + GIT_COMMIT_GRAPH_PARANOIA=false git rev-list B && + # ... but parsing the commit when double checking that + # it actually exists in the object database should fail. + test_must_fail git rev-list -1 B + ) +' + test_done |