Merge branch 'ab/perl-do-not-abuse-map'
[git] / t / t7506-status-submodule.sh
1 #!/bin/sh
2
3 test_description='git status for submodule'
4
5 . ./test-lib.sh
6
7 test_create_repo_with_commit () {
8         test_create_repo "$1" &&
9         (
10                 cd "$1" &&
11                 : >bar &&
12                 git add bar &&
13                 git commit -m " Add bar" &&
14                 : >foo &&
15                 git add foo &&
16                 git commit -m " Add foo"
17         )
18 }
19
20 sanitize_output () {
21         sed -e "s/$OID_REGEX/HASH/" -e "s/$OID_REGEX/HASH/" output >output2 &&
22         mv output2 output
23 }
24
25 sanitize_diff () {
26         sed -e "/^index [0-9a-f,]*\.\.[0-9a-f]*/d" "$1"
27 }
28
29
30 test_expect_success 'setup' '
31         test_create_repo_with_commit sub &&
32         echo output > .gitignore &&
33         git add sub .gitignore &&
34         git commit -m "Add submodule sub"
35 '
36
37 test_expect_success 'status clean' '
38         git status >output &&
39         test_i18ngrep "nothing to commit" output
40 '
41
42 test_expect_success 'commit --dry-run -a clean' '
43         test_must_fail git commit --dry-run -a >output &&
44         test_i18ngrep "nothing to commit" output
45 '
46
47 test_expect_success 'status with modified file in submodule' '
48         (cd sub && git reset --hard) &&
49         echo "changed" >sub/foo &&
50         git status >output &&
51         test_i18ngrep "modified:   sub (modified content)" output
52 '
53
54 test_expect_success 'status with modified file in submodule (porcelain)' '
55         (cd sub && git reset --hard) &&
56         echo "changed" >sub/foo &&
57         git status --porcelain >output &&
58         diff output - <<-\EOF
59          M sub
60         EOF
61 '
62
63 test_expect_success 'status with modified file in submodule (short)' '
64         (cd sub && git reset --hard) &&
65         echo "changed" >sub/foo &&
66         git status --short >output &&
67         diff output - <<-\EOF
68          m sub
69         EOF
70 '
71
72 test_expect_success 'status with added file in submodule' '
73         (cd sub && git reset --hard && echo >foo && git add foo) &&
74         git status >output &&
75         test_i18ngrep "modified:   sub (modified content)" output
76 '
77
78 test_expect_success 'status with added file in submodule (porcelain)' '
79         (cd sub && git reset --hard && echo >foo && git add foo) &&
80         git status --porcelain >output &&
81         diff output - <<-\EOF
82          M sub
83         EOF
84 '
85
86 test_expect_success 'status with added file in submodule (short)' '
87         (cd sub && git reset --hard && echo >foo && git add foo) &&
88         git status --short >output &&
89         diff output - <<-\EOF
90          m sub
91         EOF
92 '
93
94 test_expect_success 'status with untracked file in submodule' '
95         (cd sub && git reset --hard) &&
96         echo "content" >sub/new-file &&
97         git status >output &&
98         test_i18ngrep "modified:   sub (untracked content)" output
99 '
100
101 test_expect_success 'status -uno with untracked file in submodule' '
102         git status -uno >output &&
103         test_i18ngrep "^nothing to commit" output
104 '
105
106 test_expect_success 'status with untracked file in submodule (porcelain)' '
107         git status --porcelain >output &&
108         diff output - <<-\EOF
109          M sub
110         EOF
111 '
112
113 test_expect_success 'status with untracked file in submodule (short)' '
114         git status --short >output &&
115         diff output - <<-\EOF
116          ? sub
117         EOF
118 '
119
120 test_expect_success 'status with added and untracked file in submodule' '
121         (cd sub && git reset --hard && echo >foo && git add foo) &&
122         echo "content" >sub/new-file &&
123         git status >output &&
124         test_i18ngrep "modified:   sub (modified content, untracked content)" output
125 '
126
127 test_expect_success 'status with added and untracked file in submodule (porcelain)' '
128         (cd sub && git reset --hard && echo >foo && git add foo) &&
129         echo "content" >sub/new-file &&
130         git status --porcelain >output &&
131         diff output - <<-\EOF
132          M sub
133         EOF
134 '
135
136 test_expect_success 'status with modified file in modified submodule' '
137         (cd sub && git reset --hard) &&
138         rm sub/new-file &&
139         (cd sub && echo "next change" >foo && git commit -m "next change" foo) &&
140         echo "changed" >sub/foo &&
141         git status >output &&
142         test_i18ngrep "modified:   sub (new commits, modified content)" output
143 '
144
145 test_expect_success 'status with modified file in modified submodule (porcelain)' '
146         (cd sub && git reset --hard) &&
147         echo "changed" >sub/foo &&
148         git status --porcelain >output &&
149         diff output - <<-\EOF
150          M sub
151         EOF
152 '
153
154 test_expect_success 'status with added file in modified submodule' '
155         (cd sub && git reset --hard && echo >foo && git add foo) &&
156         git status >output &&
157         test_i18ngrep "modified:   sub (new commits, modified content)" output
158 '
159
160 test_expect_success 'status with added file in modified submodule (porcelain)' '
161         (cd sub && git reset --hard && echo >foo && git add foo) &&
162         git status --porcelain >output &&
163         diff output - <<-\EOF
164          M sub
165         EOF
166 '
167
168 test_expect_success 'status with untracked file in modified submodule' '
169         (cd sub && git reset --hard) &&
170         echo "content" >sub/new-file &&
171         git status >output &&
172         test_i18ngrep "modified:   sub (new commits, untracked content)" output
173 '
174
175 test_expect_success 'status with untracked file in modified submodule (porcelain)' '
176         git status --porcelain >output &&
177         diff output - <<-\EOF
178          M sub
179         EOF
180 '
181
182 test_expect_success 'status with added and untracked file in modified submodule' '
183         (cd sub && git reset --hard && echo >foo && git add foo) &&
184         echo "content" >sub/new-file &&
185         git status >output &&
186         test_i18ngrep "modified:   sub (new commits, modified content, untracked content)" output
187 '
188
189 test_expect_success 'status with added and untracked file in modified submodule (porcelain)' '
190         (cd sub && git reset --hard && echo >foo && git add foo) &&
191         echo "content" >sub/new-file &&
192         git status --porcelain >output &&
193         diff output - <<-\EOF
194          M sub
195         EOF
196 '
197
198 test_expect_success 'setup .git file for sub' '
199         (cd sub &&
200          rm -f new-file &&
201          REAL="$(pwd)/../.real" &&
202          mv .git "$REAL" &&
203          echo "gitdir: $REAL" >.git) &&
204          echo .real >>.gitignore &&
205          git commit -m "added .real to .gitignore" .gitignore
206 '
207
208 test_expect_success 'status with added file in modified submodule with .git file' '
209         (cd sub && git reset --hard && echo >foo && git add foo) &&
210         git status >output &&
211         test_i18ngrep "modified:   sub (new commits, modified content)" output
212 '
213
214 test_expect_success 'status with a lot of untracked files in the submodule' '
215         (
216                 cd sub &&
217                 i=0 &&
218                 while test $i -lt 1024
219                 do
220                         >some-file-$i &&
221                         i=$(( $i + 1 )) || exit 1
222                 done
223         ) &&
224         git status --porcelain sub 2>err.actual &&
225         test_must_be_empty err.actual &&
226         rm err.actual
227 '
228
229 test_expect_success 'rm submodule contents' '
230         rm -rf sub &&
231         mkdir sub
232 '
233
234 test_expect_success 'status clean (empty submodule dir)' '
235         git status >output &&
236         test_i18ngrep "nothing to commit" output
237 '
238
239 test_expect_success 'status -a clean (empty submodule dir)' '
240         test_must_fail git commit --dry-run -a >output &&
241         test_i18ngrep "nothing to commit" output
242 '
243
244 cat >status_expect <<\EOF
245 AA .gitmodules
246 A  sub1
247 EOF
248
249 test_expect_success 'status with merge conflict in .gitmodules' '
250         git clone . super &&
251         test_create_repo_with_commit sub1 &&
252         test_tick &&
253         test_create_repo_with_commit sub2 &&
254         (
255                 cd super &&
256                 prev=$(git rev-parse HEAD) &&
257                 git checkout -b add_sub1 &&
258                 git submodule add ../sub1 &&
259                 git commit -m "add sub1" &&
260                 git checkout -b add_sub2 $prev &&
261                 git submodule add ../sub2 &&
262                 git commit -m "add sub2" &&
263                 git checkout -b merge_conflict_gitmodules &&
264                 test_must_fail git merge add_sub1 &&
265                 git status -s >../status_actual 2>&1
266         ) &&
267         test_cmp status_actual status_expect
268 '
269
270 sha1_merge_sub1=$(cd sub1 && git rev-parse HEAD)
271 sha1_merge_sub2=$(cd sub2 && git rev-parse HEAD)
272 short_sha1_merge_sub1=$(cd sub1 && git rev-parse --short HEAD)
273 short_sha1_merge_sub2=$(cd sub2 && git rev-parse --short HEAD)
274 cat >diff_expect <<\EOF
275 diff --cc .gitmodules
276 --- a/.gitmodules
277 +++ b/.gitmodules
278 @@@ -1,3 -1,3 +1,9 @@@
279 ++<<<<<<< HEAD
280  +[submodule "sub2"]
281  +      path = sub2
282  +      url = ../sub2
283 ++=======
284 + [submodule "sub1"]
285 +       path = sub1
286 +       url = ../sub1
287 ++>>>>>>> add_sub1
288 EOF
289
290 cat >diff_submodule_expect <<\EOF
291 diff --cc .gitmodules
292 --- a/.gitmodules
293 +++ b/.gitmodules
294 @@@ -1,3 -1,3 +1,9 @@@
295 ++<<<<<<< HEAD
296  +[submodule "sub2"]
297  +      path = sub2
298  +      url = ../sub2
299 ++=======
300 + [submodule "sub1"]
301 +       path = sub1
302 +       url = ../sub1
303 ++>>>>>>> add_sub1
304 EOF
305
306 test_expect_success 'diff with merge conflict in .gitmodules' '
307         (
308                 cd super &&
309                 git diff >../diff_actual 2>&1
310         ) &&
311         sanitize_diff diff_actual >diff_sanitized &&
312         test_cmp diff_expect diff_sanitized
313 '
314
315 test_expect_success 'diff --submodule with merge conflict in .gitmodules' '
316         (
317                 cd super &&
318                 git diff --submodule >../diff_submodule_actual 2>&1
319         ) &&
320         sanitize_diff diff_submodule_actual >diff_sanitized &&
321         test_cmp diff_submodule_expect diff_sanitized
322 '
323
324 # We'll setup different cases for further testing:
325 # sub1 will contain a nested submodule,
326 # sub2 will have an untracked file
327 # sub3 will have an untracked repository
328 test_expect_success 'setup superproject with untracked file in nested submodule' '
329         (
330                 cd super &&
331                 git clean -dfx &&
332                 git rm .gitmodules &&
333                 git commit -m "remove .gitmodules" &&
334                 git submodule add -f ./sub1 &&
335                 git submodule add -f ./sub2 &&
336                 git submodule add -f ./sub1 sub3 &&
337                 git commit -a -m "messy merge in superproject" &&
338                 (
339                         cd sub1 &&
340                         git submodule add ../sub2 &&
341                         git commit -a -m "add sub2 to sub1"
342                 ) &&
343                 git add sub1 &&
344                 git commit -a -m "update sub1 to contain nested sub"
345         ) &&
346         echo content >super/sub1/sub2/file &&
347         echo content >super/sub2/file &&
348         git -C super/sub3 clone ../../sub2 untracked_repository
349 '
350
351 test_expect_success 'status with untracked file in nested submodule (porcelain)' '
352         git -C super status --porcelain >output &&
353         diff output - <<-\EOF
354          M sub1
355          M sub2
356          M sub3
357         EOF
358 '
359
360 test_expect_success 'status with untracked file in nested submodule (porcelain=2)' '
361         git -C super status --porcelain=2 >output &&
362         sanitize_output output &&
363         diff output - <<-\EOF
364         1 .M S..U 160000 160000 160000 HASH HASH sub1
365         1 .M S..U 160000 160000 160000 HASH HASH sub2
366         1 .M S..U 160000 160000 160000 HASH HASH sub3
367         EOF
368 '
369
370 test_expect_success 'status with untracked file in nested submodule (short)' '
371         git -C super status --short >output &&
372         diff output - <<-\EOF
373          ? sub1
374          ? sub2
375          ? sub3
376         EOF
377 '
378
379 test_expect_success 'setup superproject with modified file in nested submodule' '
380         git -C super/sub1/sub2 add file &&
381         git -C super/sub2 add file
382 '
383
384 test_expect_success 'status with added file in nested submodule (porcelain)' '
385         git -C super status --porcelain >output &&
386         diff output - <<-\EOF
387          M sub1
388          M sub2
389          M sub3
390         EOF
391 '
392
393 test_expect_success 'status with added file in nested submodule (porcelain=2)' '
394         git -C super status --porcelain=2 >output &&
395         sanitize_output output &&
396         diff output - <<-\EOF
397         1 .M S.M. 160000 160000 160000 HASH HASH sub1
398         1 .M S.M. 160000 160000 160000 HASH HASH sub2
399         1 .M S..U 160000 160000 160000 HASH HASH sub3
400         EOF
401 '
402
403 test_expect_success 'status with added file in nested submodule (short)' '
404         git -C super status --short >output &&
405         diff output - <<-\EOF
406          m sub1
407          m sub2
408          ? sub3
409         EOF
410 '
411
412 test_done