1package git
2
3import (
4 "context"
5 "path/filepath"
6 "testing"
7
8 "github.com/go-git/go-billy/v5/memfs"
9 "github.com/go-git/go-git/v5/config"
10 "github.com/go-git/go-git/v5/plumbing"
11 "github.com/go-git/go-git/v5/storage/memory"
12
13 fixtures "github.com/go-git/go-git-fixtures/v4"
14 . "gopkg.in/check.v1"
15)
16
17type SubmoduleSuite struct {
18 BaseSuite
19 Worktree *Worktree
20 clean func()
21}
22
23var _ = Suite(&SubmoduleSuite{})
24
25func (s *SubmoduleSuite) SetUpTest(c *C) {
26 path := fixtures.ByTag("submodule").One().Worktree().Root()
27
28 var dir string
29 dir, s.clean = s.TemporalDir()
30
31 r, err := PlainClone(filepath.Join(dir, "worktree"), false, &CloneOptions{
32 URL: path,
33 })
34
35 c.Assert(err, IsNil)
36
37 s.Repository = r
38 s.Worktree, err = r.Worktree()
39 c.Assert(err, IsNil)
40}
41
42func (s *SubmoduleSuite) TearDownTest(_ *C) {
43 s.clean()
44}
45
46func (s *SubmoduleSuite) TestInit(c *C) {
47 sm, err := s.Worktree.Submodule("basic")
48 c.Assert(err, IsNil)
49
50 c.Assert(sm.initialized, Equals, false)
51 err = sm.Init()
52 c.Assert(err, IsNil)
53
54 c.Assert(sm.initialized, Equals, true)
55
56 cfg, err := s.Repository.Config()
57 c.Assert(err, IsNil)
58
59 c.Assert(cfg.Submodules, HasLen, 1)
60 c.Assert(cfg.Submodules["basic"], NotNil)
61
62 status, err := sm.Status()
63 c.Assert(err, IsNil)
64 c.Assert(status.IsClean(), Equals, false)
65}
66
67func (s *SubmoduleSuite) TestUpdate(c *C) {
68 if testing.Short() {
69 c.Skip("skipping test in short mode.")
70 }
71
72 sm, err := s.Worktree.Submodule("basic")
73 c.Assert(err, IsNil)
74
75 err = sm.Update(&SubmoduleUpdateOptions{
76 Init: true,
77 })
78
79 c.Assert(err, IsNil)
80
81 r, err := sm.Repository()
82 c.Assert(err, IsNil)
83
84 ref, err := r.Reference(plumbing.HEAD, true)
85 c.Assert(err, IsNil)
86 c.Assert(ref.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
87
88 status, err := sm.Status()
89 c.Assert(err, IsNil)
90 c.Assert(status.IsClean(), Equals, true)
91}
92
93func (s *SubmoduleSuite) TestRepositoryWithoutInit(c *C) {
94 sm, err := s.Worktree.Submodule("basic")
95 c.Assert(err, IsNil)
96
97 r, err := sm.Repository()
98 c.Assert(err, Equals, ErrSubmoduleNotInitialized)
99 c.Assert(r, IsNil)
100}
101
102func (s *SubmoduleSuite) TestUpdateWithoutInit(c *C) {
103 sm, err := s.Worktree.Submodule("basic")
104 c.Assert(err, IsNil)
105
106 err = sm.Update(&SubmoduleUpdateOptions{})
107 c.Assert(err, Equals, ErrSubmoduleNotInitialized)
108}
109
110func (s *SubmoduleSuite) TestUpdateWithNotFetch(c *C) {
111 sm, err := s.Worktree.Submodule("basic")
112 c.Assert(err, IsNil)
113
114 err = sm.Update(&SubmoduleUpdateOptions{
115 Init: true,
116 NoFetch: true,
117 })
118
119 // Since we are not fetching, the object is not there
120 c.Assert(err, Equals, plumbing.ErrObjectNotFound)
121}
122
123func (s *SubmoduleSuite) TestUpdateWithRecursion(c *C) {
124 if testing.Short() {
125 c.Skip("skipping test in short mode.")
126 }
127
128 sm, err := s.Worktree.Submodule("itself")
129 c.Assert(err, IsNil)
130
131 err = sm.Update(&SubmoduleUpdateOptions{
132 Init: true,
133 RecurseSubmodules: 2,
134 })
135
136 c.Assert(err, IsNil)
137
138 fs := s.Worktree.Filesystem
139 _, err = fs.Stat(fs.Join("itself", "basic", "LICENSE"))
140 c.Assert(err, IsNil)
141}
142
143func (s *SubmoduleSuite) TestUpdateWithInitAndUpdate(c *C) {
144 if testing.Short() {
145 c.Skip("skipping test in short mode.")
146 }
147
148 sm, err := s.Worktree.Submodule("basic")
149 c.Assert(err, IsNil)
150
151 err = sm.Update(&SubmoduleUpdateOptions{
152 Init: true,
153 })
154 c.Assert(err, IsNil)
155
156 idx, err := s.Repository.Storer.Index()
157 c.Assert(err, IsNil)
158
159 for i, e := range idx.Entries {
160 if e.Name == "basic" {
161 e.Hash = plumbing.NewHash("b029517f6300c2da0f4b651b8642506cd6aaf45d")
162 }
163
164 idx.Entries[i] = e
165 }
166
167 err = s.Repository.Storer.SetIndex(idx)
168 c.Assert(err, IsNil)
169
170 err = sm.Update(&SubmoduleUpdateOptions{})
171 c.Assert(err, IsNil)
172
173 r, err := sm.Repository()
174 c.Assert(err, IsNil)
175
176 ref, err := r.Reference(plumbing.HEAD, true)
177 c.Assert(err, IsNil)
178 c.Assert(ref.Hash().String(), Equals, "b029517f6300c2da0f4b651b8642506cd6aaf45d")
179
180}
181
182func (s *SubmoduleSuite) TestSubmodulesInit(c *C) {
183 sm, err := s.Worktree.Submodules()
184 c.Assert(err, IsNil)
185
186 err = sm.Init()
187 c.Assert(err, IsNil)
188
189 sm, err = s.Worktree.Submodules()
190 c.Assert(err, IsNil)
191
192 for _, m := range sm {
193 c.Assert(m.initialized, Equals, true)
194 }
195}
196
197func (s *SubmoduleSuite) TestGitSubmodulesSymlink(c *C) {
198 f, err := s.Worktree.Filesystem.Create("badfile")
199 c.Assert(err, IsNil)
200 defer func() { _ = f.Close() }()
201
202 err = s.Worktree.Filesystem.Remove(gitmodulesFile)
203 c.Assert(err, IsNil)
204
205 err = s.Worktree.Filesystem.Symlink("badfile", gitmodulesFile)
206 c.Assert(err, IsNil)
207
208 _, err = s.Worktree.Submodules()
209 c.Assert(err, Equals, ErrGitModulesSymlink)
210}
211
212func (s *SubmoduleSuite) TestSubmodulesStatus(c *C) {
213 sm, err := s.Worktree.Submodules()
214 c.Assert(err, IsNil)
215
216 status, err := sm.Status()
217 c.Assert(err, IsNil)
218 c.Assert(status, HasLen, 2)
219}
220
221func (s *SubmoduleSuite) TestSubmodulesUpdateContext(c *C) {
222 if testing.Short() {
223 c.Skip("skipping test in short mode.")
224 }
225
226 sm, err := s.Worktree.Submodules()
227 c.Assert(err, IsNil)
228
229 ctx, cancel := context.WithCancel(context.Background())
230 cancel()
231
232 err = sm.UpdateContext(ctx, &SubmoduleUpdateOptions{Init: true})
233 c.Assert(err, NotNil)
234}
235
236func (s *SubmoduleSuite) TestSubmodulesFetchDepth(c *C) {
237 if testing.Short() {
238 c.Skip("skipping test in short mode.")
239 }
240
241 sm, err := s.Worktree.Submodule("basic")
242 c.Assert(err, IsNil)
243
244 err = sm.Update(&SubmoduleUpdateOptions{
245 Init: true,
246 Depth: 1,
247 })
248 c.Assert(err, IsNil)
249
250 r, err := sm.Repository()
251 c.Assert(err, IsNil)
252
253 lr, err := r.Log(&LogOptions{})
254 c.Assert(err, IsNil)
255
256 commitCount := 0
257 for _, err := lr.Next(); err == nil; _, err = lr.Next() {
258 commitCount++
259 }
260 c.Assert(err, IsNil)
261
262 c.Assert(commitCount, Equals, 1)
263}
264
265func (s *SubmoduleSuite) TestSubmoduleParseScp(c *C) {
266 repo := &Repository{
267 Storer: memory.NewStorage(),
268 wt: memfs.New(),
269 }
270 worktree := &Worktree{
271 Filesystem: memfs.New(),
272 r: repo,
273 }
274 submodule := &Submodule{
275 initialized: true,
276 c: nil,
277 w: worktree,
278 }
279
280 submodule.c = &config.Submodule{
281 URL: "git@github.com:username/submodule_repo",
282 }
283
284 _, err := submodule.Repository()
285 c.Assert(err, IsNil)
286}