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