diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-07-08 13:09:22 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2022-07-15 16:15:09 +0300 |
commit | b995e4ec151539d376e4da51bc1fa6c528c37682 (patch) | |
tree | f2324caed4a106a261d6bdd6f9d04bdbefbf3afd | |
parent | 8a3e161cec19d453fb1ff8f34bcffeeb79c693a9 (diff) |
housekeeping: Demonstrate commit-graphs referencing pruned commits
Add a test to demonstrate a shortcoming we have with commit-graphs that
reference pruned commits: even though we're pruning commits, we don't
update the commit-graphs accordingly to drop references to any such
pruned commits.
-rw-r--r-- | internal/git/housekeeping/optimize_repository_test.go | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/internal/git/housekeeping/optimize_repository_test.go b/internal/git/housekeeping/optimize_repository_test.go index 99c344467..1ca66c568 100644 --- a/internal/git/housekeeping/optimize_repository_test.go +++ b/internal/git/housekeeping/optimize_repository_test.go @@ -1111,4 +1111,48 @@ func TestWriteCommitGraphIfNeeded(t *testing.T) { gittest.Exec(t, cfg, "-C", repoPath, "commit-graph", "verify") }) } + + t.Run("commit-graph with pruned objects", func(t *testing.T) { + repoProto, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0]) + repo := localrepo.NewTestRepo(t, cfg, repoProto) + + // Write a first commit-graph that contains the root commit, only. + rootCommitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithBranch("main")) + gittest.Exec(t, cfg, "-C", repoPath, "commit-graph", "write", "--reachable", "--split", "--changed-paths") + + // Write a second, incremental commit-graph that contains a commit we're about to + // make unreachable and then prune. + unreachableCommitID := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(rootCommitID), gittest.WithBranch("main")) + gittest.Exec(t, cfg, "-C", repoPath, "commit-graph", "write", "--reachable", "--split=no-merge", "--changed-paths") + + // Reset the "main" branch back to the initial root commit ID and prune the now + // unreachable second commit. + gittest.Exec(t, cfg, "-C", repoPath, "update-ref", "refs/heads/main", rootCommitID.String()) + gittest.Exec(t, cfg, "-C", repoPath, "prune", "--expire", "now") + + // The commit-graph chain now refers to the pruned commit, and git-commit-graph(1) + // should complain about that. + var stderr bytes.Buffer + verifyCmd := gittest.NewCommand(t, cfg, "-C", repoPath, "commit-graph", "verify") + verifyCmd.Stderr = &stderr + require.EqualError(t, verifyCmd.Run(), "exit status 1") + require.Equal(t, stderr.String(), fmt.Sprintf("error: Could not read %[1]s\nfailed to parse commit %[1]s from object database for commit-graph\n", unreachableCommitID)) + + // Write the commit-graph and pretend that objects have been rewritten. Ideally, + // this causes us to fix up the broken commit-graph to not contain references to the + // pruned commit anymore. + didWrite, writeCommitGraphCfg, err := writeCommitGraphIfNeeded(ctx, repo, true) + require.NoError(t, err) + require.True(t, didWrite) + require.Equal(t, WriteCommitGraphConfig{}, writeCommitGraphCfg) + + // But right now, this is not the case. This is caused by the fact that Git will + // only do an incremental update and thus not rewrite all parts of the commit-graph + // chain. + stderr.Reset() + verifyCmd = gittest.NewCommand(t, cfg, "-C", repoPath, "commit-graph", "verify") + verifyCmd.Stderr = &stderr + require.EqualError(t, verifyCmd.Run(), "exit status 1") + require.Equal(t, stderr.String(), fmt.Sprintf("error: Could not read %[1]s\nfailed to parse commit %[1]s from object database for commit-graph\n", unreachableCommitID)) + }) } |