aboutsummaryrefslogtreecommitdiff
path: root/t/t1000-read-tree-m-3way.sh
blob: 3c4d2d6045bf026cf164374a41ae759d08a69bf8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#

test_description='Three way merge with read-tree -m

This test tries three-way merge with read-tree -m

There is one ancestor (called O for Original) and two branches A
and B derived from it.  We want to do a 3-way merge between A and
B, using O as the common ancestor.

    merge A O B

Decisions are made by comparing contents of O, A and B pathname
by pathname.  The result is determined by the following guiding
principle:

 - If only A does something to it and B does not touch it, take
   whatever A does.

 - If only B does something to it and A does not touch it, take
   whatever B does.

 - If both A and B does something but in the same way, take
   whatever they do.

 - If A and B does something but different things, we need a
   3-way merge:

   - We cannot do anything about the following cases:

     * O does not have it.  A and B both must be adding to the
       same path independently.

     * A deletes it.  B must be modifying.

   - Otherwise, A and B are modifying.  Run 3-way merge.

First, the case matrix.

 - Vertical axis is for A'\''s actions.
 - Horizontal axis is for B'\''s actions.

.----------------------------------------------------------------.
| A        B | No Action  |   Delete   |   Modify   |    Add     |
|------------+------------+------------+------------+------------|
| No Action  |            |            |            |            |
|            | select O   | delete     | select B   | select B   |
|            |            |            |            |            |
|------------+------------+------------+------------+------------|
| Delete     |            |            | ********** |    can     |
|            | delete     | delete     | merge      |    not     |
|            |            |            |            |  happen    |
|------------+------------+------------+------------+------------|
| Modify     |            | ********** | ?????????? |    can     |
|            | select A   | merge      | select A=B |    not     |
|            |            |            | merge      |  happen    |
|------------+------------+------------+------------+------------|
| Add        |            |    can     |    can     | ?????????? |
|            | select A   |    not     |    not     | select A=B |
|            |            |  happen    |  happen    | merge      |
.----------------------------------------------------------------.

In addition:

 SS: a special case of MM, where A and B makes the same modification.
 LL: a special case of AA, where A and B creates the same file.
 TT: a special case of MM, where A and B makes mergeable changes.
 DF: a special case, where A makes a directory and B makes a file.

'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-read-tree.sh
. "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh

################################################################
# Trivial "majority when 3 stages exist" merge plus #2ALT, #3ALT
# and #5ALT trivial merges.

cat >expected <<\EOF
100644 X 2	AA
100644 X 3	AA
100644 X 0	AN
100644 X 1	DD
100644 X 3	DF
100644 X 2	DF/DF
100644 X 1	DM
100644 X 3	DM
100644 X 1	DN
100644 X 3	DN
100644 X 0	LL
100644 X 1	MD
100644 X 2	MD
100644 X 1	MM
100644 X 2	MM
100644 X 3	MM
100644 X 0	MN
100644 X 0	NA
100644 X 1	ND
100644 X 2	ND
100644 X 0	NM
100644 X 0	NN
100644 X 0	SS
100644 X 1	TT
100644 X 2	TT
100644 X 3	TT
100644 X 2	Z/AA
100644 X 3	Z/AA
100644 X 0	Z/AN
100644 X 1	Z/DD
100644 X 1	Z/DM
100644 X 3	Z/DM
100644 X 1	Z/DN
100644 X 3	Z/DN
100644 X 1	Z/MD
100644 X 2	Z/MD
100644 X 1	Z/MM
100644 X 2	Z/MM
100644 X 3	Z/MM
100644 X 0	Z/MN
100644 X 0	Z/NA
100644 X 1	Z/ND
100644 X 2	Z/ND
100644 X 0	Z/NM
100644 X 0	Z/NN
EOF

check_result () {
	git ls-files --stage | sed -e 's/ '"$_x40"' / X /' >current &&
	test_cmp expected current
}

# This is done on an empty work directory, which is the normal
# merge person behaviour.
test_expect_success '3-way merge with git read-tree -m, empty cache' '
	rm -fr [NDMALTS][NDMALTSF] Z &&
	rm .git/index &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

# This starts out with the first head, which is the normal
# patch submitter behaviour.
test_expect_success '3-way merge with git read-tree -m, match H' '
	rm -fr [NDMALTS][NDMALTSF] Z &&
	rm .git/index &&
	read_tree_must_succeed $tree_A &&
	git checkout-index -f -u -a &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

: <<\END_OF_CASE_TABLE

