status: unit tests for --porcelain=v2

Test porcelain v2 status format. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff Hostetler committed Aug 12, 2016 at 11:44 UTC 888525d7865fbf9a277ef5fb8c1fe57f2fb1a0c5
1 file changed +593
t/t7064-wtstatus-pv2.sh new
+593
@@ -0,0 +1,593 @@
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 +. ./test-lib.sh
9 +
10 +
11 +test_expect_success setup '
12 + test_tick &&
13 + git config core.autocrlf false &&
14 + echo x >file_x &&
15 + echo y >file_y &&
16 + echo z >file_z &&
17 + mkdir dir1 &&
18 + echo a >dir1/file_a &&
19 + echo b >dir1/file_b
20 +'
21 +
22 +test_expect_success 'before initial commit, nothing added, only untracked' '
23 + cat >expect <<-EOF &&
24 + # branch.oid (initial)
25 + # branch.head master
26 + ? actual
27 + ? dir1/
28 + ? expect
29 + ? file_x
30 + ? file_y
31 + ? file_z
32 + EOF
33 +
34 + git status --porcelain=v2 --branch --untracked-files=normal >actual &&
35 + test_cmp expect actual
36 +'
37 +
38 +test_expect_success 'before initial commit, things added' '
39 + git add file_x file_y file_z dir1 &&
40 + OID_A=$(git hash-object -t blob -- dir1/file_a) &&
41 + OID_B=$(git hash-object -t blob -- dir1/file_b) &&
42 + OID_X=$(git hash-object -t blob -- file_x) &&
43 + OID_Y=$(git hash-object -t blob -- file_y) &&
44 + OID_Z=$(git hash-object -t blob -- file_z) &&
45 +
46 + cat >expect <<-EOF &&
47 + # branch.oid (initial)
48 + # branch.head master
49 + 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
50 + 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
51 + 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
52 + 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
53 + 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
54 + ? actual
55 + ? expect
56 + EOF
57 +
58 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
59 + test_cmp expect actual
60 +'
61 +
62 +test_expect_success 'before initial commit, things added (-z)' '
63 + lf_to_nul >expect <<-EOF &&
64 + # branch.oid (initial)
65 + # branch.head master
66 + 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
67 + 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
68 + 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
69 + 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
70 + 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
71 + ? actual
72 + ? expect
73 + EOF
74 +
75 + git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
76 + test_cmp expect actual
77 +'
78 +
79 +test_expect_success 'make first commit, comfirm HEAD oid and branch' '
80 + git commit -m initial &&
81 + H0=$(git rev-parse HEAD) &&
82 + cat >expect <<-EOF &&
83 + # branch.oid $H0
84 + # branch.head master
85 + ? actual
86 + ? expect
87 + EOF
88 +
89 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
90 + test_cmp expect actual
91 +'
92 +
93 +test_expect_success 'after first commit, create unstaged changes' '
94 + echo x >>file_x &&
95 + OID_X1=$(git hash-object -t blob -- file_x) &&
96 + rm file_z &&
97 + H0=$(git rev-parse HEAD) &&
98 +
99 + cat >expect <<-EOF &&
100 + # branch.oid $H0
101 + # branch.head master
102 + 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
103 + 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
104 + ? actual
105 + ? expect
106 + EOF
107 +
108 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
109 + test_cmp expect actual
110 +'
111 +
112 +test_expect_success 'after first commit but omit untracked files and branch' '
113 + cat >expect <<-EOF &&
114 + 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
115 + 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
116 + EOF
117 +
118 + git status --porcelain=v2 --untracked-files=no >actual &&
119 + test_cmp expect actual
120 +'
121 +
122 +test_expect_success 'after first commit, stage existing changes' '
123 + git add file_x &&
124 + git rm file_z &&
125 + H0=$(git rev-parse HEAD) &&
126 +
127 + cat >expect <<-EOF &&
128 + # branch.oid $H0
129 + # branch.head master
130 + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
131 + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
132 + ? actual
133 + ? expect
134 + EOF
135 +
136 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
137 + test_cmp expect actual
138 +'
139 +
140 +test_expect_success 'rename causes 2 path lines' '
141 + git mv file_y renamed_y &&
142 + H0=$(git rev-parse HEAD) &&
143 +
144 + q_to_tab >expect <<-EOF &&
145 + # branch.oid $H0
146 + # branch.head master
147 + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
148 + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
149 + 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
150 + ? actual
151 + ? expect
152 + EOF
153 +
154 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
155 + test_cmp expect actual
156 +'
157 +
158 +test_expect_success 'rename causes 2 path lines (-z)' '
159 + H0=$(git rev-parse HEAD) &&
160 +
161 + ## Lines use NUL path separator and line terminator, so double transform here.
162 + q_to_nul <<-EOF | lf_to_nul >expect &&
163 + # branch.oid $H0
164 + # branch.head master
165 + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
166 + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
167 + 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
168 + ? actual
169 + ? expect
170 + EOF
171 +
172 + git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
173 + test_cmp expect actual
174 +'
175 +
176 +test_expect_success 'make second commit, confirm clean and new HEAD oid' '
177 + git commit -m second &&
178 + H1=$(git rev-parse HEAD) &&
179 +
180 + cat >expect <<-EOF &&
181 + # branch.oid $H1
182 + # branch.head master
183 + ? actual
184 + ? expect
185 + EOF
186 +
187 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
188 + test_cmp expect actual
189 +'
190 +
191 +test_expect_success 'confirm ignored files are not printed' '
192 + test_when_finished "rm -f x.ign .gitignore" &&
193 + echo x.ign >.gitignore &&
194 + echo "ignore me" >x.ign &&
195 +
196 + cat >expect <<-EOF &&
197 + ? .gitignore
198 + ? actual
199 + ? expect
200 + EOF
201 +
202 + git status --porcelain=v2 --untracked-files=all >actual &&
203 + test_cmp expect actual
204 +'
205 +
206 +test_expect_success 'ignored files are printed with --ignored' '
207 + test_when_finished "rm -f x.ign .gitignore" &&
208 + echo x.ign >.gitignore &&
209 + echo "ignore me" >x.ign &&
210 +
211 + cat >expect <<-EOF &&
212 + ? .gitignore
213 + ? actual
214 + ? expect
215 + ! x.ign
216 + EOF
217 +
218 + git status --porcelain=v2 --ignored --untracked-files=all >actual &&
219 + test_cmp expect actual
220 +'
221 +
222 +test_expect_success 'create and commit permanent ignore file' '
223 + cat >.gitignore <<-EOF &&
224 + actual*
225 + expect*
226 + EOF
227 +
228 + git add .gitignore &&
229 + git commit -m ignore_trash &&
230 + H1=$(git rev-parse HEAD) &&
231 +
232 + cat >expect <<-EOF &&
233 + # branch.oid $H1
234 + # branch.head master
235 + EOF
236 +
237 + git status --porcelain=v2 --branch >actual &&
238 + test_cmp expect actual
239 +'
240 +
241 +test_expect_success 'verify --intent-to-add output' '
242 + test_when_finished "git rm -f intent1.add intent2.add" &&
243 + touch intent1.add &&
244 + echo test >intent2.add &&
245 +
246 + git add --intent-to-add intent1.add intent2.add &&
247 +
248 + cat >expect <<-EOF &&
249 + 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent1.add
250 + 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent2.add
251 + EOF
252 +
253 + git status --porcelain=v2 >actual &&
254 + test_cmp expect actual
255 +'
256 +
257 +test_expect_success 'verify AA (add-add) conflict' '
258 + test_when_finished "git reset --hard" &&
259 +
260 + git branch AA_A master &&
261 + git checkout AA_A &&
262 + echo "Branch AA_A" >conflict.txt &&
263 + OID_AA_A=$(git hash-object -t blob -- conflict.txt) &&
264 + git add conflict.txt &&
265 + git commit -m "branch aa_a" &&
266 +
267 + git branch AA_B master &&
268 + git checkout AA_B &&
269 + echo "Branch AA_B" >conflict.txt &&
270 + OID_AA_B=$(git hash-object -t blob -- conflict.txt) &&
271 + git add conflict.txt &&
272 + git commit -m "branch aa_b" &&
273 +
274 + git branch AA_M AA_B &&
275 + git checkout AA_M &&
276 + test_must_fail git merge AA_A &&
277 +
278 + HM=$(git rev-parse HEAD) &&
279 +
280 + cat >expect <<-EOF &&
281 + # branch.oid $HM
282 + # branch.head AA_M
283 + u AA N... 000000 100644 100644 100644 $_z40 $OID_AA_B $OID_AA_A conflict.txt
284 + EOF
285 +
286 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
287 + test_cmp expect actual
288 +'
289 +
290 +test_expect_success 'verify UU (edit-edit) conflict' '
291 + test_when_finished "git reset --hard" &&
292 +
293 + git branch UU_ANC master &&
294 + git checkout UU_ANC &&
295 + echo "Ancestor" >conflict.txt &&
296 + OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) &&
297 + git add conflict.txt &&
298 + git commit -m "UU_ANC" &&
299 +
300 + git branch UU_A UU_ANC &&
301 + git checkout UU_A &&
302 + echo "Branch UU_A" >conflict.txt &&
303 + OID_UU_A=$(git hash-object -t blob -- conflict.txt) &&
304 + git add conflict.txt &&
305 + git commit -m "branch uu_a" &&
306 +
307 + git branch UU_B UU_ANC &&
308 + git checkout UU_B &&
309 + echo "Branch UU_B" >conflict.txt &&
310 + OID_UU_B=$(git hash-object -t blob -- conflict.txt) &&
311 + git add conflict.txt &&
312 + git commit -m "branch uu_b" &&
313 +
314 + git branch UU_M UU_B &&
315 + git checkout UU_M &&
316 + test_must_fail git merge UU_A &&
317 +
318 + HM=$(git rev-parse HEAD) &&
319 +
320 + cat >expect <<-EOF &&
321 + # branch.oid $HM
322 + # branch.head UU_M
323 + u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt
324 + EOF
325 +
326 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
327 + test_cmp expect actual
328 +'
329 +
330 +test_expect_success 'verify upstream fields in branch header' '
331 + git checkout master &&
332 + test_when_finished "rm -rf sub_repo" &&
333 + git clone . sub_repo &&
334 + (
335 + ## Confirm local master tracks remote master.
336 + cd sub_repo &&
337 + HUF=$(git rev-parse HEAD) &&
338 +
339 + cat >expect <<-EOF &&
340 + # branch.oid $HUF
341 + # branch.head master
342 + # branch.upstream origin/master
343 + # branch.ab +0 -0
344 + EOF
345 +
346 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
347 + test_cmp expect actual &&
348 +
349 + ## Test ahead/behind.
350 + echo xyz >file_xyz &&
351 + git add file_xyz &&
352 + git commit -m xyz &&
353 +
354 + HUF=$(git rev-parse HEAD) &&
355 +
356 + cat >expect <<-EOF &&
357 + # branch.oid $HUF
358 + # branch.head master
359 + # branch.upstream origin/master
360 + # branch.ab +1 -0
361 + EOF
362 +
363 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
364 + test_cmp expect actual &&
365 +
366 + ## Repeat the above but without --branch.
367 + cat >expect <<-EOF &&
368 + EOF
369 +
370 + git status --porcelain=v2 --untracked-files=all >actual &&
371 + test_cmp expect actual &&
372 +
373 + ## Test upstream-gone case. Fake this by pointing origin/master at
374 + ## a non-existing commit.
375 + OLD=$(git rev-parse origin/master) &&
376 + NEW=$_z40 &&
377 + mv .git/packed-refs .git/old-packed-refs &&
378 + sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs &&
379 +
380 + HUF=$(git rev-parse HEAD) &&
381 +
382 + cat >expect <<-EOF &&
383 + # branch.oid $HUF
384 + # branch.head master
385 + # branch.upstream origin/master
386 + EOF
387 +
388 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
389 + test_cmp expect actual
390 + )
391 +'
392 +
393 +test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
394 + git checkout master &&
395 + git clone . sub_repo &&
396 + git clone . super_repo &&
397 + ( cd super_repo &&
398 + git submodule add ../sub_repo sub1 &&
399 +
400 + ## Confirm stage/add of clean submodule.
401 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
402 + HSUP=$(git rev-parse HEAD) &&
403 + HSUB=$HSUP &&
404 +
405 + cat >expect <<-EOF &&
406 + # branch.oid $HSUP
407 + # branch.head master
408 + # branch.upstream origin/master
409 + # branch.ab +0 -0
410 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
411 + 1 A. S... 000000 160000 160000 $_z40 $HSUB sub1
412 + EOF
413 +
414 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
415 + test_cmp expect actual
416 + )
417 +'
418 +
419 +test_expect_success 'untracked changes in added submodule (AM S..U)' '
420 + ( cd super_repo &&
421 + ## create untracked file in the submodule.
422 + ( cd sub1 &&
423 + echo "xxxx" >file_in_sub
424 + ) &&
425 +
426 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
427 + HSUP=$(git rev-parse HEAD) &&
428 + HSUB=$HSUP &&
429 +
430 + cat >expect <<-EOF &&
431 + # branch.oid $HSUP
432 + # branch.head master
433 + # branch.upstream origin/master
434 + # branch.ab +0 -0
435 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
436 + 1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1
437 + EOF
438 +
439 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
440 + test_cmp expect actual
441 + )
442 +'
443 +
444 +test_expect_success 'staged changes in added submodule (AM S.M.)' '
445 + ( cd super_repo &&
446 + ## stage the changes in the submodule.
447 + ( cd sub1 &&
448 + git add file_in_sub
449 + ) &&
450 +
451 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
452 + HSUP=$(git rev-parse HEAD) &&
453 + HSUB=$HSUP &&
454 +
455 + cat >expect <<-EOF &&
456 + # branch.oid $HSUP
457 + # branch.head master
458 + # branch.upstream origin/master
459 + # branch.ab +0 -0
460 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
461 + 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
462 + EOF
463 +
464 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
465 + test_cmp expect actual
466 + )
467 +'
468 +
469 +test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
470 + ( cd super_repo &&
471 + ( cd sub1 &&
472 + ## make additional unstaged changes (on the same file) in the submodule.
473 + ## This does not cause us to get S.MU (because the submodule does not report
474 + ## a "?" line for the unstaged changes).
475 + echo "more changes" >>file_in_sub
476 + ) &&
477 +
478 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
479 + HSUP=$(git rev-parse HEAD) &&
480 + HSUB=$HSUP &&
481 +
482 + cat >expect <<-EOF &&
483 + # branch.oid $HSUP
484 + # branch.head master
485 + # branch.upstream origin/master
486 + # branch.ab +0 -0
487 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
488 + 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
489 + EOF
490 +
491 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
492 + test_cmp expect actual
493 + )
494 +'
495 +
496 +test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
497 + ( cd super_repo &&
498 + ( cd sub1 &&
499 + ## stage new changes in tracked file.
500 + git add file_in_sub &&
501 + ## create new untracked file.
502 + echo "yyyy" >>another_file_in_sub
503 + ) &&
504 +
505 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
506 + HSUP=$(git rev-parse HEAD) &&
507 + HSUB=$HSUP &&
508 +
509 + cat >expect <<-EOF &&
510 + # branch.oid $HSUP
511 + # branch.head master
512 + # branch.upstream origin/master
513 + # branch.ab +0 -0
514 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
515 + 1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1
516 + EOF
517 +
518 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
519 + test_cmp expect actual
520 + )
521 +'
522 +
523 +test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
524 + ( cd super_repo &&
525 + ( cd sub1 &&
526 + ## Make a new commit in the submodule.
527 + git add file_in_sub &&
528 + rm -f another_file_in_sub &&
529 + git commit -m "new commit"
530 + ) &&
531 +
532 + HMOD=$(git hash-object -t blob -- .gitmodules) &&
533 + HSUP=$(git rev-parse HEAD) &&
534 + HSUB=$HSUP &&
535 +
536 + cat >expect <<-EOF &&
537 + # branch.oid $HSUP
538 + # branch.head master
539 + # branch.upstream origin/master
540 + # branch.ab +0 -0
541 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
542 + 1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1
543 + EOF
544 +
545 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
546 + test_cmp expect actual
547 + )
548 +'
549 +
550 +test_expect_success 'stage submodule in super and commit' '
551 + ( cd super_repo &&
552 + ## Stage the new submodule commit in the super.
553 + git add sub1 &&
554 + ## Commit the super so that the sub no longer appears as added.
555 + git commit -m "super commit" &&
556 +
557 + HSUP=$(git rev-parse HEAD) &&
558 +
559 + cat >expect <<-EOF &&
560 + # branch.oid $HSUP
561 + # branch.head master
562 + # branch.upstream origin/master
563 + # branch.ab +1 -0
564 + EOF
565 +
566 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
567 + test_cmp expect actual
568 + )
569 +'
570 +
571 +test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
572 + ( cd super_repo &&
573 + ( cd sub1 &&
574 + echo "zzzz" >>file_in_sub
575 + ) &&
576 +
577 + HSUP=$(git rev-parse HEAD) &&
578 + HSUB=$(cd sub1 && git rev-parse HEAD) &&
579 +
580 + cat >expect <<-EOF &&
581 + # branch.oid $HSUP
582 + # branch.head master
583 + # branch.upstream origin/master
584 + # branch.ab +1 -0
585 + 1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
586 + EOF
587 +
588 + git status --porcelain=v2 --branch --untracked-files=all >actual &&
589 + test_cmp expect actual
590 + )
591 +'
592 +
593 +test_done