Merge branch 'pd/bash-4-completion'
[git] / t / t9301-fast-import-notes.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2009 Johan Herland
4 #
5
6 test_description='test git fast-import of notes objects'
7 . ./test-lib.sh
8
9
10 test_tick
11 cat >input <<INPUT_END
12 commit refs/heads/master
13 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
14 data <<COMMIT
15 first commit
16 COMMIT
17
18 M 644 inline foo
19 data <<EOF
20 file foo in first commit
21 EOF
22
23 M 755 inline bar
24 data <<EOF
25 file bar in first commit
26 EOF
27
28 M 644 inline baz/xyzzy
29 data <<EOF
30 file baz/xyzzy in first commit
31 EOF
32
33 commit refs/heads/master
34 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
35 data <<COMMIT
36 second commit
37 COMMIT
38
39 M 644 inline foo
40 data <<EOF
41 file foo in second commit
42 EOF
43
44 M 755 inline baz/xyzzy
45 data <<EOF
46 file baz/xyzzy in second commit
47 EOF
48
49 commit refs/heads/master
50 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
51 data <<COMMIT
52 third commit
53 COMMIT
54
55 M 644 inline foo
56 data <<EOF
57 file foo in third commit
58 EOF
59
60 commit refs/heads/master
61 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
62 data <<COMMIT
63 fourth commit
64 COMMIT
65
66 M 755 inline bar
67 data <<EOF
68 file bar in fourth commit
69 EOF
70
71 INPUT_END
72
73 test_expect_success 'set up master branch' '
74
75         git fast-import <input &&
76         git whatchanged master
77 '
78
79 commit4=$(git rev-parse refs/heads/master)
80 commit3=$(git rev-parse "$commit4^")
81 commit2=$(git rev-parse "$commit4~2")
82 commit1=$(git rev-parse "$commit4~3")
83
84 test_tick
85 cat >input <<INPUT_END
86 commit refs/notes/test
87 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
88 data <<COMMIT
89 first notes commit
90 COMMIT
91
92 M 644 inline $commit1
93 data <<EOF
94 first note for first commit
95 EOF
96
97 M 755 inline $commit2
98 data <<EOF
99 first note for second commit
100 EOF
101
102 INPUT_END
103
104 cat >expect <<EXPECT_END
105     fourth commit
106     third commit
107     second commit
108     first note for second commit
109     first commit
110     first note for first commit
111 EXPECT_END
112
113 test_expect_success 'add notes with simple M command' '
114
115         git fast-import <input &&
116         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
117         test_cmp expect actual
118
119 '
120
121 test_tick
122 cat >input <<INPUT_END
123 commit refs/notes/test
124 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
125 data <<COMMIT
126 second notes commit
127 COMMIT
128
129 from refs/notes/test^0
130 N inline $commit3
131 data <<EOF
132 first note for third commit
133 EOF
134
135 N inline $commit4
136 data <<EOF
137 first note for fourth commit
138 EOF
139
140 INPUT_END
141
142 cat >expect <<EXPECT_END
143     fourth commit
144     first note for fourth commit
145     third commit
146     first note for third commit
147     second commit
148     first note for second commit
149     first commit
150     first note for first commit
151 EXPECT_END
152
153 test_expect_success 'add notes with simple N command' '
154
155         git fast-import <input &&
156         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
157         test_cmp expect actual
158
159 '
160
161 test_tick
162 cat >input <<INPUT_END
163 commit refs/notes/test
164 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
165 data <<COMMIT
166 third notes commit
167 COMMIT
168
169 from refs/notes/test^0
170 N inline $commit1
171 data <<EOF
172 second note for first commit
173 EOF
174
175 N inline $commit2
176 data <<EOF
177 second note for second commit
178 EOF
179
180 N inline $commit3
181 data <<EOF
182 second note for third commit
183 EOF
184
185 N inline $commit4
186 data <<EOF
187 second note for fourth commit
188 EOF
189
190 INPUT_END
191
192 cat >expect <<EXPECT_END
193     fourth commit
194     second note for fourth commit
195     third commit
196     second note for third commit
197     second commit
198     second note for second commit
199     first commit
200     second note for first commit
201 EXPECT_END
202
203 test_expect_success 'update existing notes with N command' '
204
205         git fast-import <input &&
206         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
207         test_cmp expect actual
208
209 '
210
211 test_tick
212 cat >input <<INPUT_END
213 commit refs/notes/test
214 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
215 data <<COMMIT
216 fourth notes commit
217 COMMIT
218
219 from refs/notes/test^0
220 M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
221 data <<EOF
222 prefix of note for third commit
223 EOF
224
225 M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
226 data <<EOF
227 prefix of note for fourth commit
228 EOF
229
230 M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
231 data <<EOF
232 pre-prefix of note for fourth commit
233 EOF
234
235 N inline $commit1
236 data <<EOF
237 third note for first commit
238 EOF
239
240 N inline $commit2
241 data <<EOF
242 third note for second commit
243 EOF
244
245 N inline $commit3
246 data <<EOF
247 third note for third commit
248 EOF
249
250 N inline $commit4
251 data <<EOF
252 third note for fourth commit
253 EOF
254
255
256 INPUT_END
257
258 whitespace="    "
259
260 cat >expect <<EXPECT_END
261     fourth commit
262     pre-prefix of note for fourth commit
263 $whitespace
264     prefix of note for fourth commit
265 $whitespace
266     third note for fourth commit
267     third commit
268     prefix of note for third commit
269 $whitespace
270     third note for third commit
271     second commit
272     third note for second commit
273     first commit
274     third note for first commit
275 EXPECT_END
276
277 test_expect_success 'add concatentation notes with M command' '
278
279         git fast-import <input &&
280         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
281         test_cmp expect actual
282
283 '
284
285 test_tick
286 cat >input <<INPUT_END
287 commit refs/notes/test
288 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
289 data <<COMMIT
290 fifth notes commit
291 COMMIT
292
293 from refs/notes/test^0
294 deleteall
295
296 INPUT_END
297
298 cat >expect <<EXPECT_END
299     fourth commit
300     third commit
301     second commit
302     first commit
303 EXPECT_END
304
305 test_expect_success 'verify that deleteall also removes notes' '
306
307         git fast-import <input &&
308         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
309         test_cmp expect actual
310
311 '
312
313 test_tick
314 cat >input <<INPUT_END
315 commit refs/notes/test
316 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
317 data <<COMMIT
318 sixth notes commit
319 COMMIT
320
321 from refs/notes/test^0
322 M 644 inline $commit1
323 data <<EOF
324 third note for first commit
325 EOF
326
327 M 644 inline $commit3
328 data <<EOF
329 third note for third commit
330 EOF
331
332 N inline $commit1
333 data <<EOF
334 fourth note for first commit
335 EOF
336
337 N inline $commit3
338 data <<EOF
339 fourth note for third commit
340 EOF
341
342 INPUT_END
343
344 cat >expect <<EXPECT_END
345     fourth commit
346     third commit
347     fourth note for third commit
348     second commit
349     first commit
350     fourth note for first commit
351 EXPECT_END
352
353 test_expect_success 'verify that later N commands override earlier M commands' '
354
355         git fast-import <input &&
356         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
357         test_cmp expect actual
358
359 '
360
361 # Write fast-import commands to create the given number of commits
362 fast_import_commits () {
363         my_ref=$1
364         my_num_commits=$2
365         my_append_to_file=$3
366         my_i=0
367         while test $my_i -lt $my_num_commits
368         do
369                 my_i=$(($my_i + 1))
370                 test_tick
371                 cat >>"$my_append_to_file" <<INPUT_END
372 commit $my_ref
373 mark :$my_i
374 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
375 data <<COMMIT
376 commit #$my_i
377 COMMIT
378
379 M 644 inline file
380 data <<EOF
381 file contents in commit #$my_i
382 EOF
383
384 INPUT_END
385         done
386 }
387
388 # Write fast-import commands to create the given number of notes annotating
389 # the commits created by fast_import_commits()
390 fast_import_notes () {
391         my_notes_ref=$1
392         my_num_commits=$2
393         my_append_to_file=$3
394         my_note_append=$4
395         test_tick
396         cat >>"$my_append_to_file" <<INPUT_END
397 commit $my_notes_ref
398 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
399 data <<COMMIT
400 committing $my_num_commits notes
401 COMMIT
402
403 INPUT_END
404
405         my_i=0
406         while test $my_i -lt $my_num_commits
407         do
408                 my_i=$(($my_i + 1))
409                 cat >>"$my_append_to_file" <<INPUT_END
410 N inline :$my_i
411 data <<EOF
412 note for commit #$my_i$my_note_append
413 EOF
414
415 INPUT_END
416         done
417 }
418
419
420 rm input expect
421 num_commits=400
422 # Create lots of commits
423 fast_import_commits "refs/heads/many_commits" $num_commits input
424 # Create one note per above commit
425 fast_import_notes "refs/notes/many_notes" $num_commits input
426 # Add a couple of non-notes as well
427 test_tick
428 cat >>input <<INPUT_END
429 commit refs/notes/many_notes
430 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
431 data <<COMMIT
432 committing some non-notes to the notes tree
433 COMMIT
434
435 M 755 inline foobar/non-note.txt
436 data <<EOF
437 This is not a note, but rather a regular file residing in a notes tree
438 EOF
439
440 M 644 inline deadbeef
441 data <<EOF
442 Non-note file
443 EOF
444
445 M 644 inline de/adbeef
446 data <<EOF
447 Another non-note file
448 EOF
449
450 INPUT_END
451 # Finally create the expected output from all these notes and commits
452 i=$num_commits
453 while test $i -gt 0
454 do
455         cat >>expect <<EXPECT_END
456     commit #$i
457     note for commit #$i
458 EXPECT_END
459         i=$(($i - 1))
460 done
461
462 test_expect_success 'add lots of commits and notes' '
463
464         git fast-import <input &&
465         GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
466             grep "^    " > actual &&
467         test_cmp expect actual
468
469 '
470
471 test_expect_success 'verify that lots of notes trigger a fanout scheme' '
472
473         # None of the entries in the top-level notes tree should be a full SHA1
474         git ls-tree --name-only refs/notes/many_notes |
475         while read path
476         do
477                 if test $(expr length "$path") -ge 40
478                 then
479                         return 1
480                 fi
481         done
482
483 '
484
485 cat >>expect_non-note1 << EOF
486 This is not a note, but rather a regular file residing in a notes tree
487 EOF
488
489 cat >>expect_non-note2 << EOF
490 Non-note file
491 EOF
492
493 cat >>expect_non-note3 << EOF
494 Another non-note file
495 EOF
496
497 test_expect_success 'verify that non-notes are untouched by a fanout change' '
498
499         git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
500         test_cmp expect_non-note1 actual &&
501         git cat-file -p refs/notes/many_notes:deadbeef > actual &&
502         test_cmp expect_non-note2 actual &&
503         git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
504         test_cmp expect_non-note3 actual
505
506 '
507 remaining_notes=10
508 test_tick
509 cat >>input <<INPUT_END
510 commit refs/notes/many_notes
511 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
512 data <<COMMIT
513 removing all notes but $remaining_notes
514 COMMIT
515 from refs/notes/many_notes^0
516 INPUT_END
517
518 i=$remaining_notes
519 while test $i -lt $num_commits
520 do
521         i=$(($i + 1))
522         cat >>input <<INPUT_END
523 N 0000000000000000000000000000000000000000 :$i
524 INPUT_END
525 done
526
527 i=$num_commits
528 rm expect
529 while test $i -gt 0
530 do
531         cat >>expect <<EXPECT_END
532     commit #$i
533 EXPECT_END
534         if test $i -le $remaining_notes
535         then
536                 cat >>expect <<EXPECT_END
537     note for commit #$i
538 EXPECT_END
539         fi
540         i=$(($i - 1))
541 done
542
543 test_expect_success 'remove lots of notes' '
544
545         git fast-import <input &&
546         GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
547             grep "^    " > actual &&
548         test_cmp expect actual
549
550 '
551
552 test_expect_success 'verify that removing notes trigger fanout consolidation' '
553
554         # All entries in the top-level notes tree should be a full SHA1
555         git ls-tree --name-only -r refs/notes/many_notes |
556         while read path
557         do
558                 # Explicitly ignore the non-note paths
559                 test "$path" = "foobar/non-note.txt" && continue
560                 test "$path" = "deadbeef" && continue
561                 test "$path" = "de/adbeef" && continue
562
563                 if test $(expr length "$path") -ne 40
564                 then
565                         return 1
566                 fi
567         done
568
569 '
570
571 test_expect_success 'verify that non-notes are untouched by a fanout change' '
572
573         git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
574         test_cmp expect_non-note1 actual &&
575         git cat-file -p refs/notes/many_notes:deadbeef > actual &&
576         test_cmp expect_non-note2 actual &&
577         git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
578         test_cmp expect_non-note3 actual
579
580 '
581
582
583 rm input expect
584 num_notes_refs=10
585 num_commits=16
586 some_commits=8
587 # Create commits
588 fast_import_commits "refs/heads/more_commits" $num_commits input
589 # Create one note per above commit per notes ref
590 i=0
591 while test $i -lt $num_notes_refs
592 do
593         i=$(($i + 1))
594         fast_import_notes "refs/notes/more_notes_$i" $num_commits input
595 done
596 # Trigger branch reloading in git-fast-import by repeating the note creation
597 i=0
598 while test $i -lt $num_notes_refs
599 do
600         i=$(($i + 1))
601         fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
602 done
603 # Finally create the expected output from the notes in refs/notes/more_notes_1
604 i=$num_commits
605 while test $i -gt 0
606 do
607         note_data="note for commit #$i"
608         if test $i -le $some_commits
609         then
610                 note_data="$note_data (2)"
611         fi
612         cat >>expect <<EXPECT_END
613     commit #$i
614     $note_data
615 EXPECT_END
616         i=$(($i - 1))
617 done
618
619 test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
620
621         git fast-import --active-branches=5 <input &&
622         GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
623             grep "^    " > actual &&
624         test_cmp expect actual
625
626 '
627
628 test_done