1
+#!/bin/sh
2
+
3
+test_description='git log --graph visual root indentations'
4
+
5
+. ./test-lib.sh
6
+. "$TEST_DIRECTORY"/lib-log-graph.sh
7
+
8
+check_graph_with_description () {
9
+ cat >expect &&
10
+ lib_test_cmp_graph --format="%s%ndescription%nsecond-line" "$@"
11
+}
12
+
13
+create_orphan () {
14
+ git checkout --orphan "$1" &&
15
+ test_might_fail git rm -rf .
16
+}
17
+
18
+# disable commit-graph topo order to have the graph to render in different
19
+# ways (used in --first-parent tests to have multiple visual roots while a
20
+# column is active at the same time).
21
+unset_commit_graph () {
22
+ sane_unset GIT_TEST_COMMIT_GRAPH &&
23
+ rm -f .git/objects/info/commit-graph &&
24
+ rm -rf .git/objects/info/commit-graphs
25
+}
26
+
27
+test_expect_success 'single root commit is not indented' '
28
+ create_orphan _1 && test_commit 1_A &&
29
+ lib_test_check_graph _1 <<-\EOF
30
+ * 1_A
31
+ EOF
32
+'
33
+
34
+test_expect_success 'visual root indented before unrelated branch' '
35
+ create_orphan _2 && test_commit 2_A && test_commit 2_B &&
36
+ create_orphan _3 && test_commit 3_A &&
37
+ lib_test_check_graph _2 _3 <<-\EOF
38
+ * 3_A
39
+ * 2_B
40
+ * 2_A
41
+ EOF
42
+'
43
+
44
+test_expect_success 'visual root indentation with --left-right' '
45
+ lib_test_check_graph --left-right _2..._3 <<-\EOF
46
+ > 3_A
47
+ < 2_B
48
+ < 2_A
49
+ EOF
50
+'
51
+
52
+# A better case of why indentation is still needed with '--left-right' flag is
53
+# that unrelated branches can be on the same side, so it's needed to
54
+# differentiate visual roots on the same side.
55
+test_expect_success 'visual root indentation with --left-right having unrelated commits on the same side' '
56
+ lib_test_check_graph --left-right _2..._3 _1 <<-\EOF
57
+ > 3_A
58
+ < 2_B
59
+ \
60
+ < 2_A
61
+ > 1_A
62
+ EOF
63
+'
64
+
65
+test_expect_success 'visual root indents the description also' '
66
+ check_graph_with_description _2 _3 <<-\EOF
67
+ * 3_A
68
+ description
69
+ second-line
70
+ * 2_B
71
+ | description
72
+ | second-line
73
+ * 2_A
74
+ description
75
+ second-line
76
+ EOF
77
+'
78
+
79
+test_expect_success 'indented visual root parent gets connected to its child' '
80
+ create_orphan _4 && test_commit 4_A && test_commit 4_B &&
81
+ create_orphan _5 && test_commit 5_A && test_commit 5_B &&
82
+ lib_test_check_graph _4 _5 <<-\EOF
83
+ * 5_B
84
+ \
85
+ * 5_A
86
+ * 4_B
87
+ * 4_A
88
+ EOF
89
+'
90
+
91
+test_expect_success 'indented visual root parent gets connected to its child with description' '
92
+ check_graph_with_description _4 _5 <<-\EOF
93
+ * 5_B
94
+ | description
95
+ | second-line
96
+ \
97
+ * 5_A
98
+ description
99
+ second-line
100
+ * 4_B
101
+ | description
102
+ | second-line
103
+ * 4_A
104
+ description
105
+ second-line
106
+ EOF
107
+'
108
+
109
+test_expect_success 'visual roots cascade and last root does not' '
110
+ create_orphan _7 && test_commit 7_A && test_commit 7_B &&
111
+ create_orphan _8 && test_commit 8_A &&
112
+ create_orphan _9 && test_commit 9_A &&
113
+ create_orphan _10 && test_commit 10_A &&
114
+ lib_test_check_graph _7 _8 _9 _10 <<-\EOF
115
+ * 10_A
116
+ * 9_A
117
+ * 8_A
118
+ * 7_B
119
+ * 7_A
120
+ EOF
121
+'
122
+
123
+test_expect_success 'last root does not cascade' '
124
+ lib_test_check_graph _8 _9 _10 <<-\EOF
125
+ * 10_A
126
+ * 9_A
127
+ * 8_A
128
+ EOF
129
+'
130
+
131
+test_expect_success 'merge parents are roots between them but they do not indent' '
132
+ create_orphan _11 && test_commit 11_A &&
133
+ create_orphan _12 && test_commit 12_A &&
134
+ create_orphan _13 && test_commit 13_A &&
135
+ git checkout _11 &&
136
+ TREE=$(git write-tree) &&
137
+ MERGE=$(git commit-tree $TREE -p _11 -p _12 -p _13 -m 11_octopus) &&
138
+ git reset --hard $MERGE &&
139
+ lib_test_check_graph _11 <<-\EOF
140
+ *-. 11_octopus
141
+ |\ \
142
+ | | * 13_A
143
+ | * 12_A
144
+ * 11_A
145
+ EOF
146
+'
147
+
148
+# The last parent of a merge can be indented if nothing related to it needs to
149
+# be rendered after, if it's another visual root, merge parent must not get
150
+# indented but rather activate cascading.
151
+test_expect_success 'merge then unrelated visual root and unrelated branch' '
152
+ create_orphan _16 && test_commit 16_A && test_commit 16_B &&
153
+ create_orphan _17 && test_commit 17_A &&
154
+ create_orphan _18 && test_commit 18_A &&
155
+ create_orphan _19 && test_commit 19_A &&
156
+ create_orphan _20 && test_commit 20_A &&
157
+ git checkout _18 &&
158
+ TREE=$(git write-tree) &&
159
+ MERGE=$(git commit-tree $TREE -p _18 -p _19 -p _20 -m 18_octopus) &&
160
+ git reset --hard $MERGE &&
161
+ lib_test_check_graph _18 _17 _16 <<-\EOF
162
+ *-. 18_octopus
163
+ |\ \
164
+ | | * 20_A
165
+ | * 19_A
166
+ * 18_A
167
+ * 17_A
168
+ * 16_B
169
+ * 16_A
170
+ EOF
171
+'
172
+
173
+# The last commit root does not get indented, if the next thing after the root
174
+# merge parent is the last commit, indent the merge parent.
175
+test_expect_success 'merge then unrelated root indents merge parent' '
176
+ lib_test_check_graph _18 _17 <<-\EOF
177
+ *-. 18_octopus
178
+ |\ \
179
+ | | * 20_A
180
+ | * 19_A
181
+ \
182
+ * 18_A
183
+ * 17_A
184
+ EOF
185
+'
186
+
187
+test_expect_success 'merge then unrelated branch indents merge parent' '
188
+ lib_test_check_graph _18 _16 <<-\EOF
189
+ *-. 18_octopus
190
+ |\ \
191
+ | | * 20_A
192
+ | * 19_A
193
+ \
194
+ * 18_A
195
+ * 16_B
196
+ * 16_A
197
+ EOF
198
+'
199
+
200
+test_expect_success 'two-parent merge of orphans' '
201
+ create_orphan _21 && test_commit 21_A &&
202
+ create_orphan _22 && test_commit 22_A &&
203
+ git checkout _21 &&
204
+ TREE=$(git write-tree) &&
205
+ MERGE=$(git commit-tree $TREE -p _21 -p _22 -m 21_merge) &&
206
+ git reset --hard $MERGE &&
207
+ lib_test_check_graph _21 <<-\EOF
208
+ * 21_merge
209
+ |\
210
+ | * 22_A
211
+ * 21_A
212
+ EOF
213
+'
214
+
215
+test_expect_success 'commit with filtered parent becomes a visual root' '
216
+ create_orphan _23 &&
217
+ echo test >other.txt &&
218
+ git add other.txt &&
219
+ git commit -m "23_A" &&
220
+ echo test >foo.txt &&
221
+ git add foo.txt &&
222
+ git commit -m "23_B" &&
223
+ create_orphan _24 &&
224
+ echo test >foo.txt &&
225
+ git add foo.txt &&
226
+ git commit -m "24_A" &&
227
+ lib_test_check_graph _23 _24 -- foo.txt <<-\EOF
228
+ * 23_B
229
+ * 24_A
230
+ EOF
231
+'
232
+
233
+test_expect_success 'filtered parent cascading edge case' '
234
+ create_orphan _27 &&
235
+ echo test >foo.txt &&
236
+ git add foo.txt &&
237
+ test_tick &&
238
+ git commit -m "D (last)" &&
239
+
240
+ create_orphan _25 &&
241
+ echo test >other.txt &&
242
+ git add other.txt &&
243
+ test_tick &&
244
+ git commit -m "C-filtered" &&
245
+
246
+ echo test >foo.txt &&
247
+ git add foo.txt &&
248
+ test_tick &&
249
+ git commit -m "B (child of filtered)" &&
250
+
251
+ create_orphan _26 &&
252
+ echo test >foo.txt &&
253
+ git add foo.txt &&
254
+ test_tick &&
255
+ git commit -m "A (visual root)" &&
256
+
257
+ lib_test_check_graph _25 _26 _27 -- foo.txt <<-\EOF
258
+ * A (visual root)
259
+ * B (child of filtered)
260
+ * D (last)
261
+ EOF
262
+'
263
+
264
+test_expect_success 'multiple filtered parents in sequence' '
265
+ create_orphan _44 &&
266
+ echo a >other.txt && git add other.txt && git commit -m "44_F" &&
267
+ echo b >foo.txt && git add foo.txt && git commit -m "44_C" &&
268
+
269
+ create_orphan _45 &&
270
+ echo c >other.txt && git add other.txt && git commit -m "45_F" &&
271
+ echo d >foo.txt && git add foo.txt && git commit -m "45_C" &&
272
+
273
+ create_orphan _46 &&
274
+ echo e >foo.txt && git add foo.txt && git commit -m "46_A" &&
275
+
276
+ lib_test_check_graph _44 _45 _46 -- foo.txt <<-\EOF
277
+ * 44_C
278
+ * 45_C
279
+ * 46_A
280
+ EOF
281
+'
282
+
283
+# These tests prove why there is no need to have indentation for boundary
284
+# commits.
285
+#
286
+# Boundary commits rather than starting a column they 'inherit' the one of
287
+# its child so there will always be an edge that connects it removing the
288
+# ambiguity.
289
+test_expect_success 'unrelated boundaries are not ambiguous' '
290
+ create_orphan _28 && test_commit 28_A && test_commit 28_B &&
291
+ test_commit 28_C &&
292
+ create_orphan _29 && test_commit 29_A && test_commit 29_B &&
293
+ lib_test_check_graph --boundary 28_A.._28 29_A.._29 <<-\EOF
294
+ * 29_B
295
+ | * 28_C
296
+ | * 28_B
297
+ | o 28_A
298
+ o 29_A
299
+ EOF
300
+'
301
+
302
+# Same structure as t6016
303
+test_expect_success 'boundary commits big test' '
304
+ # 3 commits on branch _30
305
+ create_orphan _30 &&
306
+ test_commit 30_A &&
307
+ test_commit 30_B &&
308
+ test_commit 30_C &&
309
+
310
+ # 2 commits on branch _31, started from 30_A
311
+ git checkout -b _31 30_A &&
312
+ test_commit 31_A &&
313
+ test_commit 31_B &&
314
+
315
+ # 2 commits on branch _32, started from 30_B
316
+ git checkout -b _32 30_B &&
317
+ test_commit 32_A &&
318
+ test_commit 32_B &&
319
+
320
+ # Octopus merge _31 and _32 into -30
321
+ git checkout _30 &&
322
+ git merge _31 _32 -m 30_D &&
323
+ git tag 30_D &&
324
+ test_commit 30_E &&
325
+
326
+ # More commits on _32, then merge _32 into _30
327
+ git checkout _32 &&
328
+ test_commit 32_C &&
329
+ test_commit 32_D &&
330
+ git checkout _30 &&
331
+ git merge -s ours _32 -m 30_F &&
332
+ git tag 30_F &&
333
+ test_commit 30_G &&
334
+ lib_test_check_graph --boundary _30 _31 _32 ^32_C <<-\EOF
335
+ * 30_G
336
+ * 30_F
337
+ |\
338
+ | * 32_D
339
+ * | 30_E
340
+ | |
341
+ | \
342
+ *-. \ 30_D
343
+ |\ \ \
344
+ | * | | 31_B
345
+ | * | | 31_A
346
+ * | | | 30_C
347
+ o | | | 30_B
348
+ |/ / /
349
+ o / / 30_A
350
+ / /
351
+ | o 32_C
352
+ |/
353
+ o 32_B
354
+ EOF
355
+'
356
+
357
+# Filter by --first-parent and then forcing the filtered parents to be shown.
358
+test_expect_success '--first-parent flag with the filtered parents' '
359
+ (
360
+ unset_commit_graph &&
361
+ create_orphan _35 && test_commit 35_A && test_commit 35_B &&
362
+ create_orphan _36 && test_commit 36_A &&
363
+ create_orphan _37 && test_commit 37_A &&
364
+ git checkout _35 &&
365
+ TREE=$(git write-tree) &&
366
+ MERGE=$(git commit-tree $TREE -p _35 -p _36 -p _37 -m 35_octopus) &&
367
+ git reset --hard $MERGE &&
368
+ lib_test_check_graph --first-parent _35 _36 _37 <<-\EOF
369
+ * 35_octopus
370
+ | * 37_A
371
+ | * 36_A
372
+ * 35_B
373
+ * 35_A
374
+ EOF
375
+ )
376
+'
377
+
378
+test_expect_success '--first-parent with filtered parents but one has a child' '
379
+ (
380
+ unset_commit_graph &&
381
+ create_orphan _38 && test_commit 38_A && test_commit 38_B &&
382
+ create_orphan _39 && test_commit 39_A &&
383
+ create_orphan _40 && test_commit 40_A && test_commit 40_B &&
384
+ git checkout _38 &&
385
+ TREE=$(git write-tree) &&
386
+ MERGE=$(git commit-tree $TREE -p _38 -p _39 -p _40 -m 38_octopus) &&
387
+ git reset --hard $MERGE &&
388
+ lib_test_check_graph --first-parent _38 _39 _40 <<-\EOF
389
+ * 38_octopus
390
+ | * 40_B
391
+ | * 40_A
392
+ | * 39_A
393
+ * 38_B
394
+ * 38_A
395
+ EOF
396
+ )
397
+'
398
+
399
+test_expect_success '--first-parent with filtered parents but both have children' '
400
+ (
401
+ unset_commit_graph &&
402
+ create_orphan _41 && test_commit 41_A && test_commit 41_B &&
403
+ create_orphan _42 && test_commit 42_A && test_commit 42_B &&
404
+ create_orphan _43 && test_commit 43_A && test_commit 43_B &&
405
+ git checkout _41 &&
406
+ TREE=$(git write-tree) &&
407
+ MERGE=$(git commit-tree $TREE -p _41 -p _42 -p _43 -m 41_octopus) &&
408
+ git reset --hard $MERGE &&
409
+ lib_test_check_graph --first-parent _41 _42 _43 <<-\EOF
410
+ * 41_octopus
411
+ | * 43_B
412
+ | \
413
+ | * 43_A
414
+ | * 42_B
415
+ | * 42_A
416
+ * 41_B
417
+ * 41_A
418
+ EOF
419
+ )
420
+'
421
+
422
+test_expect_success 'two unrelated merges' '
423
+ create_orphan _50 && test_commit 50_A &&
424
+ git checkout -b _51 &&
425
+ test_commit 51_A && test_commit 51_B &&
426
+ git checkout _50 &&
427
+ git merge --no-ff _51 -m 50_B &&
428
+
429
+ create_orphan _52 && test_commit 52_A &&
430
+ git checkout -b _53 &&
431
+ test_commit 53_A && test_commit 53_B &&
432
+ git checkout _52 &&
433
+ git merge --no-ff _53 -m 52_B &&
434
+
435
+ lib_test_check_graph _52 _50 <<-\EOF
436
+ * 52_B
437
+ |\
438
+ | * 53_B
439
+ | * 53_A
440
+ |/
441
+ \
442
+ * 52_A
443
+ * 50_B
444
+ |\
445
+ | * 51_B
446
+ | * 51_A
447
+ |/
448
+ * 50_A
449
+ EOF
450
+'
451
+
452
+test_expect_success '--max-count treats the last visible commit as the last commit' '
453
+ lib_test_check_graph --max-count=2 _8 _9 _10 <<-\EOF
454
+ * 10_A
455
+ * 9_A
456
+ EOF
457
+'
458
+
459
+test_expect_success '--max-count=1 shows a single root without indentation' '
460
+ lib_test_check_graph --max-count=1 _8 _9 _10 <<-\EOF
461
+ * 10_A
462
+ EOF
463
+'
464
+
465
+test_expect_success '--max-count-oldest indents visual roots' '
466
+ lib_test_check_graph --max-count-oldest=3 _8 _9 _10 <<-\EOF
467
+ * 10_A
468
+ * 9_A
469
+ * 8_A
470
+ EOF
471
+'
472
+
473
+# when the graph commits are filtered with regex options like --author, the
474
+# commit parents do not come NULL so it is needed to check if the parents are
475
+# interesting.
476
+test_expect_success '--author skipped parent makes a visual root' '
477
+ create_orphan _55 &&
478
+ test_tick &&
479
+ git commit --allow-empty -m 55_A &&
480
+ create_orphan _54 &&
481
+ test_tick &&
482
+ git commit --allow-empty --author="Other <other@example.com>" -m 54_A &&
483
+ test_tick &&
484
+ git commit --allow-empty -m 54_B &&
485
+ test_tick &&
486
+ git commit --allow-empty -m 54_C &&
487
+ lib_test_check_graph --author="A U Thor" _54 _55 <<-\EOF
488
+ * 54_C
489
+ \
490
+ * 54_B
491
+ * 55_A
492
+ EOF
493
+'
494
+
495
+test_expect_success '--grep skipped parent makes a visual root' '
496
+ create_orphan _57 &&
497
+ test_tick &&
498
+ git commit --allow-empty -m 57_keep_A &&
499
+ create_orphan _56 &&
500
+ test_tick &&
501
+ git commit --allow-empty -m 56_skip &&
502
+ test_tick &&
503
+ git commit --allow-empty -m 56_keep_A &&
504
+ test_tick &&
505
+ git commit --allow-empty -m 56_keep_B &&
506
+ lib_test_check_graph --grep=keep _56 _57 <<-\EOF
507
+ * 56_keep_B
508
+ \
509
+ * 56_keep_A
510
+ * 57_keep_A
511
+ EOF
512
+'
513
+
514
+test_done