refactor: decouple git.Repository(ctx) from git.Commit & git.Tree (#38464)

1. Storing "ctx" in a long-living object is wrong
2. Make the commit & tree cacheable (for the future performance
optimization)
3. Also fix some bad designs like `// FIXME: bad design, this field can
be nil if the commit is from "last commit cache"`

ref:
* #33893
This commit is contained in:
wxiaoguang
2026-07-15 17:30:01 +00:00
committed by GitHub
parent ed678b9d45
commit 82edc3da01
115 changed files with 732 additions and 864 deletions
+7 -58
View File
@@ -91,10 +91,9 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
continue
}
assert.NotNil(t, commit)
assert.NotNil(t, commit.Tree)
assert.NotNil(t, commit.Tree.repo)
assert.NotNil(t, commit.TreeID)
tree, err := commit.Tree.SubTree(testCase.Path)
tree, err := commit.SubTree(t.Context(), repo1, testCase.Path)
if err != nil {
assert.NoError(t, err, "Unable to get subtree: %s of commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
@@ -102,9 +101,8 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
assert.NotNil(t, tree, "tree is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
assert.NotNil(t, tree.repo, "repo is nil for testCase CommitID %s in Path %s", testCase.CommitID, testCase.Path)
entries, err := tree.ListEntries()
entries, err := tree.ListEntries(t.Context(), repo1)
if err != nil {
assert.NoError(t, err, "Unable to get entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
// no point trying to do anything else for this test.
@@ -112,7 +110,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
}
// FIXME: Context.TODO() - if graceful has started we should use its Shutdown context otherwise use install signals in TestMain.
commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", commit, testCase.Path)
commitsInfo, treeCommit, err := entries.GetCommitsInfo(t.Context(), "/any/repo-link", repo1, commit, testCase.Path)
assert.NoError(t, err, "Unable to get commit information for entries of subtree: %s in commit: %s from testcase due to error: %v", testCase.Path, testCase.CommitID, err)
if err != nil {
t.FailNow()
@@ -127,7 +125,7 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
continue
}
assert.Equal(t, expectedInfo.CommitID, commit.ID.String())
assert.Equal(t, expectedInfo.Size, entry.Size(), entry.Name())
assert.Equal(t, expectedInfo.Size, entry.GetSize(t.Context(), repo1), entry.Name())
}
}
}
@@ -155,9 +153,9 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
t.Run("NonExistingSubmoduleAsNil", func(t *testing.T) {
commit, err := bareRepo1.GetCommit("HEAD")
require.NoError(t, err)
treeEntry, err := commit.GetTreeEntryByPath("file1.txt")
treeEntry, err := commit.GetTreeEntryByPath(t.Context(), bareRepo1, "file1.txt")
require.NoError(t, err)
cisf, err := GetCommitInfoSubmoduleFile("/any/repo-link", "file1.txt", commit, treeEntry.ID)
cisf, err := GetCommitInfoSubmoduleFile(t.Context(), "/any/repo-link", "file1.txt", bareRepo1, commit, treeEntry.ID)
require.NoError(t, err)
assert.Equal(t, &CommitSubmoduleFile{
repoLink: "/any/repo-link",
@@ -169,52 +167,3 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
assert.Nil(t, cisf.SubmoduleWebLinkTree(t.Context()))
})
}
func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
type benchmarkType struct {
url string
name string
}
benchmarks := []benchmarkType{
{url: "https://github.com/go-gitea/gitea.git", name: "gitea"},
{url: "https://github.com/ethantkoenig/manyfiles.git", name: "manyfiles"},
{url: "https://github.com/moby/moby.git", name: "moby"},
{url: "https://github.com/golang/go.git", name: "go"},
{url: "https://github.com/torvalds/linux.git", name: "linux"},
}
doBenchmark := func(benchmark benchmarkType) {
var commit *Commit
var entries Entries
var repo *Repository
repoPath, err := cloneRepo(b, benchmark.url)
if err != nil {
b.Fatal(err)
}
if repo, err = OpenRepository(b.Context(), repoPath); err != nil {
b.Fatal(err)
}
defer repo.Close()
if commit, err = repo.GetBranchCommit("master"); err != nil {
b.Fatal(err)
} else if entries, err = commit.Tree.ListEntries(); err != nil {
b.Fatal(err)
}
b.ResetTimer()
b.Run(benchmark.name, func(b *testing.B) {
for b.Loop() {
_, _, err := entries.GetCommitsInfo(b.Context(), "/any/repo-link", commit, "")
if err != nil {
b.Fatal(err)
}
}
})
}
for _, benchmark := range benchmarks {
doBenchmark(benchmark)
}
}