fork of go-git with some jj specific features
1package git
2
3import (
4 "os"
5 "testing"
6 "time"
7
8 "github.com/go-git/go-git/v5/plumbing"
9 "github.com/go-git/go-git/v5/plumbing/cache"
10 "github.com/go-git/go-git/v5/plumbing/format/packfile"
11 "github.com/go-git/go-git/v5/plumbing/object"
12 "github.com/go-git/go-git/v5/storage/filesystem"
13 "github.com/go-git/go-git/v5/storage/memory"
14
15 "github.com/go-git/go-billy/v5"
16 "github.com/go-git/go-billy/v5/memfs"
17 "github.com/go-git/go-billy/v5/osfs"
18 "github.com/go-git/go-billy/v5/util"
19 fixtures "github.com/go-git/go-git-fixtures/v4"
20 . "gopkg.in/check.v1"
21)
22
23func Test(t *testing.T) { TestingT(t) }
24
25type BaseSuite struct {
26 fixtures.Suite
27 Repository *Repository
28
29 cache map[string]*Repository
30}
31
32func (s *BaseSuite) SetUpSuite(c *C) {
33 s.buildBasicRepository(c)
34
35 s.cache = make(map[string]*Repository)
36}
37
38func (s *BaseSuite) TearDownSuite(c *C) {
39 s.Suite.TearDownSuite(c)
40}
41
42func (s *BaseSuite) buildBasicRepository(_ *C) {
43 f := fixtures.Basic().One()
44 s.Repository = s.NewRepository(f)
45}
46
47// NewRepository returns a new repository using the .git folder, if the fixture
48// is tagged as worktree the filesystem from fixture is used, otherwise a new
49// memfs filesystem is used as worktree.
50func (s *BaseSuite) NewRepository(f *fixtures.Fixture) *Repository {
51 var worktree, dotgit billy.Filesystem
52 if f.Is("worktree") {
53 r, err := PlainOpen(f.Worktree().Root())
54 if err != nil {
55 panic(err)
56 }
57
58 return r
59 }
60
61 dotgit = f.DotGit()
62 worktree = memfs.New()
63
64 st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault())
65
66 r, err := Open(st, worktree)
67 if err != nil {
68 panic(err)
69 }
70
71 return r
72}
73
74// NewRepositoryWithEmptyWorktree returns a new repository using the .git folder
75// from the fixture but without a empty memfs worktree, the index and the
76// modules are deleted from the .git folder.
77func (s *BaseSuite) NewRepositoryWithEmptyWorktree(f *fixtures.Fixture) *Repository {
78 dotgit := f.DotGit()
79 err := dotgit.Remove("index")
80 if err != nil {
81 panic(err)
82 }
83
84 err = util.RemoveAll(dotgit, "modules")
85 if err != nil {
86 panic(err)
87 }
88
89 worktree := memfs.New()
90
91 st := filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault())
92
93 r, err := Open(st, worktree)
94 if err != nil {
95 panic(err)
96 }
97
98 return r
99
100}
101
102func (s *BaseSuite) NewRepositoryFromPackfile(f *fixtures.Fixture) *Repository {
103 h := f.PackfileHash
104 if r, ok := s.cache[h]; ok {
105 return r
106 }
107
108 storer := memory.NewStorage()
109 p := f.Packfile()
110 defer func() { _ = p.Close() }()
111
112 if err := packfile.UpdateObjectStorage(storer, p); err != nil {
113 panic(err)
114 }
115
116 err := storer.SetReference(plumbing.NewHashReference(plumbing.HEAD, plumbing.NewHash(f.Head)))
117 if err != nil {
118 panic(err)
119 }
120
121 r, err := Open(storer, memfs.New())
122 if err != nil {
123 panic(err)
124 }
125
126 s.cache[h] = r
127 return r
128}
129
130func (s *BaseSuite) GetBasicLocalRepositoryURL() string {
131 fixture := fixtures.Basic().One()
132 return s.GetLocalRepositoryURL(fixture)
133}
134
135func (s *BaseSuite) GetLocalRepositoryURL(f *fixtures.Fixture) string {
136 return f.DotGit().Root()
137}
138
139func (s *BaseSuite) TemporalHomeDir() (path string, clean func()) {
140 home, err := os.UserHomeDir()
141 if err != nil {
142 panic(err)
143 }
144
145 fs := osfs.New(home)
146 relPath, err := util.TempDir(fs, "", "")
147 if err != nil {
148 panic(err)
149 }
150
151 path = fs.Join(fs.Root(), relPath)
152 clean = func() {
153 _ = util.RemoveAll(fs, relPath)
154 }
155
156 return
157}
158
159func (s *BaseSuite) TemporalFilesystem(c *C) (fs billy.Filesystem) {
160 fs = osfs.New(c.MkDir())
161 path, err := util.TempDir(fs, "", "")
162 if err != nil {
163 panic(err)
164 }
165
166 fs, err = fs.Chroot(path)
167 if err != nil {
168 panic(err)
169 }
170
171 return
172}
173
174type SuiteCommon struct{}
175
176var _ = Suite(&SuiteCommon{})
177
178var countLinesTests = [...]struct {
179 i string // the string we want to count lines from
180 e int // the expected number of lines in i
181}{
182 {"", 0},
183 {"a", 1},
184 {"a\n", 1},
185 {"a\nb", 2},
186 {"a\nb\n", 2},
187 {"a\nb\nc", 3},
188 {"a\nb\nc\n", 3},
189 {"a\n\n\nb\n", 4},
190 {"first line\n\tsecond line\nthird line\n", 3},
191}
192
193func (s *SuiteCommon) TestCountLines(c *C) {
194 for i, t := range countLinesTests {
195 o := countLines(t.i)
196 c.Assert(o, Equals, t.e, Commentf("subtest %d, input=%q", i, t.i))
197 }
198}
199
200func AssertReferences(c *C, r *Repository, expected map[string]string) {
201 for name, target := range expected {
202 expected := plumbing.NewReferenceFromStrings(name, target)
203
204 obtained, err := r.Reference(expected.Name(), true)
205 c.Assert(err, IsNil)
206
207 c.Assert(obtained, DeepEquals, expected)
208 }
209}
210
211func AssertReferencesMissing(c *C, r *Repository, expected []string) {
212 for _, name := range expected {
213 _, err := r.Reference(plumbing.ReferenceName(name), false)
214 c.Assert(err, NotNil)
215 c.Assert(err, Equals, plumbing.ErrReferenceNotFound)
216 }
217}
218
219func CommitNewFile(c *C, repo *Repository, fileName string) plumbing.Hash {
220 wt, err := repo.Worktree()
221 c.Assert(err, IsNil)
222
223 fd, err := wt.Filesystem.Create(fileName)
224 c.Assert(err, IsNil)
225
226 _, err = fd.Write([]byte("# test file"))
227 c.Assert(err, IsNil)
228
229 err = fd.Close()
230 c.Assert(err, IsNil)
231
232 _, err = wt.Add(fileName)
233 c.Assert(err, IsNil)
234
235 sha, err := wt.Commit("test commit", &CommitOptions{
236 Author: &object.Signature{
237 Name: "test",
238 Email: "test@example.com",
239 When: time.Now(),
240 },
241 Committer: &object.Signature{
242 Name: "test",
243 Email: "test@example.com",
244 When: time.Now(),
245 },
246 })
247 c.Assert(err, IsNil)
248
249 return sha
250}