1package git
2
3import (
4 "os"
5 "testing"
6
7 "github.com/go-git/go-git/v5/plumbing"
8 "github.com/go-git/go-git/v5/plumbing/cache"
9 "github.com/go-git/go-git/v5/plumbing/format/packfile"
10 "github.com/go-git/go-git/v5/plumbing/transport"
11 "github.com/go-git/go-git/v5/storage/filesystem"
12 "github.com/go-git/go-git/v5/storage/memory"
13
14 "github.com/go-git/go-billy/v5"
15 "github.com/go-git/go-billy/v5/memfs"
16 "github.com/go-git/go-billy/v5/osfs"
17 "github.com/go-git/go-billy/v5/util"
18 fixtures "github.com/go-git/go-git-fixtures/v4"
19 . "gopkg.in/check.v1"
20)
21
22func Test(t *testing.T) { TestingT(t) }
23
24type BaseSuite struct {
25 fixtures.Suite
26 Repository *Repository
27
28 backupProtocol transport.Transport
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 *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 p.Close()
111
112 if err := packfile.UpdateObjectStorage(storer, p); err != nil {
113 panic(err)
114 }
115
116 storer.SetReference(plumbing.NewHashReference(plumbing.HEAD, plumbing.NewHash(f.Head)))
117
118 r, err := Open(storer, memfs.New())
119 if err != nil {
120 panic(err)
121 }
122
123 s.cache[h] = r
124 return r
125}
126
127func (s *BaseSuite) GetBasicLocalRepositoryURL() string {
128 fixture := fixtures.Basic().One()
129 return s.GetLocalRepositoryURL(fixture)
130}
131
132func (s *BaseSuite) GetLocalRepositoryURL(f *fixtures.Fixture) string {
133 return f.DotGit().Root()
134}
135
136func (s *BaseSuite) TemporalDir() (path string, clean func()) {
137 fs := osfs.New(os.TempDir())
138 path, err := util.TempDir(fs, "", "")
139 if err != nil {
140 panic(err)
141 }
142
143 return fs.Join(fs.Root(), path), func() {
144 util.RemoveAll(fs, path)
145 }
146}
147
148func (s *BaseSuite) TemporalFilesystem() (fs billy.Filesystem, clean func()) {
149 fs = osfs.New(os.TempDir())
150 path, err := util.TempDir(fs, "", "")
151 if err != nil {
152 panic(err)
153 }
154
155 fs, err = fs.Chroot(path)
156 if err != nil {
157 panic(err)
158 }
159
160 return fs, func() {
161 util.RemoveAll(fs, path)
162 }
163}
164
165type SuiteCommon struct{}
166
167var _ = Suite(&SuiteCommon{})
168
169var countLinesTests = [...]struct {
170 i string // the string we want to count lines from
171 e int // the expected number of lines in i
172}{
173 {"", 0},
174 {"a", 1},
175 {"a\n", 1},
176 {"a\nb", 2},
177 {"a\nb\n", 2},
178 {"a\nb\nc", 3},
179 {"a\nb\nc\n", 3},
180 {"a\n\n\nb\n", 4},
181 {"first line\n\tsecond line\nthird line\n", 3},
182}
183
184func (s *SuiteCommon) TestCountLines(c *C) {
185 for i, t := range countLinesTests {
186 o := countLines(t.i)
187 c.Assert(o, Equals, t.e, Commentf("subtest %d, input=%q", i, t.i))
188 }
189}
190
191func AssertReferences(c *C, r *Repository, expected map[string]string) {
192 for name, target := range expected {
193 expected := plumbing.NewReferenceFromStrings(name, target)
194
195 obtained, err := r.Reference(expected.Name(), true)
196 c.Assert(err, IsNil)
197
198 c.Assert(obtained, DeepEquals, expected)
199 }
200}