summaryrefslogtreecommitdiff
path: root/t/t4301-merge-tree-write-tree.sh
blob: f091259a55eba49fd632694b08495a4b8e8b0429 (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
#!/bin/sh
 
test_description='git merge-tree --write-tree'
 
. ./test-lib.sh
 
# This test is ort-specific
if test "$GIT_TEST_MERGE_ALGORITHM" != "ort"
then
	skip_all="GIT_TEST_MERGE_ALGORITHM != ort"
	test_done
fi
 
test_expect_success setup '
	test_write_lines 1 2 3 4 5 >numbers &&
	echo hello >greeting &&
	echo foo >whatever &&
	git add numbers greeting whatever &&
	test_tick &&
	git commit -m initial &&
 
	git branch side1 &&
	git branch side2 &&
	git branch side3 &&
 
	git checkout side1 &&
	test_write_lines 1 2 3 4 5 6 >numbers &&
	echo hi >greeting &&
	echo bar >whatever &&
	git add numbers greeting whatever &&
	test_tick &&
	git commit -m modify-stuff &&
 
	git checkout side2 &&
	test_write_lines 0 1 2 3 4 5 >numbers &&
	echo yo >greeting &&
	git rm whatever &&
	mkdir whatever &&
	>whatever/empty &&
	git add numbers greeting whatever/empty &&
	test_tick &&
	git commit -m other-modifications &&
 
	git checkout side3 &&
	git mv numbers sequence &&
	test_tick &&
	git commit -m rename-numbers &&
 
	git switch --orphan unrelated &&
	>something-else &&
	git add something-else &&
	test_tick &&
	git commit -m first-commit
'
 
test_expect_success 'Clean merge' '
	TREE_OID=$(git merge-tree --write-tree side1 side3) &&
	q_to_tab <<-EOF >expect &&
	100644 blob $(git rev-parse side1:greeting)Qgreeting
	100644 blob $(git rev-parse side1:numbers)Qsequence
	100644 blob $(git rev-parse side1:whatever)Qwhatever
	EOF
 
	git ls-tree $TREE_OID >actual &&
	test_cmp expect actual
'
 
test_expect_success 'Content merge and a few conflicts' '
	git checkout side1^0 &&
	test_must_fail git merge side2 &&
	expected_tree=$(git rev-parse AUTO_MERGE) &&
 
	# We will redo the merge, while we are still in a conflicted state!
	git ls-files -u >conflicted-file-info &&
	test_when_finished "git reset --hard" &&
 
	test_expect_code 1 git merge-tree --write-tree side1 side2 >RESULT &&
	actual_tree=$(head -n 1 RESULT) &&
 
	# Due to differences of e.g. "HEAD" vs "side1", the results will not
	# exactly match.  Dig into individual files.
 
	# Numbers should have three-way merged cleanly
	test_write_lines 0 1 2 3 4 5 6 >expect &&
	git show ${actual_tree}:numbers >actual &&
	test_cmp expect actual &&
 
	# whatever and whatever~<branch> should have same HASHES
	git rev-parse ${expected_tree}:whatever ${expected_tree}:whatever~HEAD >expect &&
	git rev-parse ${actual_tree}:whatever ${actual_tree}:whatever~side1 >actual &&
	test_cmp expect actual &&
 
	# greeting should have a merge conflict
	git show ${expected_tree}:greeting >tmp &&
	sed -e s/HEAD/side1/ tmp >expect &&
	git show ${actual_tree}:greeting >actual &&
	test_cmp expect actual
'
 
test_expect_success 'Barf on misspelled option, with exit code other than 0 or 1' '
	# Mis-spell with single "s" instead of double "s"
	test_expect_code 129 git merge-tree --write-tree --mesages FOOBAR side1 side2 2>expect &&
 
	grep "error: unknown option.*mesages" expect
'
 
test_expect_success 'Barf on too many arguments' '
	test_expect_code 129 git merge-tree --write-tree side1 side2 invalid 2>expect &&
 
	grep "^usage: git merge-tree" expect
'
 
anonymize_hash() {
	sed -e "s/[0-9a-f]\{40,\}/HASH/g" "$@"
}
 
test_expect_success 'test conflict notices and such' '
	test_expect_code 1 git merge-tree --write-tree --name-only side1 side2 >out &&
	anonymize_hash out >actual &&
 
	# Expected results:
	#   "greeting" should merge with conflicts
	#   "numbers" should merge cleanly
	#   "whatever" has *both* a modify/delete and a file/directory conflict
	cat <<-EOF >expect &&
	HASH
	greeting
	whatever~side1
 
	Auto-merging greeting
	CONFLICT (content): Merge conflict in greeting
	Auto-merging numbers
	CONFLICT (file/directory): directory in the way of whatever from side1; moving it to whatever~side1 instead.
	CONFLICT (modify/delete): whatever~side1 deleted in side2 and modified in side1.  Version side1 of whatever~side1 left in tree.
	EOF
 
	test_cmp expect actual
'
 
for opt in $(git merge-tree --git-completion-helper-all)
do
	if test $opt = "--trivial-merge" || test $opt = "--write-tree"
	then
		continue
	fi
 
	test_expect_success "usage: --trivial-merge is incompatible with $opt" '
		test_expect_code 128 git merge-tree --trivial-merge $opt side1 side2 side3
	'
done
 
test_expect_success 'Just the conflicted files without the messages' '
	test_expect_code 1 git merge-tree --write-tree --no-messages --name-only side1 side2 >out &&
	anonymize_hash out >actual &&
 
	test_write_lines HASH greeting whatever~side1 >expect &&
 
	test_cmp expect actual
'
 
test_expect_success 'Check conflicted oids and modes without messages' '
	test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out &&
	anonymize_hash out >actual &&
 
	# Compare the basic output format
	q_to_tab >expect <<-\EOF &&
	HASH
	100644 HASH 1Qgreeting
	100644 HASH 2Qgreeting
	100644 HASH 3Qgreeting
	100644 HASH 1Qwhatever~side1
	100644 HASH 2Qwhatever~side1
	EOF
 
	test_cmp expect actual &&
 
	# Check the actual hashes against the `ls-files -u` output too
	tail -n +2 out | sed -e s/side1/HEAD/ >actual &&
	test_cmp conflicted-file-info actual
'
 
test_expect_success 'NUL terminated conflicted file "lines"' '
	git checkout -b tweak1 side1 &&
	test_write_lines zero 1 2 3 4 5 6 >numbers &&
	git add numbers &&
	git mv numbers "Αυτά μου φαίνονται κινέζικα" &&
	git commit -m "Renamed numbers" &&
 
	test_expect_code 1 git merge-tree --write-tree -z tweak1 side2 >out &&
	anonymize_hash out >actual &&
	printf "\\n" >>actual &&
 
	# Expected results:
	#   "greeting" should merge with conflicts
	#   "whatever" has *both* a modify/delete and a file/directory conflict
	#   "Αυτά μου φαίνονται κινέζικα" should have a conflict
	echo HASH | lf_to_nul >expect &&
 
	q_to_tab <<-EOF | lf_to_nul >>expect &&
	100644 HASH 1Qgreeting
	100644 HASH 2Qgreeting
	100644 HASH 3Qgreeting
	100644 HASH 1Qwhatever~tweak1
	100644 HASH 2Qwhatever~tweak1
	100644 HASH 1QΑυτά μου φαίνονται κινέζικα
	100644 HASH 2QΑυτά μου φαίνονται κινέζικα
	100644 HASH 3QΑυτά μου φαίνονται κινέζικα
 
	EOF
 
	q_to_nul <<-EOF >>expect &&
	1QgreetingQAuto-mergingQAuto-merging greeting
	Q1QgreetingQCONFLICT (contents)QCONFLICT (content): Merge conflict in greeting
	Q2Qwhatever~tweak1QwhateverQCONFLICT (file/directory)QCONFLICT (file/directory): directory in the way of whatever from tweak1; moving it to whatever~tweak1 instead.
	Q1Qwhatever~tweak1QCONFLICT (modify/delete)QCONFLICT (modify/delete): whatever~tweak1 deleted in side2 and modified in tweak1.  Version tweak1 of whatever~tweak1 left in tree.
	Q1QΑυτά μου φαίνονται κινέζικαQAuto-mergingQAuto-merging Αυτά μου φαίνονται κινέζικα
	Q1QΑυτά μου φαίνονται κινέζικαQCONFLICT (contents)QCONFLICT (content): Merge conflict in Αυτά μου φαίνονται κινέζικα
	Q
	EOF
 
	test_cmp expect actual
'
 
test_expect_success 'error out by default for unrelated histories' '
	test_expect_code 128 git merge-tree --write-tree side1 unrelated 2>error &&
 
	grep "refusing to merge unrelated histories" error
'
 
test_expect_success 'can override merge of unrelated histories' '
	git merge-tree --write-tree --allow-unrelated-histories side1 unrelated >tree &&
	TREE=$(cat tree) &&
 
	git rev-parse side1:numbers side1:greeting side1:whatever unrelated:something-else >expect &&
	git rev-parse $TREE:numbers $TREE:greeting $TREE:whatever $TREE:something-else >actual &&
 
	test_cmp expect actual
'
 
test_done