We have so far tested only empty index and clean-and-matching-A index
case which are trivial.  Make sure index requirements are also
checked.

"git read-tree -m O A B"

     O       A       B         result      index requirements
-------------------------------------------------------------------
  1  missing missing missing   -           must not exist.
 ------------------------------------------------------------------
  2  missing missing exists    take B*     must match B, if exists.
 ------------------------------------------------------------------
  3  missing exists  missing   take A*     must match A, if exists.
 ------------------------------------------------------------------
  4  missing exists  A!=B      no merge    must match A and be
                                           up-to-date, if exists.
 ------------------------------------------------------------------
  5  missing exists  A==B      take A      must match A, if exists.
 ------------------------------------------------------------------
  6  exists  missing missing   remove      must not exist.
 ------------------------------------------------------------------
  7  exists  missing O!=B      no merge    must not exist.
 ------------------------------------------------------------------
  8  exists  missing O==B      remove      must not exist.
 ------------------------------------------------------------------
  9  exists  O!=A    missing   no merge    must match A and be
                                           up-to-date, if exists.
 ------------------------------------------------------------------
 10  exists  O==A    missing   no merge    must match A
 ------------------------------------------------------------------
 11  exists  O!=A    O!=B      no merge    must match A and be
                     A!=B                  up-to-date, if exists.
 ------------------------------------------------------------------
 12  exists  O!=A    O!=B      take A      must match A, if exists.
                     A==B
 ------------------------------------------------------------------
 13  exists  O!=A    O==B      take A      must match A, if exists.
 ------------------------------------------------------------------
 14  exists  O==A    O!=B      take B      if exists, must either (1)
                                           match A and be up-to-date,
                                           or (2) match B.
 ------------------------------------------------------------------
 15  exists  O==A    O==B      take B      must match A if exists.
 ------------------------------------------------------------------
 16  exists  O==A    O==B      barf        must match A if exists.
     *multi* in one  in another
-------------------------------------------------------------------

Note: we need to be careful in case 2 and 3.  The tree A may contain
DF (file) when tree B require DF to be a directory by having DF/DF
(file).

END_OF_CASE_TABLE

test_expect_success '1 - must not have an entry not in A.' '
	rm -f .git/index XX &&
	echo XX >XX &&
	git update-index --add XX &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '2 - must match B in !O && !A && B case.' '
	rm -f .git/index NA &&
	cp .orig-B/NA NA &&
	git update-index --add NA &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B
'

test_expect_success '2 - matching B alone is OK in !O && !A && B case.' '
	rm -f .git/index NA &&
	cp .orig-B/NA NA &&
	git update-index --add NA &&
	echo extra >>NA &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B
'

test_expect_success '3 - must match A in !O && A && !B case.' '
	rm -f .git/index AN &&
	cp .orig-A/AN AN &&
	git update-index --add AN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '3 - matching A alone is OK in !O && A && !B case.' '
	rm -f .git/index AN &&
	cp .orig-A/AN AN &&
	git update-index --add AN &&
	echo extra >>AN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B
'

