1package v2_test
2
3import (
4 "os"
5 "testing"
6
7 "github.com/go-git/go-billy/v5"
8 "github.com/go-git/go-billy/v5/util"
9 "github.com/go-git/go-git/v5/plumbing"
10 "github.com/go-git/go-git/v5/plumbing/cache"
11 commitgraph "github.com/go-git/go-git/v5/plumbing/format/commitgraph/v2"
12 "github.com/go-git/go-git/v5/plumbing/format/packfile"
13 "github.com/go-git/go-git/v5/plumbing/object"
14 "github.com/go-git/go-git/v5/storage/filesystem"
15 "github.com/stretchr/testify/suite"
16
17 fixtures "github.com/go-git/go-git-fixtures/v4"
18)
19
20type CommitgraphFixtureSuite struct {
21 fixtures.Suite
22}
23
24type CommitgraphSuite struct {
25 suite.Suite
26 CommitgraphFixtureSuite
27}
28
29func TestCommitgraphSuite(t *testing.T) {
30 suite.Run(t, new(CommitgraphSuite))
31}
32
33func testReadIndex(s *CommitgraphSuite, fs billy.Filesystem, path string) commitgraph.Index {
34 reader, err := fs.Open(path)
35 s.NoError(err)
36 index, err := commitgraph.OpenFileIndex(reader)
37 s.NoError(err)
38 s.NotNil(index)
39 return index
40}
41
42func testDecodeHelper(s *CommitgraphSuite, index commitgraph.Index) {
43 // Root commit
44 nodeIndex, err := index.GetIndexByHash(plumbing.NewHash("347c91919944a68e9413581a1bc15519550a3afe"))
45 s.NoError(err)
46 commitData, err := index.GetCommitDataByIndex(nodeIndex)
47 s.NoError(err)
48 s.Len(commitData.ParentIndexes, 0)
49 s.Len(commitData.ParentHashes, 0)
50
51 // Regular commit
52 nodeIndex, err = index.GetIndexByHash(plumbing.NewHash("e713b52d7e13807e87a002e812041f248db3f643"))
53 s.NoError(err)
54 commitData, err = index.GetCommitDataByIndex(nodeIndex)
55 s.NoError(err)
56 s.Len(commitData.ParentIndexes, 1)
57 s.Len(commitData.ParentHashes, 1)
58 s.Equal("347c91919944a68e9413581a1bc15519550a3afe", commitData.ParentHashes[0].String())
59
60 // Merge commit
61 nodeIndex, err = index.GetIndexByHash(plumbing.NewHash("b29328491a0682c259bcce28741eac71f3499f7d"))
62 s.NoError(err)
63 commitData, err = index.GetCommitDataByIndex(nodeIndex)
64 s.NoError(err)
65 s.Len(commitData.ParentIndexes, 2)
66 s.Len(commitData.ParentHashes, 2)
67 s.Equal("e713b52d7e13807e87a002e812041f248db3f643", commitData.ParentHashes[0].String())
68 s.Equal("03d2c021ff68954cf3ef0a36825e194a4b98f981", commitData.ParentHashes[1].String())
69
70 // Octopus merge commit
71 nodeIndex, err = index.GetIndexByHash(plumbing.NewHash("6f6c5d2be7852c782be1dd13e36496dd7ad39560"))
72 s.NoError(err)
73 commitData, err = index.GetCommitDataByIndex(nodeIndex)
74 s.NoError(err)
75 s.Len(commitData.ParentIndexes, 3)
76 s.Len(commitData.ParentHashes, 3)
77 s.Equal("ce275064ad67d51e99f026084e20827901a8361c", commitData.ParentHashes[0].String())
78 s.Equal("bb13916df33ed23004c3ce9ed3b8487528e655c1", commitData.ParentHashes[1].String())
79 s.Equal("a45273fe2d63300e1962a9e26a6b15c276cd7082", commitData.ParentHashes[2].String())
80
81 // Check all hashes
82 hashes := index.Hashes()
83 s.Len(hashes, 11)
84 s.Equal("03d2c021ff68954cf3ef0a36825e194a4b98f981", hashes[0].String())
85 s.Equal("e713b52d7e13807e87a002e812041f248db3f643", hashes[10].String())
86}
87
88func (s *CommitgraphSuite) TestDecodeMultiChain() {
89 for _, f := range fixtures.ByTag("commit-graph-chain-2") {
90 dotgit := f.DotGit()
91 index, err := commitgraph.OpenChainOrFileIndex(dotgit)
92 s.NoError(err)
93 defer index.Close()
94 storer := filesystem.NewStorage(f.DotGit(), cache.NewObjectLRUDefault())
95 p := f.Packfile()
96 defer p.Close()
97 packfile.UpdateObjectStorage(storer, p)
98
99 for idx, hash := range index.Hashes() {
100 idx2, err := index.GetIndexByHash(hash)
101 s.NoError(err)
102 s.Equal(uint32(idx), idx2)
103 hash2, err := index.GetHashByIndex(idx2)
104 s.NoError(err)
105 s.Equal(hash.String(), hash2.String())
106
107 commitData, err := index.GetCommitDataByIndex(uint32(idx))
108 s.NoError(err)
109 commit, err := object.GetCommit(storer, hash)
110 s.NoError(err)
111
112 for i, parent := range commit.ParentHashes {
113 s.Equal(hash.String()+":"+commitData.ParentHashes[i].String(), hash.String()+":"+parent.String())
114 }
115 }
116 }
117}
118
119func (s *CommitgraphSuite) TestDecode() {
120 for _, f := range fixtures.ByTag("commit-graph") {
121 dotgit := f.DotGit()
122 index := testReadIndex(s, dotgit, dotgit.Join("objects", "info", "commit-graph"))
123 defer index.Close()
124 testDecodeHelper(s, index)
125 }
126}
127
128func (s *CommitgraphSuite) TestDecodeChain() {
129 for _, f := range fixtures.ByTag("commit-graph") {
130 dotgit := f.DotGit()
131 index, err := commitgraph.OpenChainOrFileIndex(dotgit)
132 s.NoError(err)
133 defer index.Close()
134 testDecodeHelper(s, index)
135 }
136
137 for _, f := range fixtures.ByTag("commit-graph-chain") {
138 dotgit := f.DotGit()
139 index, err := commitgraph.OpenChainOrFileIndex(dotgit)
140 s.NoError(err)
141 defer index.Close()
142 testDecodeHelper(s, index)
143 }
144}
145
146func (s *CommitgraphSuite) TestReencode() {
147 for _, f := range fixtures.ByTag("commit-graph") {
148 dotgit := f.DotGit()
149
150 reader, err := dotgit.Open(dotgit.Join("objects", "info", "commit-graph"))
151 s.NoError(err)
152 defer reader.Close()
153 index, err := commitgraph.OpenFileIndex(reader)
154 s.NoError(err)
155 defer index.Close()
156
157 writer, err := util.TempFile(dotgit, "", "commit-graph")
158 s.NoError(err)
159 tmpName := writer.Name()
160 defer os.Remove(tmpName)
161
162 encoder := commitgraph.NewEncoder(writer)
163 err = encoder.Encode(index)
164 s.NoError(err)
165 writer.Close()
166
167 tmpIndex := testReadIndex(s, dotgit, tmpName)
168 defer tmpIndex.Close()
169 testDecodeHelper(s, tmpIndex)
170 }
171}
172
173func (s *CommitgraphSuite) TestReencodeInMemory() {
174 for _, f := range fixtures.ByTag("commit-graph") {
175 dotgit := f.DotGit()
176
177 reader, err := dotgit.Open(dotgit.Join("objects", "info", "commit-graph"))
178 s.NoError(err)
179 index, err := commitgraph.OpenFileIndex(reader)
180 s.NoError(err)
181
182 memoryIndex := commitgraph.NewMemoryIndex()
183 defer memoryIndex.Close()
184 for i, hash := range index.Hashes() {
185 commitData, err := index.GetCommitDataByIndex(uint32(i))
186 s.NoError(err)
187 memoryIndex.Add(hash, commitData)
188 }
189 index.Close()
190
191 writer, err := util.TempFile(dotgit, "", "commit-graph")
192 s.NoError(err)
193 tmpName := writer.Name()
194 defer os.Remove(tmpName)
195
196 encoder := commitgraph.NewEncoder(writer)
197 err = encoder.Encode(memoryIndex)
198 s.NoError(err)
199 writer.Close()
200
201 tmpIndex := testReadIndex(s, dotgit, tmpName)
202 defer tmpIndex.Close()
203 testDecodeHelper(s, tmpIndex)
204 }
205}