git notes merge: Add testcases for merging notes trees at different fanouts
Notes trees may exist at different fanout levels internally. This implementation detail should not be visible to the user, and it should certainly not affect the merging of notes tree. This patch adds testcases verifying the correctness of 'git notes merge' when merging notes trees at different fanout levels. This patch has been improved by the following contributions: - Junio C Hamano: Portability: Don't string-compare 'wc -l' output Thanks-to: Junio C Hamano <gitster@pobox.com> Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Johan Herland committed
Nov 9, 2010 at 22:49 UTC
305ddd444ee66607581c014b371ed74af534eca5
1 file changed
+436
t/t3311-notes-merge-fanout.sh
new
+436
@@ -0,0 +1,436 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2010 Johan Herland
4
+#
5
+
6
+test_description='Test notes merging at various fanout levels'
7
+
8
+. ./test-lib.sh
9
+
10
+verify_notes () {
11
+ notes_ref="$1"
12
+ commit="$2"
13
+ if test -f "expect_notes_$notes_ref"
14
+ then
15
+ git -c core.notesRef="refs/notes/$notes_ref" notes |
16
+ sort >"output_notes_$notes_ref" &&
17
+ test_cmp "expect_notes_$notes_ref" "output_notes_$notes_ref" ||
18
+ return 1
19
+ fi &&
20
+ git -c core.notesRef="refs/notes/$notes_ref" log --format="%H %s%n%N" \
21
+ "$commit" >"output_log_$notes_ref" &&
22
+ test_cmp "expect_log_$notes_ref" "output_log_$notes_ref"
23
+}
24
+
25
+verify_fanout () {
26
+ notes_ref="$1"
27
+ # Expect entire notes tree to have a fanout == 1
28
+ git rev-parse --quiet --verify "refs/notes/$notes_ref" >/dev/null &&
29
+ git ls-tree -r --name-only "refs/notes/$notes_ref" |
30
+ while read path
31
+ do
32
+ case "$path" in
33
+ ??/??????????????????????????????????????)
34
+ : true
35
+ ;;
36
+ *)
37
+ echo "Invalid path \"$path\"" &&
38
+ return 1
39
+ ;;
40
+ esac
41
+ done
42
+}
43
+
44
+verify_no_fanout () {
45
+ notes_ref="$1"
46
+ # Expect entire notes tree to have a fanout == 0
47
+ git rev-parse --quiet --verify "refs/notes/$notes_ref" >/dev/null &&
48
+ git ls-tree -r --name-only "refs/notes/$notes_ref" |
49
+ while read path
50
+ do
51
+ case "$path" in
52
+ ????????????????????????????????????????)
53
+ : true
54
+ ;;
55
+ *)
56
+ echo "Invalid path \"$path\"" &&
57
+ return 1
58
+ ;;
59
+ esac
60
+ done
61
+}
62
+
63
+# Set up a notes merge scenario with different kinds of conflicts
64
+test_expect_success 'setup a few initial commits with notes (notes ref: x)' '
65
+ git config core.notesRef refs/notes/x &&
66
+ for i in 1 2 3 4 5
67
+ do
68
+ test_commit "commit$i" >/dev/null &&
69
+ git notes add -m "notes for commit$i" || return 1
70
+ done
71
+'
72
+
73
+commit_sha1=$(git rev-parse commit1^{commit})
74
+commit_sha2=$(git rev-parse commit2^{commit})
75
+commit_sha3=$(git rev-parse commit3^{commit})
76
+commit_sha4=$(git rev-parse commit4^{commit})
77
+commit_sha5=$(git rev-parse commit5^{commit})
78
+
79
+cat <<EOF | sort >expect_notes_x
80
+aed91155c7a72c2188e781fdf40e0f3761b299db $commit_sha5
81
+99fab268f9d7ee7b011e091a436c78def8eeee69 $commit_sha4
82
+953c20ae26c7aa0b428c20693fe38bc687f9d1a9 $commit_sha3
83
+6358796131b8916eaa2dde6902642942a1cb37e1 $commit_sha2
84
+b02d459c32f0e68f2fe0981033bb34f38776ba47 $commit_sha1
85
+EOF
86
+
87
+cat >expect_log_x <<EOF
88
+$commit_sha5 commit5
89
+notes for commit5
90
+
91
+$commit_sha4 commit4
92
+notes for commit4
93
+
94
+$commit_sha3 commit3
95
+notes for commit3
96
+
97
+$commit_sha2 commit2
98
+notes for commit2
99
+
100
+$commit_sha1 commit1
101
+notes for commit1
102
+
103
+EOF
104
+
105
+test_expect_success 'sanity check (x)' '
106
+ verify_notes x commit5 &&
107
+ verify_no_fanout x
108
+'
109
+
110
+num=300
111
+
112
+cp expect_log_x expect_log_y
113
+
114
+test_expect_success 'Add a few hundred commits w/notes to trigger fanout (x -> y)' '
115
+ git update-ref refs/notes/y refs/notes/x &&
116
+ git config core.notesRef refs/notes/y &&
117
+ i=5 &&
118
+ while test $i -lt $num
119
+ do
120
+ i=$(($i + 1)) &&
121
+ test_commit "commit$i" >/dev/null &&
122
+ git notes add -m "notes for commit$i" || return 1
123
+ done &&
124
+ test "$(git rev-parse refs/notes/y)" != "$(git rev-parse refs/notes/x)" &&
125
+ # Expected number of commits and notes
126
+ test $(git rev-list HEAD | wc -l) = $num &&
127
+ test $(git notes list | wc -l) = $num &&
128
+ # 5 first notes unchanged
129
+ verify_notes y commit5
130
+'
131
+
132
+test_expect_success 'notes tree has fanout (y)' 'verify_fanout y'
133
+
134
+test_expect_success 'No-op merge (already included) (x => y)' '
135
+ git update-ref refs/notes/m refs/notes/y &&
136
+ git config core.notesRef refs/notes/m &&
137
+ git notes merge x &&
138
+ test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/y)"
139
+'
140
+
141
+test_expect_success 'Fast-forward merge (y => x)' '
142
+ git update-ref refs/notes/m refs/notes/x &&
143
+ git notes merge y &&
144
+ test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/y)"
145
+'
146
+
147
+cat <<EOF | sort >expect_notes_z
148
+9f506ee70e20379d7f78204c77b334f43d77410d $commit_sha3
149
+23a47d6ea7d589895faf800752054818e1e7627b $commit_sha2
150
+b02d459c32f0e68f2fe0981033bb34f38776ba47 $commit_sha1
151
+EOF
152
+
153
+cat >expect_log_z <<EOF
154
+$commit_sha5 commit5
155
+
156
+$commit_sha4 commit4
157
+
158
+$commit_sha3 commit3
159
+notes for commit3
160
+
161
+appended notes for commit3
162
+
163
+$commit_sha2 commit2
164
+new notes for commit2
165
+
166
+$commit_sha1 commit1
167
+notes for commit1
168
+
169
+EOF
170
+
171
+test_expect_success 'change some of the initial 5 notes (x -> z)' '
172
+ git update-ref refs/notes/z refs/notes/x &&
173
+ git config core.notesRef refs/notes/z &&
174
+ git notes add -f -m "new notes for commit2" commit2 &&
175
+ git notes append -m "appended notes for commit3" commit3 &&
176
+ git notes remove commit4 &&
177
+ git notes remove commit5 &&
178
+ verify_notes z commit5
179
+'
180
+
181
+test_expect_success 'notes tree has no fanout (z)' 'verify_no_fanout z'
182
+
183
+cp expect_log_z expect_log_m
184
+
185
+test_expect_success 'successful merge without conflicts (y => z)' '
186
+ git update-ref refs/notes/m refs/notes/z &&
187
+ git config core.notesRef refs/notes/m &&
188
+ git notes merge y &&
189
+ verify_notes m commit5 &&
190
+ # x/y/z unchanged
191
+ verify_notes x commit5 &&
192
+ verify_notes y commit5 &&
193
+ verify_notes z commit5
194
+'
195
+
196
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
197
+
198
+cat >expect_log_w <<EOF
199
+$commit_sha5 commit5
200
+
201
+$commit_sha4 commit4
202
+other notes for commit4
203
+
204
+$commit_sha3 commit3
205
+other notes for commit3
206
+
207
+$commit_sha2 commit2
208
+notes for commit2
209
+
210
+$commit_sha1 commit1
211
+other notes for commit1
212
+
213
+EOF
214
+
215
+test_expect_success 'introduce conflicting changes (y -> w)' '
216
+ git update-ref refs/notes/w refs/notes/y &&
217
+ git config core.notesRef refs/notes/w &&
218
+ git notes add -f -m "other notes for commit1" commit1 &&
219
+ git notes add -f -m "other notes for commit3" commit3 &&
220
+ git notes add -f -m "other notes for commit4" commit4 &&
221
+ git notes remove commit5 &&
222
+ verify_notes w commit5
223
+'
224
+
225
+cat >expect_log_m <<EOF
226
+$commit_sha5 commit5
227
+
228
+$commit_sha4 commit4
229
+other notes for commit4
230
+
231
+$commit_sha3 commit3
232
+other notes for commit3
233
+
234
+$commit_sha2 commit2
235
+new notes for commit2
236
+
237
+$commit_sha1 commit1
238
+other notes for commit1
239
+
240
+EOF
241
+
242
+test_expect_success 'successful merge using "ours" strategy (z => w)' '
243
+ git update-ref refs/notes/m refs/notes/w &&
244
+ git config core.notesRef refs/notes/m &&
245
+ git notes merge -s ours z &&
246
+ verify_notes m commit5 &&
247
+ # w/x/y/z unchanged
248
+ verify_notes w commit5 &&
249
+ verify_notes x commit5 &&
250
+ verify_notes y commit5 &&
251
+ verify_notes z commit5
252
+'
253
+
254
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
255
+
256
+cat >expect_log_m <<EOF
257
+$commit_sha5 commit5
258
+
259
+$commit_sha4 commit4
260
+
261
+$commit_sha3 commit3
262
+notes for commit3
263
+
264
+appended notes for commit3
265
+
266
+$commit_sha2 commit2
267
+new notes for commit2
268
+
269
+$commit_sha1 commit1
270
+other notes for commit1
271
+
272
+EOF
273
+
274
+test_expect_success 'successful merge using "theirs" strategy (z => w)' '
275
+ git update-ref refs/notes/m refs/notes/w &&
276
+ git notes merge -s theirs z &&
277
+ verify_notes m commit5 &&
278
+ # w/x/y/z unchanged
279
+ verify_notes w commit5 &&
280
+ verify_notes x commit5 &&
281
+ verify_notes y commit5 &&
282
+ verify_notes z commit5
283
+'
284
+
285
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
286
+
287
+cat >expect_log_m <<EOF
288
+$commit_sha5 commit5
289
+
290
+$commit_sha4 commit4
291
+other notes for commit4
292
+
293
+$commit_sha3 commit3
294
+other notes for commit3
295
+
296
+notes for commit3
297
+
298
+appended notes for commit3
299
+
300
+$commit_sha2 commit2
301
+new notes for commit2
302
+
303
+$commit_sha1 commit1
304
+other notes for commit1
305
+
306
+EOF
307
+
308
+test_expect_success 'successful merge using "union" strategy (z => w)' '
309
+ git update-ref refs/notes/m refs/notes/w &&
310
+ git notes merge -s union z &&
311
+ verify_notes m commit5 &&
312
+ # w/x/y/z unchanged
313
+ verify_notes w commit5 &&
314
+ verify_notes x commit5 &&
315
+ verify_notes y commit5 &&
316
+ verify_notes z commit5
317
+'
318
+
319
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
320
+
321
+cat >expect_log_m <<EOF
322
+$commit_sha5 commit5
323
+
324
+$commit_sha4 commit4
325
+other notes for commit4
326
+
327
+$commit_sha3 commit3
328
+appended notes for commit3
329
+notes for commit3
330
+other notes for commit3
331
+
332
+$commit_sha2 commit2
333
+new notes for commit2
334
+
335
+$commit_sha1 commit1
336
+other notes for commit1
337
+
338
+EOF
339
+
340
+test_expect_success 'successful merge using "cat_sort_uniq" strategy (z => w)' '
341
+ git update-ref refs/notes/m refs/notes/w &&
342
+ git notes merge -s cat_sort_uniq z &&
343
+ verify_notes m commit5 &&
344
+ # w/x/y/z unchanged
345
+ verify_notes w commit5 &&
346
+ verify_notes x commit5 &&
347
+ verify_notes y commit5 &&
348
+ verify_notes z commit5
349
+'
350
+
351
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
352
+
353
+# We're merging z into w. Here are the conflicts we expect:
354
+#
355
+# commit | x -> w | x -> z | conflict?
356
+# -------|-----------|-----------|----------
357
+# 1 | changed | unchanged | no, use w
358
+# 2 | unchanged | changed | no, use z
359
+# 3 | changed | changed | yes (w, then z in conflict markers)
360
+# 4 | changed | deleted | yes (w)
361
+# 5 | deleted | deleted | no, deleted
362
+
363
+test_expect_success 'fails to merge using "manual" strategy (z => w)' '
364
+ git update-ref refs/notes/m refs/notes/w &&
365
+ test_must_fail git notes merge z
366
+'
367
+
368
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
369
+
370
+cat <<EOF | sort >expect_conflicts
371
+$commit_sha3
372
+$commit_sha4
373
+EOF
374
+
375
+cat >expect_conflict_$commit_sha3 <<EOF
376
+<<<<<<< refs/notes/m
377
+other notes for commit3
378
+=======
379
+notes for commit3
380
+
381
+appended notes for commit3
382
+>>>>>>> refs/notes/z
383
+EOF
384
+
385
+cat >expect_conflict_$commit_sha4 <<EOF
386
+other notes for commit4
387
+EOF
388
+
389
+test_expect_success 'verify conflict entries (with no fanout)' '
390
+ ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
391
+ test_cmp expect_conflicts output_conflicts &&
392
+ ( for f in $(cat expect_conflicts); do
393
+ test_cmp "expect_conflict_$f" ".git/NOTES_MERGE_WORKTREE/$f" ||
394
+ exit 1
395
+ done ) &&
396
+ # Verify that current notes tree (pre-merge) has not changed (m == w)
397
+ test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)"
398
+'
399
+
400
+cat >expect_log_m <<EOF
401
+$commit_sha5 commit5
402
+
403
+$commit_sha4 commit4
404
+other notes for commit4
405
+
406
+$commit_sha3 commit3
407
+other notes for commit3
408
+
409
+appended notes for commit3
410
+
411
+$commit_sha2 commit2
412
+new notes for commit2
413
+
414
+$commit_sha1 commit1
415
+other notes for commit1
416
+
417
+EOF
418
+
419
+test_expect_success 'resolve and finalize merge (z => w)' '
420
+ cat >.git/NOTES_MERGE_WORKTREE/$commit_sha3 <<EOF &&
421
+other notes for commit3
422
+
423
+appended notes for commit3
424
+EOF
425
+ git notes merge --commit &&
426
+ verify_notes m commit5 &&
427
+ # w/x/y/z unchanged
428
+ verify_notes w commit5 &&
429
+ verify_notes x commit5 &&
430
+ verify_notes y commit5 &&
431
+ verify_notes z commit5
432
+'
433
+
434
+test_expect_success 'notes tree still has fanout after merge (m)' 'verify_fanout m'
435
+
436
+test_done