test_expect_success '3 (fail) - must match A in !O && A && !B case.' '
	rm -f .git/index AN &&
	cp .orig-A/AN AN &&
	echo extra >>AN &&
	git update-index --add AN &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '4 - must match and be up-to-date in !O && A && B && A!=B case.' '
	rm -f .git/index AA &&
	cp .orig-A/AA AA &&
	git update-index --add AA &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '
	rm -f .git/index AA &&
	cp .orig-A/AA AA &&
	git update-index --add AA &&
	echo extra >>AA &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '4 (fail) - must match and be up-to-date in !O && A && B && A!=B case.' '
	rm -f .git/index AA &&
	cp .orig-A/AA AA &&
	echo extra >>AA &&
	git update-index --add AA &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '5 - must match in !O && A && B && A==B case.' '
	rm -f .git/index LL &&
	cp .orig-A/LL LL &&
	git update-index --add LL &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '5 - must match in !O && A && B && A==B case.' '
	rm -f .git/index LL &&
	cp .orig-A/LL LL &&
	git update-index --add LL &&
	echo extra >>LL &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '5 (fail) - must match A in !O && A && B && A==B case.' '
	rm -f .git/index LL &&
	cp .orig-A/LL LL &&
	echo extra >>LL &&
	git update-index --add LL &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '6 - must not exist in O && !A && !B case' '
	rm -f .git/index DD &&
	echo DD >DD &&
	git update-index --add DD &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '7 - must not exist in O && !A && B && O!=B case' '
	rm -f .git/index DM &&
	cp .orig-B/DM DM &&
	git update-index --add DM &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '8 - must not exist in O && !A && B && O==B case' '
	rm -f .git/index DN &&
	cp .orig-B/DN DN &&
	git update-index --add DN &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '9 - must match and be up-to-date in O && A && !B && O!=A case' '
	rm -f .git/index MD &&
	cp .orig-A/MD MD &&
	git update-index --add MD &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' '
	rm -f .git/index MD &&
	cp .orig-A/MD MD &&
	git update-index --add MD &&
	echo extra >>MD &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '9 (fail) - must match and be up-to-date in O && A && !B && O!=A case' '
	rm -f .git/index MD &&
	cp .orig-A/MD MD &&
	echo extra >>MD &&
	git update-index --add MD &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '10 - must match and be up-to-date in O && A && !B && O==A case' '
	rm -f .git/index ND &&
	cp .orig-A/ND ND &&
	git update-index --add ND &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '
	rm -f .git/index ND &&
	cp .orig-A/ND ND &&
	git update-index --add ND &&
	echo extra >>ND &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '10 (fail) - must match and be up-to-date in O && A && !B && O==A case' '
	rm -f .git/index ND &&
	cp .orig-A/ND ND &&
	echo extra >>ND &&
	git update-index --add ND &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '11 - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
	rm -f .git/index MM &&
	cp .orig-A/MM MM &&
	git update-index --add MM &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
	rm -f .git/index MM &&
	cp .orig-A/MM MM &&
	git update-index --add MM &&
	echo extra >>MM &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '11 (fail) - must match and be up-to-date in O && A && B && O!=A && O!=B && A!=B case' '
	rm -f .git/index MM &&
	cp .orig-A/MM MM &&
	echo extra >>MM &&
	git update-index --add MM &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '
	rm -f .git/index SS &&
	cp .orig-A/SS SS &&
	git update-index --add SS &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '12 - must match A in O && A && B && O!=A && A==B case' '
	rm -f .git/index SS &&
	cp .orig-A/SS SS &&
	git update-index --add SS &&
	echo extra >>SS &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '12 (fail) - must match A in O && A && B && O!=A && A==B case' '
	rm -f .git/index SS &&
	cp .orig-A/SS SS &&
	echo extra >>SS &&
	git update-index --add SS &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '
	rm -f .git/index MN &&
	cp .orig-A/MN MN &&
	git update-index --add MN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '13 - must match A in O && A && B && O!=A && O==B case' '
	rm -f .git/index MN &&
	cp .orig-A/MN MN &&
	git update-index --add MN &&
	echo extra >>MN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '14 - must match and be up-to-date in O && A && B && O==A && O!=B case' '
	rm -f .git/index NM &&
	cp .orig-A/NM NM &&
	git update-index --add NM &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '14 - may match B in O && A && B && O==A && O!=B case' '
	rm -f .git/index NM &&
	cp .orig-B/NM NM &&
	git update-index --add NM &&
	echo extra >>NM &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '
	rm -f .git/index NM &&
	cp .orig-A/NM NM &&
	git update-index --add NM &&
	echo extra >>NM &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '14 (fail) - must match and be up-to-date in O && A && B && O==A && O!=B case' '
	rm -f .git/index NM &&
	cp .orig-A/NM NM &&
	echo extra >>NM &&
	git update-index --add NM &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '
	rm -f .git/index NN &&
	cp .orig-A/NN NN &&
	git update-index --add NN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '15 - must match A in O && A && B && O==A && O==B case' '
	rm -f .git/index NN &&
	cp .orig-A/NN NN &&
	git update-index --add NN &&
	echo extra >>NN &&
	read_tree_must_succeed -m $tree_O $tree_A $tree_B &&
	check_result
'

test_expect_success '15 (fail) - must match A in O && A && B && O==A && O==B case' '
	rm -f .git/index NN &&
	cp .orig-A/NN NN &&
	echo extra >>NN &&
	git update-index --add NN &&
	read_tree_must_fail -m $tree_O $tree_A $tree_B
'

test_expect_success '16 - A matches in one and B matches in another.' '
	rm -f .git/index F16 &&
	echo F16 >F16 &&
	git update-index --add F16 &&
	tree0=$(git write-tree) &&
	echo E16 >F16 &&
	git update-index F16 &&
	tree1=$(git write-tree) &&
	read_tree_must_succeed -m $tree0 $tree1 $tree1 $tree0 &&
	git ls-files --stage
'

test_done