directory rename detection: basic testcases
Reviewed-by: Stefan Beller <sbeller@google.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Apr 19, 2018 at 10:57 UTC
04550ab56f3191a27cb8e4f10a7398b396094f58
1 file changed
+442
t/t6043-merge-rename-directories.sh
new
+442
@@ -0,0 +1,442 @@
1
+#!/bin/sh
2
+
3
+test_description="recursive merge with directory renames"
4
+# includes checking of many corner cases, with a similar methodology to:
5
+# t6042: corner cases with renames but not criss-cross merges
6
+# t6036: corner cases with both renames and criss-cross merges
7
+#
8
+# The setup for all of them, pictorially, is:
9
+#
10
+# A
11
+# o
12
+# / \
13
+# O o ?
14
+# \ /
15
+# o
16
+# B
17
+#
18
+# To help make it easier to follow the flow of tests, they have been
19
+# divided into sections and each test will start with a quick explanation
20
+# of what commits O, A, and B contain.
21
+#
22
+# Notation:
23
+# z/{b,c} means files z/b and z/c both exist
24
+# x/d_1 means file x/d exists with content d1. (Purpose of the
25
+# underscore notation is to differentiate different
26
+# files that might be renamed into each other's paths.)
27
+
28
+. ./test-lib.sh
29
+
30
+
31
+###########################################################################
32
+# SECTION 1: Basic cases we should be able to handle
33
+###########################################################################
34
+
35
+# Testcase 1a, Basic directory rename.
36
+# Commit O: z/{b,c}
37
+# Commit A: y/{b,c}
38
+# Commit B: z/{b,c,d,e/f}
39
+# Expected: y/{b,c,d,e/f}
40
+
41
+test_expect_success '1a-setup: Simple directory rename detection' '
42
+ test_create_repo 1a &&
43
+ (
44
+ cd 1a &&
45
+
46
+ mkdir z &&
47
+ echo b >z/b &&
48
+ echo c >z/c &&
49
+ git add z &&
50
+ test_tick &&
51
+ git commit -m "O" &&
52
+
53
+ git branch O &&
54
+ git branch A &&
55
+ git branch B &&
56
+
57
+ git checkout A &&
58
+ git mv z y &&
59
+ test_tick &&
60
+ git commit -m "A" &&
61
+
62
+ git checkout B &&
63
+ echo d >z/d &&
64
+ mkdir z/e &&
65
+ echo f >z/e/f &&
66
+ git add z/d z/e/f &&
67
+ test_tick &&
68
+ git commit -m "B"
69
+ )
70
+'
71
+
72
+test_expect_failure '1a-check: Simple directory rename detection' '
73
+ (
74
+ cd 1a &&
75
+
76
+ git checkout A^0 &&
77
+
78
+ git merge -s recursive B^0 &&
79
+
80
+ git ls-files -s >out &&
81
+ test_line_count = 4 out &&
82
+
83
+ git rev-parse >actual \
84
+ HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e/f &&
85
+ git rev-parse >expect \
86
+ O:z/b O:z/c B:z/d B:z/e/f &&
87
+ test_cmp expect actual &&
88
+
89
+ git hash-object y/d >actual &&
90
+ git rev-parse B:z/d >expect &&
91
+ test_cmp expect actual &&
92
+
93
+ test_must_fail git rev-parse HEAD:z/d &&
94
+ test_must_fail git rev-parse HEAD:z/e/f &&
95
+ test_path_is_missing z/d &&
96
+ test_path_is_missing z/e/f
97
+ )
98
+'
99
+
100
+# Testcase 1b, Merge a directory with another
101
+# Commit O: z/{b,c}, y/d
102
+# Commit A: z/{b,c,e}, y/d
103
+# Commit B: y/{b,c,d}
104
+# Expected: y/{b,c,d,e}
105
+
106
+test_expect_success '1b-setup: Merge a directory with another' '
107
+ test_create_repo 1b &&
108
+ (
109
+ cd 1b &&
110
+
111
+ mkdir z &&
112
+ echo b >z/b &&
113
+ echo c >z/c &&
114
+ mkdir y &&
115
+ echo d >y/d &&
116
+ git add z y &&
117
+ test_tick &&
118
+ git commit -m "O" &&
119
+
120
+ git branch O &&
121
+ git branch A &&
122
+ git branch B &&
123
+
124
+ git checkout A &&
125
+ echo e >z/e &&
126
+ git add z/e &&
127
+ test_tick &&
128
+ git commit -m "A" &&
129
+
130
+ git checkout B &&
131
+ git mv z/b y &&
132
+ git mv z/c y &&
133
+ rmdir z &&
134
+ test_tick &&
135
+ git commit -m "B"
136
+ )
137
+'
138
+
139
+test_expect_failure '1b-check: Merge a directory with another' '
140
+ (
141
+ cd 1b &&
142
+
143
+ git checkout A^0 &&
144
+
145
+ git merge -s recursive B^0 &&
146
+
147
+ git ls-files -s >out &&
148
+ test_line_count = 4 out &&
149
+
150
+ git rev-parse >actual \
151
+ HEAD:y/b HEAD:y/c HEAD:y/d HEAD:y/e &&
152
+ git rev-parse >expect \
153
+ O:z/b O:z/c O:y/d A:z/e &&
154
+ test_cmp expect actual &&
155
+ test_must_fail git rev-parse HEAD:z/e
156
+ )
157
+'
158
+
159
+# Testcase 1c, Transitive renaming
160
+# (Related to testcases 3a and 6d -- when should a transitive rename apply?)
161
+# (Related to testcases 9c and 9d -- can transitivity repeat?)
162
+# Commit O: z/{b,c}, x/d
163
+# Commit A: y/{b,c}, x/d
164
+# Commit B: z/{b,c,d}
165
+# Expected: y/{b,c,d} (because x/d -> z/d -> y/d)
166
+
167
+test_expect_success '1c-setup: Transitive renaming' '
168
+ test_create_repo 1c &&
169
+ (
170
+ cd 1c &&
171
+
172
+ mkdir z &&
173
+ echo b >z/b &&
174
+ echo c >z/c &&
175
+ mkdir x &&
176
+ echo d >x/d &&
177
+ git add z x &&
178
+ test_tick &&
179
+ git commit -m "O" &&
180
+
181
+ git branch O &&
182
+ git branch A &&
183
+ git branch B &&
184
+
185
+ git checkout A &&
186
+ git mv z y &&
187
+ test_tick &&
188
+ git commit -m "A" &&
189
+
190
+ git checkout B &&
191
+ git mv x/d z/d &&
192
+ test_tick &&
193
+ git commit -m "B"
194
+ )
195
+'
196
+
197
+test_expect_failure '1c-check: Transitive renaming' '
198
+ (
199
+ cd 1c &&
200
+
201
+ git checkout A^0 &&
202
+
203
+ git merge -s recursive B^0 &&
204
+
205
+ git ls-files -s >out &&
206
+ test_line_count = 3 out &&
207
+
208
+ git rev-parse >actual \
209
+ HEAD:y/b HEAD:y/c HEAD:y/d &&
210
+ git rev-parse >expect \
211
+ O:z/b O:z/c O:x/d &&
212
+ test_cmp expect actual &&
213
+ test_must_fail git rev-parse HEAD:x/d &&
214
+ test_must_fail git rev-parse HEAD:z/d &&
215
+ test_path_is_missing z/d
216
+ )
217
+'
218
+
219
+# Testcase 1d, Directory renames (merging two directories into one new one)
220
+# cause a rename/rename(2to1) conflict
221
+# (Related to testcases 1c and 7b)
222
+# Commit O. z/{b,c}, y/{d,e}
223
+# Commit A. x/{b,c}, y/{d,e,m,wham_1}
224
+# Commit B. z/{b,c,n,wham_2}, x/{d,e}
225
+# Expected: x/{b,c,d,e,m,n}, CONFLICT:(y/wham_1 & z/wham_2 -> x/wham)
226
+# Note: y/m & z/n should definitely move into x. By the same token, both
227
+# y/wham_1 & z/wham_2 should too...giving us a conflict.
228
+
229
+test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) conflict' '
230
+ test_create_repo 1d &&
231
+ (
232
+ cd 1d &&
233
+
234
+ mkdir z &&
235
+ echo b >z/b &&
236
+ echo c >z/c &&
237
+ mkdir y &&
238
+ echo d >y/d &&
239
+ echo e >y/e &&
240
+ git add z y &&
241
+ test_tick &&
242
+ git commit -m "O" &&
243
+
244
+ git branch O &&
245
+ git branch A &&
246
+ git branch B &&
247
+
248
+ git checkout A &&
249
+ git mv z x &&
250
+ echo m >y/m &&
251
+ echo wham1 >y/wham &&
252
+ git add y &&
253
+ test_tick &&
254
+ git commit -m "A" &&
255
+
256
+ git checkout B &&
257
+ git mv y x &&
258
+ echo n >z/n &&
259
+ echo wham2 >z/wham &&
260
+ git add z &&
261
+ test_tick &&
262
+ git commit -m "B"
263
+ )
264
+'
265
+
266
+test_expect_failure '1d-check: Directory renames cause a rename/rename(2to1) conflict' '
267
+ (
268
+ cd 1d &&
269
+
270
+ git checkout A^0 &&
271
+
272
+ test_must_fail git merge -s recursive B^0 >out &&
273
+ test_i18ngrep "CONFLICT (rename/rename)" out &&
274
+
275
+ git ls-files -s >out &&
276
+ test_line_count = 8 out &&
277
+ git ls-files -u >out &&
278
+ test_line_count = 2 out &&
279
+ git ls-files -o >out &&
280
+ test_line_count = 3 out &&
281
+
282
+ git rev-parse >actual \
283
+ :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n &&
284
+ git rev-parse >expect \
285
+ O:z/b O:z/c O:y/d O:y/e A:y/m B:z/n &&
286
+ test_cmp expect actual &&
287
+
288
+ test_must_fail git rev-parse :0:x/wham &&
289
+ git rev-parse >actual \
290
+ :2:x/wham :3:x/wham &&
291
+ git rev-parse >expect \
292
+ A:y/wham B:z/wham &&
293
+ test_cmp expect actual &&
294
+
295
+ test_path_is_missing x/wham &&
296
+ test_path_is_file x/wham~HEAD &&
297
+ test_path_is_file x/wham~B^0 &&
298
+
299
+ git hash-object >actual \
300
+ x/wham~HEAD x/wham~B^0 &&
301
+ git rev-parse >expect \
302
+ A:y/wham B:z/wham &&
303
+ test_cmp expect actual
304
+ )
305
+'
306
+
307
+# Testcase 1e, Renamed directory, with all filenames being renamed too
308
+# Commit O: z/{oldb,oldc}
309
+# Commit A: y/{newb,newc}
310
+# Commit B: z/{oldb,oldc,d}
311
+# Expected: y/{newb,newc,d}
312
+
313
+test_expect_success '1e-setup: Renamed directory, with all files being renamed too' '
314
+ test_create_repo 1e &&
315
+ (
316
+ cd 1e &&
317
+
318
+ mkdir z &&
319
+ echo b >z/oldb &&
320
+ echo c >z/oldc &&
321
+ git add z &&
322
+ test_tick &&
323
+ git commit -m "O" &&
324
+
325
+ git branch O &&
326
+ git branch A &&
327
+ git branch B &&
328
+
329
+ git checkout A &&
330
+ mkdir y &&
331
+ git mv z/oldb y/newb &&
332
+ git mv z/oldc y/newc &&
333
+ test_tick &&
334
+ git commit -m "A" &&
335
+
336
+ git checkout B &&
337
+ echo d >z/d &&
338
+ git add z/d &&
339
+ test_tick &&
340
+ git commit -m "B"
341
+ )
342
+'
343
+
344
+test_expect_failure '1e-check: Renamed directory, with all files being renamed too' '
345
+ (
346
+ cd 1e &&
347
+
348
+ git checkout A^0 &&
349
+
350
+ git merge -s recursive B^0 &&
351
+
352
+ git ls-files -s >out &&
353
+ test_line_count = 3 out &&
354
+
355
+ git rev-parse >actual \
356
+ HEAD:y/newb HEAD:y/newc HEAD:y/d &&
357
+ git rev-parse >expect \
358
+ O:z/oldb O:z/oldc B:z/d &&
359
+ test_cmp expect actual &&
360
+ test_must_fail git rev-parse HEAD:z/d
361
+ )
362
+'
363
+
364
+# Testcase 1f, Split a directory into two other directories
365
+# (Related to testcases 3a, all of section 2, and all of section 4)
366
+# Commit O: z/{b,c,d,e,f}
367
+# Commit A: z/{b,c,d,e,f,g}
368
+# Commit B: y/{b,c}, x/{d,e,f}
369
+# Expected: y/{b,c}, x/{d,e,f,g}
370
+
371
+test_expect_success '1f-setup: Split a directory into two other directories' '
372
+ test_create_repo 1f &&
373
+ (
374
+ cd 1f &&
375
+
376
+ mkdir z &&
377
+ echo b >z/b &&
378
+ echo c >z/c &&
379
+ echo d >z/d &&
380
+ echo e >z/e &&
381
+ echo f >z/f &&
382
+ git add z &&
383
+ test_tick &&
384
+ git commit -m "O" &&
385
+
386
+ git branch O &&
387
+ git branch A &&
388
+ git branch B &&
389
+
390
+ git checkout A &&
391
+ echo g >z/g &&
392
+ git add z/g &&
393
+ test_tick &&
394
+ git commit -m "A" &&
395
+
396
+ git checkout B &&
397
+ mkdir y &&
398
+ mkdir x &&
399
+ git mv z/b y/ &&
400
+ git mv z/c y/ &&
401
+ git mv z/d x/ &&
402
+ git mv z/e x/ &&
403
+ git mv z/f x/ &&
404
+ rmdir z &&
405
+ test_tick &&
406
+ git commit -m "B"
407
+ )
408
+'
409
+
410
+test_expect_failure '1f-check: Split a directory into two other directories' '
411
+ (
412
+ cd 1f &&
413
+
414
+ git checkout A^0 &&
415
+
416
+ git merge -s recursive B^0 &&
417
+
418
+ git ls-files -s >out &&
419
+ test_line_count = 6 out &&
420
+
421
+ git rev-parse >actual \
422
+ HEAD:y/b HEAD:y/c HEAD:x/d HEAD:x/e HEAD:x/f HEAD:x/g &&
423
+ git rev-parse >expect \
424
+ O:z/b O:z/c O:z/d O:z/e O:z/f A:z/g &&
425
+ test_cmp expect actual &&
426
+ test_path_is_missing z/g &&
427
+ test_must_fail git rev-parse HEAD:z/g
428
+ )
429
+'
430
+
431
+###########################################################################
432
+# Rules suggested by testcases in section 1:
433
+#
434
+# We should still detect the directory rename even if it wasn't just
435
+# the directory renamed, but the files within it. (see 1b)
436
+#
437
+# If renames split a directory into two or more others, the directory
438
+# with the most renames, "wins" (see 1c). However, see the testcases
439
+# in section 2, plus testcases 3a and 4a.
440
+###########################################################################
441
+
442
+test_done