]> git.ipfire.org Git - thirdparty/git.git/blob - t/t7064-wtstatus-pv2.sh
branch.c: simplify advice-and-die sequence
[thirdparty/git.git] / t / t7064-wtstatus-pv2.sh
1 #!/bin/sh
2
3 test_description='git status --porcelain=v2
4
5 This test exercises porcelain V2 output for git status.'
6
7
8 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=master
9 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10
11 . ./test-lib.sh
12
13
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
24 '
25
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
37
38 git status --porcelain=v2 --branch --untracked-files=normal >actual &&
39 test_cmp expect actual
40 '
41
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) &&
49
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
61
62 git status --porcelain=v2 --branch --untracked-files=all >actual &&
63 test_cmp expect actual
64 '
65
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
78
79 git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
80 test_cmp expect actual
81 '
82
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
92
93 git status --porcelain=v2 --branch --untracked-files=all >actual &&
94 test_cmp expect actual
95 '
96
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) &&
102
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
110 EOF
111
112 git status --porcelain=v2 --branch --untracked-files=all >actual &&
113 test_cmp expect actual
114 '
115
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
121 EOF
122
123 test_when_finished "git stash pop && git stash pop" &&
124
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
129 '
130
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
135 EOF
136
137 git status --porcelain=v2 --untracked-files=no >actual &&
138 test_cmp expect actual
139 '
140
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) &&
145
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
153 EOF
154
155 git status --porcelain=v2 --branch --untracked-files=all >actual &&
156 test_cmp expect actual
157 '
158
159 test_expect_success 'rename causes 2 path lines' '
160 git mv file_y renamed_y &&
161 H0=$(git rev-parse HEAD) &&
162
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
171 EOF
172
173 git status --porcelain=v2 --branch --untracked-files=all >actual &&
174 test_cmp expect actual
175 '
176
177 test_expect_success 'rename causes 2 path lines (-z)' '
178 H0=$(git rev-parse HEAD) &&
179
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
189 EOF
190
191 git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
192 test_cmp expect actual
193 '
194
195 test_expect_success 'make second commit, confirm clean and new HEAD oid' '
196 git commit -m second &&
197 H1=$(git rev-parse HEAD) &&
198
199 cat >expect <<-EOF &&
200 # branch.oid $H1
201 # branch.head initial-branch
202 ? actual
203 ? expect
204 EOF
205
206 git status --porcelain=v2 --branch --untracked-files=all >actual &&
207 test_cmp expect actual
208 '
209
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 &&
214
215 cat >expect <<-EOF &&
216 ? .gitignore
217 ? actual
218 ? expect
219 EOF
220
221 git status --porcelain=v2 --untracked-files=all >actual &&
222 test_cmp expect actual
223 '
224
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 &&
229
230 cat >expect <<-EOF &&
231 ? .gitignore
232 ? actual
233 ? expect
234 ! x.ign
235 EOF
236
237 git status --porcelain=v2 --ignored --untracked-files=all >actual &&
238 test_cmp expect actual
239 '
240
241 test_expect_success 'create and commit permanent ignore file' '
242 cat >.gitignore <<-EOF &&
243 actual*
244 expect*
245 EOF
246
247 git add .gitignore &&
248 git commit -m ignore_trash &&
249 H1=$(git rev-parse HEAD) &&
250
251 cat >expect <<-EOF &&
252 # branch.oid $H1
253 # branch.head initial-branch
254 EOF
255
256 git status --porcelain=v2 --branch >actual &&
257 test_cmp expect actual
258 '
259
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 &&
264
265 git add --intent-to-add intent1.add intent2.add &&
266
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
270 EOF
271
272 git status --porcelain=v2 >actual &&
273 test_cmp expect actual
274 '
275
276 test_expect_success 'verify AA (add-add) conflict' '
277 test_when_finished "git reset --hard" &&
278
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" &&
285
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" &&
292
293 git branch AA_M AA_B &&
294 git checkout AA_M &&
295 test_must_fail git merge AA_A &&
296
297 HM=$(git rev-parse HEAD) &&
298
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
303 EOF
304
305 git status --porcelain=v2 --branch --untracked-files=all >actual &&
306 test_cmp expect actual
307 '
308
309 test_expect_success 'verify UU (edit-edit) conflict' '
310 test_when_finished "git reset --hard" &&
311
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" &&
318
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" &&
325
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" &&
332
333 git branch UU_M UU_B &&
334 git checkout UU_M &&
335 test_must_fail git merge UU_A &&
336
337 HM=$(git rev-parse HEAD) &&
338
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
343 EOF
344
345 git status --porcelain=v2 --branch --untracked-files=all >actual &&
346 test_cmp expect actual
347 '
348
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 &&
353 (
354 ## Confirm local initial-branch tracks remote initial-branch.
355 cd sub_repo &&
356 HUF=$(git rev-parse HEAD) &&
357
358 cat >expect <<-EOF &&
359 # branch.oid $HUF
360 # branch.head initial-branch
361 # branch.upstream origin/initial-branch
362 # branch.ab +0 -0
363 EOF
364
365 git status --porcelain=v2 --branch --untracked-files=all >actual &&
366 test_cmp expect actual &&
367
368 ## Test ahead/behind.
369 echo xyz >file_xyz &&
370 git add file_xyz &&
371 git commit -m xyz &&
372
373 HUF=$(git rev-parse HEAD) &&
374
375 cat >expect <<-EOF &&
376 # branch.oid $HUF
377 # branch.head initial-branch
378 # branch.upstream origin/initial-branch
379 # branch.ab +1 -0
380 EOF
381
382 git status --porcelain=v2 --branch --untracked-files=all >actual &&
383 test_cmp expect actual &&
384
385 ## Repeat the above but without --branch.
386 git status --porcelain=v2 --untracked-files=all >actual &&
387 test_must_be_empty actual &&
388
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 &&
392
393 HUF=$(git rev-parse HEAD) &&
394
395 cat >expect <<-EOF &&
396 # branch.oid $HUF
397 # branch.head initial-branch
398 # branch.upstream origin/initial-branch
399 EOF
400
401 git status --porcelain=v2 --branch --untracked-files=all >actual &&
402 test_cmp expect actual
403 )
404 '
405
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 &&
410 (
411 ## Confirm local initial-branch tracks remote initial-branch.
412 cd sub_repo &&
413 HUF=$(git rev-parse HEAD) &&
414
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
421 EOF
422
423 git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
424 test_cmp expect actual &&
425
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
432 EOF
433
434 git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
435 test_cmp expect actual &&
436
437 ## Test non-equal ahead/behind.
438 echo xyz >file_xyz &&
439 git add file_xyz &&
440 git commit -m xyz &&
441
442 HUF=$(git rev-parse HEAD) &&
443
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 +? -?
450 EOF
451
452 git status --no-ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
453 test_cmp expect actual &&
454
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
461 EOF
462
463 git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
464 test_cmp expect actual &&
465
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 &&
469
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
473 )
474 '
475
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 &&
482
483 ## Confirm stage/add of clean submodule.
484 HMOD=$(git hash-object -t blob -- .gitmodules) &&
485 HSUP=$(git rev-parse HEAD) &&
486 HSUB=$HSUP &&
487
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
495 EOF
496
497 git status --porcelain=v2 --branch --untracked-files=all >actual &&
498 test_cmp expect actual
499 )
500 '
501
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 ) &&
508
509 HMOD=$(git hash-object -t blob -- .gitmodules) &&
510 HSUP=$(git rev-parse HEAD) &&
511 HSUB=$HSUP &&
512
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
520 EOF
521
522 git status --porcelain=v2 --branch --untracked-files=all >actual &&
523 test_cmp expect actual
524 )
525 '
526
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 ) &&
533
534 HMOD=$(git hash-object -t blob -- .gitmodules) &&
535 HSUP=$(git rev-parse HEAD) &&
536 HSUB=$HSUP &&
537
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
545 EOF
546
547 git status --porcelain=v2 --branch --untracked-files=all >actual &&
548 test_cmp expect actual
549 )
550 '
551
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 ) &&
560
561 HMOD=$(git hash-object -t blob -- .gitmodules) &&
562 HSUP=$(git rev-parse HEAD) &&
563 HSUB=$HSUP &&
564
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
572 EOF
573
574 git status --porcelain=v2 --branch --untracked-files=all >actual &&
575 test_cmp expect actual
576 )
577 '
578
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 ) &&
587
588 HMOD=$(git hash-object -t blob -- .gitmodules) &&
589 HSUP=$(git rev-parse HEAD) &&
590 HSUB=$HSUP &&
591
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
599 EOF
600
601 git status --porcelain=v2 --branch --untracked-files=all >actual &&
602 test_cmp expect actual
603 )
604 '
605
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 ) &&
614
615 HMOD=$(git hash-object -t blob -- .gitmodules) &&
616 HSUP=$(git rev-parse HEAD) &&
617 HSUB=$HSUP &&
618
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
626 EOF
627
628 git status --porcelain=v2 --branch --untracked-files=all >actual &&
629 test_cmp expect actual
630 )
631 '
632
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" &&
639
640 HSUP=$(git rev-parse HEAD) &&
641
642 cat >expect <<-EOF &&
643 # branch.oid $HSUP
644 # branch.head initial-branch
645 # branch.upstream origin/initial-branch
646 # branch.ab +1 -0
647 EOF
648
649 git status --porcelain=v2 --branch --untracked-files=all >actual &&
650 test_cmp expect actual
651 )
652 '
653
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 ) &&
659
660 HSUP=$(git rev-parse HEAD) &&
661 HSUB=$(cd sub1 && git rev-parse HEAD) &&
662
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
669 EOF
670
671 git status --porcelain=v2 --branch --untracked-files=all >actual &&
672 test_cmp expect actual
673 )
674 '
675
676 test_done