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