git submodule: add submodules with git add -f <path>
[git] / t / t7400-submodule-basic.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2007 Lars Hjemli
4 #
5
6 test_description='Basic porcelain support for submodules
7
8 This test tries to verify basic sanity of the init, update and status
9 subcommands of git submodule.
10 '
11
12 . ./test-lib.sh
13
14 test_expect_success 'setup - initial commit' '
15         >t &&
16         git add t &&
17         git commit -m "initial commit" &&
18         git branch initial
19 '
20
21 test_expect_success 'setup - repository in init subdirectory' '
22         mkdir init &&
23         (
24                 cd init &&
25                 git init &&
26                 echo a >a &&
27                 git add a &&
28                 git commit -m "submodule commit 1" &&
29                 git tag -a -m "rev-1" rev-1
30         )
31 '
32
33 test_expect_success 'setup - commit with gitlink' '
34         echo a >a &&
35         echo z >z &&
36         git add a init z &&
37         git commit -m "super commit 1"
38 '
39
40 test_expect_success 'setup - hide init subdirectory' '
41         mv init .subrepo
42 '
43
44 test_expect_success 'setup - repository to add submodules to' '
45         git init addtest &&
46         git init addtest-ignore
47 '
48
49 # The 'submodule add' tests need some repository to add as a submodule.
50 # The trash directory is a good one as any.
51 submodurl=$TRASH_DIRECTORY
52
53 listbranches() {
54         git for-each-ref --format='%(refname)' 'refs/heads/*'
55 }
56
57 inspect() {
58         dir=$1 &&
59         dotdot="${2:-..}" &&
60
61         (
62                 cd "$dir" &&
63                 listbranches >"$dotdot/heads" &&
64                 { git symbolic-ref HEAD || :; } >"$dotdot/head" &&
65                 git rev-parse HEAD >"$dotdot/head-sha1" &&
66                 git update-index --refresh &&
67                 git diff-files --exit-code &&
68                 git clean -n -d -x >"$dotdot/untracked"
69         )
70 }
71
72 test_expect_success 'submodule add' '
73         echo "refs/heads/master" >expect &&
74         >empty &&
75
76         (
77                 cd addtest &&
78                 git submodule add "$submodurl" submod &&
79                 git submodule init
80         ) &&
81
82         rm -f heads head untracked &&
83         inspect addtest/submod ../.. &&
84         test_cmp expect heads &&
85         test_cmp expect head &&
86         test_cmp empty untracked
87 '
88
89 test_expect_success 'submodule add to .gitignored path' '
90         echo "refs/heads/master" >expect &&
91         >empty &&
92
93         (
94                 cd addtest-ignore &&
95                 # Does not use test_commit due to the ignore
96                 echo "*" > .gitignore &&
97                 git add --force .gitignore &&
98                 git commit -m"Ignore everything" &&
99                 git submodule add "$submodurl" submod &&
100                 git submodule init
101         ) &&
102
103         rm -f heads head untracked &&
104         inspect addtest/submod ../.. &&
105         test_cmp expect heads &&
106         test_cmp expect head &&
107         test_cmp empty untracked
108 '
109
110 test_expect_success 'submodule add --branch' '
111         echo "refs/heads/initial" >expect-head &&
112         cat <<-\EOF >expect-heads &&
113         refs/heads/initial
114         refs/heads/master
115         EOF
116         >empty &&
117
118         (
119                 cd addtest &&
120                 git submodule add -b initial "$submodurl" submod-branch &&
121                 git submodule init
122         ) &&
123
124         rm -f heads head untracked &&
125         inspect addtest/submod-branch ../.. &&
126         test_cmp expect-heads heads &&
127         test_cmp expect-head head &&
128         test_cmp empty untracked
129 '
130
131 test_expect_success 'submodule add with ./ in path' '
132         echo "refs/heads/master" >expect &&
133         >empty &&
134
135         (
136                 cd addtest &&
137                 git submodule add "$submodurl" ././dotsubmod/./frotz/./ &&
138                 git submodule init
139         ) &&
140
141         rm -f heads head untracked &&
142         inspect addtest/dotsubmod/frotz ../../.. &&
143         test_cmp expect heads &&
144         test_cmp expect head &&
145         test_cmp empty untracked
146 '
147
148 test_expect_success 'submodule add with // in path' '
149         echo "refs/heads/master" >expect &&
150         >empty &&
151
152         (
153                 cd addtest &&
154                 git submodule add "$submodurl" slashslashsubmod///frotz// &&
155                 git submodule init
156         ) &&
157
158         rm -f heads head untracked &&
159         inspect addtest/slashslashsubmod/frotz ../../.. &&
160         test_cmp expect heads &&
161         test_cmp expect head &&
162         test_cmp empty untracked
163 '
164
165 test_expect_success 'submodule add with /.. in path' '
166         echo "refs/heads/master" >expect &&
167         >empty &&
168
169         (
170                 cd addtest &&
171                 git submodule add "$submodurl" dotdotsubmod/../realsubmod/frotz/.. &&
172                 git submodule init
173         ) &&
174
175         rm -f heads head untracked &&
176         inspect addtest/realsubmod ../.. &&
177         test_cmp expect heads &&
178         test_cmp expect head &&
179         test_cmp empty untracked
180 '
181
182 test_expect_success 'submodule add with ./, /.. and // in path' '
183         echo "refs/heads/master" >expect &&
184         >empty &&
185
186         (
187                 cd addtest &&
188                 git submodule add "$submodurl" dot/dotslashsubmod/./../..////realsubmod2/a/b/c/d/../../../../frotz//.. &&
189                 git submodule init
190         ) &&
191
192         rm -f heads head untracked &&
193         inspect addtest/realsubmod2 ../.. &&
194         test_cmp expect heads &&
195         test_cmp expect head &&
196         test_cmp empty untracked
197 '
198
199 test_expect_success 'setup - add an example entry to .gitmodules' '
200         GIT_CONFIG=.gitmodules \
201         git config submodule.example.url git://example.com/init.git
202 '
203
204 test_expect_success 'status should fail for unmapped paths' '
205         test_must_fail git submodule status
206 '
207
208 test_expect_success 'setup - map path in .gitmodules' '
209         cat <<\EOF >expect &&
210 [submodule "example"]
211         url = git://example.com/init.git
212         path = init
213 EOF
214
215         GIT_CONFIG=.gitmodules git config submodule.example.path init &&
216
217         test_cmp expect .gitmodules
218 '
219
220 test_expect_success 'status should only print one line' '
221         git submodule status >lines &&
222         test $(wc -l <lines) = 1
223 '
224
225 test_expect_success 'setup - fetch commit name from submodule' '
226         rev1=$(cd .subrepo && git rev-parse HEAD) &&
227         printf "rev1: %s\n" "$rev1" &&
228         test -n "$rev1"
229 '
230
231 test_expect_success 'status should initially be "missing"' '
232         git submodule status >lines &&
233         grep "^-$rev1" lines
234 '
235
236 test_expect_success 'init should register submodule url in .git/config' '
237         echo git://example.com/init.git >expect &&
238
239         git submodule init &&
240         git config submodule.example.url >url &&
241         git config submodule.example.url ./.subrepo &&
242
243         test_cmp expect url
244 '
245
246 test_expect_success 'update should fail when path is used by a file' '
247         echo hello >expect &&
248
249         echo "hello" >init &&
250         test_must_fail git submodule update &&
251
252         test_cmp expect init
253 '
254
255 test_expect_success 'update should fail when path is used by a nonempty directory' '
256         echo hello >expect &&
257
258         rm -fr init &&
259         mkdir init &&
260         echo "hello" >init/a &&
261
262         test_must_fail git submodule update &&
263
264         test_cmp expect init/a
265 '
266
267 test_expect_success 'update should work when path is an empty dir' '
268         rm -fr init &&
269         rm -f head-sha1 &&
270         echo "$rev1" >expect &&
271
272         mkdir init &&
273         git submodule update &&
274
275         inspect init &&
276         test_cmp expect head-sha1
277 '
278
279 test_expect_success 'status should be "up-to-date" after update' '
280         git submodule status >list &&
281         grep "^ $rev1" list
282 '
283
284 test_expect_success 'status should be "modified" after submodule commit' '
285         (
286                 cd init &&
287                 echo b >b &&
288                 git add b &&
289                 git commit -m "submodule commit 2"
290         ) &&
291
292         rev2=$(cd init && git rev-parse HEAD) &&
293         test -n "$rev2" &&
294         git submodule status >list &&
295
296         grep "^+$rev2" list
297 '
298
299 test_expect_success 'the --cached sha1 should be rev1' '
300         git submodule --cached status >list &&
301         grep "^+$rev1" list
302 '
303
304 test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
305         git diff >diff &&
306         grep "^+Subproject commit $rev2" diff
307 '
308
309 test_expect_success 'update should checkout rev1' '
310         rm -f head-sha1 &&
311         echo "$rev1" >expect &&
312
313         git submodule update init &&
314         inspect init &&
315
316         test_cmp expect head-sha1
317 '
318
319 test_expect_success 'status should be "up-to-date" after update' '
320         git submodule status >list &&
321         grep "^ $rev1" list
322 '
323
324 test_expect_success 'checkout superproject with subproject already present' '
325         git checkout initial &&
326         git checkout master
327 '
328
329 test_expect_success 'apply submodule diff' '
330         >empty &&
331
332         git branch second &&
333         (
334                 cd init &&
335                 echo s >s &&
336                 git add s &&
337                 git commit -m "change subproject"
338         ) &&
339         git update-index --add init &&
340         git commit -m "change init" &&
341         git format-patch -1 --stdout >P.diff &&
342         git checkout second &&
343         git apply --index P.diff &&
344
345         git diff --cached master >staged &&
346         test_cmp empty staged
347 '
348
349 test_expect_success 'update --init' '
350         mv init init2 &&
351         git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
352         git config --remove-section submodule.example &&
353         test_must_fail git config submodule.example.url &&
354
355         git submodule update init > update.out &&
356         cat update.out &&
357         grep "not initialized" update.out &&
358         ! test -d init/.git &&
359
360         git submodule update --init init &&
361         test -d init/.git
362 '
363
364 test_expect_success 'do not add files from a submodule' '
365
366         git reset --hard &&
367         test_must_fail git add init/a
368
369 '
370
371 test_expect_success 'gracefully add submodule with a trailing slash' '
372
373         git reset --hard &&
374         git commit -m "commit subproject" init &&
375         (cd init &&
376          echo b > a) &&
377         git add init/ &&
378         git diff --exit-code --cached init &&
379         commit=$(cd init &&
380          git commit -m update a >/dev/null &&
381          git rev-parse HEAD) &&
382         git add init/ &&
383         test_must_fail git diff --exit-code --cached init &&
384         test $commit = $(git ls-files --stage |
385                 sed -n "s/^160000 \([^ ]*\).*/\1/p")
386
387 '
388
389 test_expect_success 'ls-files gracefully handles trailing slash' '
390
391         test "init" = "$(git ls-files init/)"
392
393 '
394
395 test_expect_success 'moving to a commit without submodule does not leave empty dir' '
396         rm -rf init &&
397         mkdir init &&
398         git reset --hard &&
399         git checkout initial &&
400         test ! -d init &&
401         git checkout second
402 '
403
404 test_expect_success 'submodule <invalid-path> warns' '
405
406         git submodule no-such-submodule 2> output.err &&
407         grep "^error: .*no-such-submodule" output.err
408
409 '
410
411 test_expect_success 'add submodules without specifying an explicit path' '
412         mkdir repo &&
413         cd repo &&
414         git init &&
415         echo r >r &&
416         git add r &&
417         git commit -m "repo commit 1" &&
418         cd .. &&
419         git clone --bare repo/ bare.git &&
420         cd addtest &&
421         git submodule add "$submodurl/repo" &&
422         git config -f .gitmodules submodule.repo.path repo &&
423         git submodule add "$submodurl/bare.git" &&
424         git config -f .gitmodules submodule.bare.path bare
425 '
426
427 test_done