t0000-t3999: detect and signal failure within loop
[git/debian.git] / t / t7064-wtstatus-pv2.sh
blob47fc21d96232ae4ae46e2e7a9db63723bdc66ff0
1 #!/bin/sh
3 test_description='git status --porcelain=v2
5 This test exercises porcelain V2 output for git status.'
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
11 . ./test-lib.sh
14 test_expect_success setup '
15 git checkout -f --orphan initial-branch &&
16 test_tick &&
17 git config core.autocrlf false &&
18 echo x >file_x &&
19 echo y >file_y &&
20 echo z >file_z &&
21 mkdir dir1 &&
22 echo a >dir1/file_a &&
23 echo b >dir1/file_b
26 test_expect_success 'before initial commit, nothing added, only untracked' '
27 cat >expect <<-EOF &&
28 # branch.oid (initial)
29 # branch.head initial-branch
30 ? actual
31 ? dir1/
32 ? expect
33 ? file_x
34 ? file_y
35 ? file_z
36 EOF
38 git status --porcelain=v2 --branch --untracked-files=normal >actual &&
39 test_cmp expect actual
42 test_expect_success 'before initial commit, things added' '
43 git add file_x file_y file_z dir1 &&
44 OID_A=$(git hash-object -t blob -- dir1/file_a) &&
45 OID_B=$(git hash-object -t blob -- dir1/file_b) &&
46 OID_X=$(git hash-object -t blob -- file_x) &&
47 OID_Y=$(git hash-object -t blob -- file_y) &&
48 OID_Z=$(git hash-object -t blob -- file_z) &&
50 cat >expect <<-EOF &&
51 # branch.oid (initial)
52 # branch.head initial-branch
53 1 A. N... 000000 100644 100644 $ZERO_OID $OID_A dir1/file_a
54 1 A. N... 000000 100644 100644 $ZERO_OID $OID_B dir1/file_b
55 1 A. N... 000000 100644 100644 $ZERO_OID $OID_X file_x
56 1 A. N... 000000 100644 100644 $ZERO_OID $OID_Y file_y
57 1 A. N... 000000 100644 100644 $ZERO_OID $OID_Z file_z
58 ? actual
59 ? expect
60 EOF
62 git status --porcelain=v2 --branch --untracked-files=all >actual &&
63 test_cmp expect actual
66 test_expect_success 'before initial commit, things added (-z)' '
67 lf_to_nul >expect <<-EOF &&
68 # branch.oid (initial)
69 # branch.head initial-branch
70 1 A. N... 000000 100644 100644 $ZERO_OID $OID_A dir1/file_a
71 1 A. N... 000000 100644 100644 $ZERO_OID $OID_B dir1/file_b
72 1 A. N... 000000 100644 100644 $ZERO_OID $OID_X file_x
73 1 A. N... 000000 100644 100644 $ZERO_OID $OID_Y file_y
74 1 A. N... 000000 100644 100644 $ZERO_OID $OID_Z file_z
75 ? actual
76 ? expect
77 EOF
79 git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
80 test_cmp expect actual
83 test_expect_success 'make first commit, comfirm HEAD oid and branch' '
84 git commit -m initial &&
85 H0=$(git rev-parse HEAD) &&
86 cat >expect <<-EOF &&
87 # branch.oid $H0
88 # branch.head initial-branch
89 ? actual
90 ? expect
91 EOF
93 git status --porcelain=v2 --branch --untracked-files=all >actual &&
94 test_cmp expect actual
97 test_expect_success 'after first commit, create unstaged changes' '
98 echo x >>file_x &&
99 OID_X1=$(git hash-object -t blob -- file_x) &&
100 rm file_z &&
101 H0=$(git rev-parse HEAD) &&
103 cat >expect <<-EOF &&
104 # branch.oid $H0
105 # branch.head initial-branch
106 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
107 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
108 ? actual
109 ? expect
112 git status --porcelain=v2 --branch --untracked-files=all >actual &&
113 test_cmp expect actual
116 test_expect_success 'after first commit, stash existing changes' '
117 cat >expect <<-EOF &&
118 # branch.oid $H0
119 # branch.head initial-branch
120 # stash 2
123 test_when_finished "git stash pop && git stash pop" &&
125 git stash -- file_x &&
126 git stash &&
127 git status --porcelain=v2 --branch --show-stash --untracked-files=no >actual &&
128 test_cmp expect actual
131 test_expect_success 'after first commit but omit untracked files and branch' '
132 cat >expect <<-EOF &&
133 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
134 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
137 git status --porcelain=v2 --untracked-files=no >actual &&
138 test_cmp expect actual
141 test_expect_success 'after first commit, stage existing changes' '
142 git add file_x &&
143 git rm file_z &&
144 H0=$(git rev-parse HEAD) &&
146 cat >expect <<-EOF &&
147 # branch.oid $H0
148 # branch.head initial-branch
149 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
150 1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
151 ? actual
152 ? expect
155 git status --porcelain=v2 --branch --untracked-files=all >actual &&
156 test_cmp expect actual
159 test_expect_success 'rename causes 2 path lines' '
160 git mv file_y renamed_y &&
161 H0=$(git rev-parse HEAD) &&
163 q_to_tab >expect <<-EOF &&
164 # branch.oid $H0
165 # branch.head initial-branch
166 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
167 1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
168 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
169 ? actual
170 ? expect
173 git status --porcelain=v2 --branch --untracked-files=all >actual &&
174 test_cmp expect actual
177 test_expect_success 'rename causes 2 path lines (-z)' '
178 H0=$(git rev-parse HEAD) &&
180 ## Lines use NUL path separator and line terminator, so double transform here.
181 q_to_nul <<-EOF | lf_to_nul >expect &&
182 # branch.oid $H0
183 # branch.head initial-branch
184 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
185 1 D. N... 100644 000000 000000 $OID_Z $ZERO_OID file_z
186 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
187 ? actual
188 ? expect
191 git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
192 test_cmp expect actual
195 test_expect_success 'make second commit, confirm clean and new HEAD oid' '
196 git commit -m second &&
197 H1=$(git rev-parse HEAD) &&
199 cat >expect <<-EOF &&
200 # branch.oid $H1
201 # branch.head initial-branch
202 ? actual
203 ? expect
206 git status --porcelain=v2 --branch --untracked-files=all >actual &&
207 test_cmp expect actual
210 test_expect_success 'confirm ignored files are not printed' '
211 test_when_finished "rm -f x.ign .gitignore" &&
212 echo x.ign >.gitignore &&
213 echo "ignore me" >x.ign &&
215 cat >expect <<-EOF &&
216 ? .gitignore
217 ? actual
218 ? expect
221 git status --porcelain=v2 --untracked-files=all >actual &&
222 test_cmp expect actual
225 test_expect_success 'ignored files are printed with --ignored' '
226 test_when_finished "rm -f x.ign .gitignore" &&
227 echo x.ign >.gitignore &&
228 echo "ignore me" >x.ign &&
230 cat >expect <<-EOF &&
231 ? .gitignore
232 ? actual
233 ? expect
234 ! x.ign
237 git status --porcelain=v2 --ignored --untracked-files=all >actual &&
238 test_cmp expect actual
241 test_expect_success 'create and commit permanent ignore file' '
242 cat >.gitignore <<-EOF &&
243 actual*
244 expect*
247 git add .gitignore &&
248 git commit -m ignore_trash &&
249 H1=$(git rev-parse HEAD) &&
251 cat >expect <<-EOF &&
252 # branch.oid $H1
253 # branch.head initial-branch
256 git status --porcelain=v2 --branch >actual &&
257 test_cmp expect actual
260 test_expect_success 'verify --intent-to-add output' '
261 test_when_finished "git rm -f intent1.add intent2.add" &&
262 touch intent1.add &&
263 echo test >intent2.add &&
265 git add --intent-to-add intent1.add intent2.add &&
267 cat >expect <<-EOF &&
268 1 .A N... 000000 000000 100644 $ZERO_OID $ZERO_OID intent1.add
269 1 .A N... 000000 000000 100644 $ZERO_OID $ZERO_OID intent2.add
272 git status --porcelain=v2 >actual &&
273 test_cmp expect actual
276 test_expect_success 'verify AA (add-add) conflict' '
277 test_when_finished "git reset --hard" &&
279 git branch AA_A initial-branch &&
280 git checkout AA_A &&
281 echo "Branch AA_A" >conflict.txt &&
282 OID_AA_A=$(git hash-object -t blob -- conflict.txt) &&
283 git add conflict.txt &&
284 git commit -m "branch aa_a" &&
286 git branch AA_B initial-branch &&
287 git checkout AA_B &&
288 echo "Branch AA_B" >conflict.txt &&
289 OID_AA_B=$(git hash-object -t blob -- conflict.txt) &&
290 git add conflict.txt &&
291 git commit -m "branch aa_b" &&
293 git branch AA_M AA_B &&
294 git checkout AA_M &&
295 test_must_fail git merge AA_A &&
297 HM=$(git rev-parse HEAD) &&
299 cat >expect <<-EOF &&
300 # branch.oid $HM
301 # branch.head AA_M
302 u AA N... 000000 100644 100644 100644 $ZERO_OID $OID_AA_B $OID_AA_A conflict.txt
305 git status --porcelain=v2 --branch --untracked-files=all >actual &&
306 test_cmp expect actual
309 test_expect_success 'verify UU (edit-edit) conflict' '
310 test_when_finished "git reset --hard" &&
312 git branch UU_ANC initial-branch &&
313 git checkout UU_ANC &&
314 echo "Ancestor" >conflict.txt &&
315 OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) &&
316 git add conflict.txt &&
317 git commit -m "UU_ANC" &&
319 git branch UU_A UU_ANC &&
320 git checkout UU_A &&
321 echo "Branch UU_A" >conflict.txt &&
322 OID_UU_A=$(git hash-object -t blob -- conflict.txt) &&
323 git add conflict.txt &&
324 git commit -m "branch uu_a" &&
326 git branch UU_B UU_ANC &&
327 git checkout UU_B &&
328 echo "Branch UU_B" >conflict.txt &&
329 OID_UU_B=$(git hash-object -t blob -- conflict.txt) &&
330 git add conflict.txt &&
331 git commit -m "branch uu_b" &&
333 git branch UU_M UU_B &&
334 git checkout UU_M &&
335 test_must_fail git merge UU_A &&
337 HM=$(git rev-parse HEAD) &&
339 cat >expect <<-EOF &&
340 # branch.oid $HM
341 # branch.head UU_M
342 u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt
345 git status --porcelain=v2 --branch --untracked-files=all >actual &&
346 test_cmp expect actual
349 test_expect_success 'verify upstream fields in branch header' '
350 git checkout initial-branch &&
351 test_when_finished "rm -rf sub_repo" &&
352 git clone . sub_repo &&
354 ## Confirm local initial-branch tracks remote initial-branch.
355 cd sub_repo &&
356 HUF=$(git rev-parse HEAD) &&
358 cat >expect <<-EOF &&
359 # branch.oid $HUF
360 # branch.head initial-branch
361 # branch.upstream origin/initial-branch
362 # branch.ab +0 -0
365 git status --porcelain=v2 --branch --untracked-files=all >actual &&
366 test_cmp expect actual &&
368 ## Test ahead/behind.
369 echo xyz >file_xyz &&
370 git add file_xyz &&
371 git commit -m xyz &&
373 HUF=$(git rev-parse HEAD) &&
375 cat >expect <<-EOF &&
376 # branch.oid $HUF
377 # branch.head initial-branch
378 # branch.upstream origin/initial-branch
379 # branch.ab +1 -0
382 git status --porcelain=v2 --branch --untracked-files=all >actual &&
383 test_cmp expect actual &&
385 ## Repeat the above but without --branch.
386 git status --porcelain=v2 --untracked-files=all >actual &&
387 test_must_be_empty actual &&
389 ## Test upstream-gone case. Fake this by pointing
390 ## origin/initial-branch at a non-existing commit.
391 git update-ref -d refs/remotes/origin/initial-branch &&
393 HUF=$(git rev-parse HEAD) &&
395 cat >expect <<-EOF &&
396 # branch.oid $HUF
397 # branch.head initial-branch
398 # branch.upstream origin/initial-branch
401 git status --porcelain=v2 --branch --untracked-files=all >actual &&
402 test_cmp expect actual
406 test_expect_success 'verify --[no-]ahead-behind with V2 format' '
407 git checkout initial-branch &&
408 test_when_finished "rm -rf sub_repo" &&
409 git clone . sub_repo &&
411 ## Confirm local initial-branch tracks remote initial-branch.
412 cd sub_repo &&
413 HUF=$(git rev-parse HEAD) &&
415 # Confirm --no-ahead-behind reports traditional branch.ab with 0/0 for equal branches.
416 cat >expect <<-EOF &&
417 # branch.oid $HUF
418 # branch.head initial-branch
419 # branch.upstream origin/initial-branch
420 # branch.ab +0 -0
423 git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
424 test_cmp expect actual &&
426 # Confirm --ahead-behind reports traditional branch.ab with 0/0.
427 cat >expect <<-EOF &&
428 # branch.oid $HUF
429 # branch.head initial-branch
430 # branch.upstream origin/initial-branch
431 # branch.ab +0 -0
434 git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
435 test_cmp expect actual &&
437 ## Test non-equal ahead/behind.
438 echo xyz >file_xyz &&
439 git add file_xyz &&
440 git commit -m xyz &&
442 HUF=$(git rev-parse HEAD) &&
444 # Confirm --no-ahead-behind reports branch.ab with ?/? for non-equal branches.
445 cat >expect <<-EOF &&
446 # branch.oid $HUF
447 # branch.head initial-branch
448 # branch.upstream origin/initial-branch
449 # branch.ab +? -?
452 git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
453 test_cmp expect actual &&
455 # Confirm --ahead-behind reports traditional branch.ab with 1/0.
456 cat >expect <<-EOF &&
457 # branch.oid $HUF
458 # branch.head initial-branch
459 # branch.upstream origin/initial-branch
460 # branch.ab +1 -0
463 git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
464 test_cmp expect actual &&
466 # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
467 git -c status.aheadbehind=false status --porcelain=v2 --branch --untracked-files=all >actual &&
468 test_cmp expect actual &&
470 # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
471 git -c status.aheadbehind=true status --porcelain=v2 --branch --untracked-files=all >actual &&
472 test_cmp expect actual
476 test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
477 git checkout initial-branch &&
478 git clone . sub_repo &&
479 git clone . super_repo &&
480 ( cd super_repo &&
481 git submodule add ../sub_repo sub1 &&
483 ## Confirm stage/add of clean submodule.
484 HMOD=$(git hash-object -t blob -- .gitmodules) &&
485 HSUP=$(git rev-parse HEAD) &&
486 HSUB=$HSUP &&
488 cat >expect <<-EOF &&
489 # branch.oid $HSUP
490 # branch.head initial-branch
491 # branch.upstream origin/initial-branch
492 # branch.ab +0 -0
493 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
494 1 A. S... 000000 160000 160000 $ZERO_OID $HSUB sub1
497 git status --porcelain=v2 --branch --untracked-files=all >actual &&
498 test_cmp expect actual
502 test_expect_success 'untracked changes in added submodule (AM S..U)' '
503 ( cd super_repo &&
504 ## create untracked file in the submodule.
505 ( cd sub1 &&
506 echo "xxxx" >file_in_sub
507 ) &&
509 HMOD=$(git hash-object -t blob -- .gitmodules) &&
510 HSUP=$(git rev-parse HEAD) &&
511 HSUB=$HSUP &&
513 cat >expect <<-EOF &&
514 # branch.oid $HSUP
515 # branch.head initial-branch
516 # branch.upstream origin/initial-branch
517 # branch.ab +0 -0
518 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
519 1 AM S..U 000000 160000 160000 $ZERO_OID $HSUB sub1
522 git status --porcelain=v2 --branch --untracked-files=all >actual &&
523 test_cmp expect actual
527 test_expect_success 'staged changes in added submodule (AM S.M.)' '
528 ( cd super_repo &&
529 ## stage the changes in the submodule.
530 ( cd sub1 &&
531 git add file_in_sub
532 ) &&
534 HMOD=$(git hash-object -t blob -- .gitmodules) &&
535 HSUP=$(git rev-parse HEAD) &&
536 HSUB=$HSUP &&
538 cat >expect <<-EOF &&
539 # branch.oid $HSUP
540 # branch.head initial-branch
541 # branch.upstream origin/initial-branch
542 # branch.ab +0 -0
543 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
544 1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
547 git status --porcelain=v2 --branch --untracked-files=all >actual &&
548 test_cmp expect actual
552 test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
553 ( cd super_repo &&
554 ( cd sub1 &&
555 ## make additional unstaged changes (on the same file) in the submodule.
556 ## This does not cause us to get S.MU (because the submodule does not report
557 ## a "?" line for the unstaged changes).
558 echo "more changes" >>file_in_sub
559 ) &&
561 HMOD=$(git hash-object -t blob -- .gitmodules) &&
562 HSUP=$(git rev-parse HEAD) &&
563 HSUB=$HSUP &&
565 cat >expect <<-EOF &&
566 # branch.oid $HSUP
567 # branch.head initial-branch
568 # branch.upstream origin/initial-branch
569 # branch.ab +0 -0
570 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
571 1 AM S.M. 000000 160000 160000 $ZERO_OID $HSUB sub1
574 git status --porcelain=v2 --branch --untracked-files=all >actual &&
575 test_cmp expect actual
579 test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
580 ( cd super_repo &&
581 ( cd sub1 &&
582 ## stage new changes in tracked file.
583 git add file_in_sub &&
584 ## create new untracked file.
585 echo "yyyy" >>another_file_in_sub
586 ) &&
588 HMOD=$(git hash-object -t blob -- .gitmodules) &&
589 HSUP=$(git rev-parse HEAD) &&
590 HSUB=$HSUP &&
592 cat >expect <<-EOF &&
593 # branch.oid $HSUP
594 # branch.head initial-branch
595 # branch.upstream origin/initial-branch
596 # branch.ab +0 -0
597 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
598 1 AM S.MU 000000 160000 160000 $ZERO_OID $HSUB sub1
601 git status --porcelain=v2 --branch --untracked-files=all >actual &&
602 test_cmp expect actual
606 test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
607 ( cd super_repo &&
608 ( cd sub1 &&
609 ## Make a new commit in the submodule.
610 git add file_in_sub &&
611 rm -f another_file_in_sub &&
612 git commit -m "new commit"
613 ) &&
615 HMOD=$(git hash-object -t blob -- .gitmodules) &&
616 HSUP=$(git rev-parse HEAD) &&
617 HSUB=$HSUP &&
619 cat >expect <<-EOF &&
620 # branch.oid $HSUP
621 # branch.head initial-branch
622 # branch.upstream origin/initial-branch
623 # branch.ab +0 -0
624 1 A. N... 000000 100644 100644 $ZERO_OID $HMOD .gitmodules
625 1 AM SC.. 000000 160000 160000 $ZERO_OID $HSUB sub1
628 git status --porcelain=v2 --branch --untracked-files=all >actual &&
629 test_cmp expect actual
633 test_expect_success 'stage submodule in super and commit' '
634 ( cd super_repo &&
635 ## Stage the new submodule commit in the super.
636 git add sub1 &&
637 ## Commit the super so that the sub no longer appears as added.
638 git commit -m "super commit" &&
640 HSUP=$(git rev-parse HEAD) &&
642 cat >expect <<-EOF &&
643 # branch.oid $HSUP
644 # branch.head initial-branch
645 # branch.upstream origin/initial-branch
646 # branch.ab +1 -0
649 git status --porcelain=v2 --branch --untracked-files=all >actual &&
650 test_cmp expect actual
654 test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
655 ( cd super_repo &&
656 ( cd sub1 &&
657 echo "zzzz" >>file_in_sub
658 ) &&
660 HSUP=$(git rev-parse HEAD) &&
661 HSUB=$(cd sub1 && git rev-parse HEAD) &&
663 cat >expect <<-EOF &&
664 # branch.oid $HSUP
665 # branch.head initial-branch
666 # branch.upstream origin/initial-branch
667 # branch.ab +1 -0
668 1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
671 git status --porcelain=v2 --branch --untracked-files=all >actual &&
672 test_cmp expect actual
676 test_done