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