test-tool: handle the `-C <directory>` option just like `git`
[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 feature notes
124 commit refs/notes/test
125 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
126 data <<COMMIT
127 second notes commit
128 COMMIT
129
130 from refs/notes/test^0
131 N inline $commit3
132 data <<EOF
133 first note for third commit
134 EOF
135
136 N inline $commit4
137 data <<EOF
138 first note for fourth commit
139 EOF
140
141 INPUT_END
142
143 cat >expect <<EXPECT_END
144     fourth commit
145     first note for fourth commit
146     third commit
147     first note for third commit
148     second commit
149     first note for second commit
150     first commit
151     first note for first commit
152 EXPECT_END
153
154 test_expect_success 'add notes with simple N command' '
155
156         git fast-import <input &&
157         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
158         test_cmp expect actual
159
160 '
161
162 test_tick
163 cat >input <<INPUT_END
164 commit refs/notes/test
165 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
166 data <<COMMIT
167 third notes commit
168 COMMIT
169
170 from refs/notes/test^0
171 N inline $commit1
172 data <<EOF
173 second note for first commit
174 EOF
175
176 N inline $commit2
177 data <<EOF
178 second note for second commit
179 EOF
180
181 N inline $commit3
182 data <<EOF
183 second note for third commit
184 EOF
185
186 N inline $commit4
187 data <<EOF
188 second note for fourth commit
189 EOF
190
191 INPUT_END
192
193 cat >expect <<EXPECT_END
194     fourth commit
195     second note for fourth commit
196     third commit
197     second note for third commit
198     second commit
199     second note for second commit
200     first commit
201     second note for first commit
202 EXPECT_END
203
204 test_expect_success 'update existing notes with N command' '
205
206         git fast-import <input &&
207         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
208         test_cmp expect actual
209
210 '
211
212 test_tick
213 cat >input <<INPUT_END
214 commit refs/notes/test
215 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
216 data <<COMMIT
217 fourth notes commit
218 COMMIT
219
220 from refs/notes/test^0
221 M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
222 data <<EOF
223 prefix of note for third commit
224 EOF
225
226 M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
227 data <<EOF
228 prefix of note for fourth commit
229 EOF
230
231 M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
232 data <<EOF
233 pre-prefix of note for fourth commit
234 EOF
235
236 N inline $commit1
237 data <<EOF
238 third note for first commit
239 EOF
240
241 N inline $commit2
242 data <<EOF
243 third note for second commit
244 EOF
245
246 N inline $commit3
247 data <<EOF
248 third note for third commit
249 EOF
250
251 N inline $commit4
252 data <<EOF
253 third note for fourth commit
254 EOF
255
256
257 INPUT_END
258
259 whitespace="    "
260
261 cat >expect <<EXPECT_END
262     fourth commit
263     pre-prefix of note for fourth commit
264 $whitespace
265     prefix of note for fourth commit
266 $whitespace
267     third note for fourth commit
268     third commit
269     prefix of note for third commit
270 $whitespace
271     third note for third commit
272     second commit
273     third note for second commit
274     first commit
275     third note for first commit
276 EXPECT_END
277
278 test_expect_success 'add concatentation notes with M command' '
279
280         git fast-import <input &&
281         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
282         test_cmp expect actual
283
284 '
285
286 test_tick
287 cat >input <<INPUT_END
288 commit refs/notes/test
289 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
290 data <<COMMIT
291 fifth notes commit
292 COMMIT
293
294 from refs/notes/test^0
295 deleteall
296
297 INPUT_END
298
299 cat >expect <<EXPECT_END
300     fourth commit
301     third commit
302     second commit
303     first commit
304 EXPECT_END
305
306 test_expect_success 'verify that deleteall also removes notes' '
307
308         git fast-import <input &&
309         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
310         test_cmp expect actual
311
312 '
313
314 test_tick
315 cat >input <<INPUT_END
316 commit refs/notes/test
317 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
318 data <<COMMIT
319 sixth notes commit
320 COMMIT
321
322 from refs/notes/test^0
323 M 644 inline $commit1
324 data <<EOF
325 third note for first commit
326 EOF
327
328 M 644 inline $commit3
329 data <<EOF
330 third note for third commit
331 EOF
332
333 N inline $commit1
334 data <<EOF
335 fourth note for first commit
336 EOF
337
338 N inline $commit3
339 data <<EOF
340 fourth note for third commit
341 EOF
342
343 INPUT_END
344
345 cat >expect <<EXPECT_END
346     fourth commit
347     third commit
348     fourth note for third commit
349     second commit
350     first commit
351     fourth note for first commit
352 EXPECT_END
353
354 test_expect_success 'verify that later N commands override earlier M commands' '
355
356         git fast-import <input &&
357         GIT_NOTES_REF=refs/notes/test git log | grep "^    " > actual &&
358         test_cmp expect actual
359
360 '
361
362 # Write fast-import commands to create the given number of commits
363 fast_import_commits () {
364         my_ref=$1
365         my_num_commits=$2
366         my_append_to_file=$3
367         my_i=0
368         while test $my_i -lt $my_num_commits
369         do
370                 my_i=$(($my_i + 1))
371                 test_tick
372                 cat >>"$my_append_to_file" <<INPUT_END
373 commit $my_ref
374 mark :$my_i
375 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
376 data <<COMMIT
377 commit #$my_i
378 COMMIT
379
380 M 644 inline file
381 data <<EOF
382 file contents in commit #$my_i
383 EOF
384
385 INPUT_END
386         done
387 }
388
389 # Write fast-import commands to create the given number of notes annotating
390 # the commits created by fast_import_commits()
391 fast_import_notes () {
392         my_notes_ref=$1
393         my_num_commits=$2
394         my_append_to_file=$3
395         my_note_append=$4
396         test_tick
397         cat >>"$my_append_to_file" <<INPUT_END
398 commit $my_notes_ref
399 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
400 data <<COMMIT
401 committing $my_num_commits notes
402 COMMIT
403
404 INPUT_END
405
406         my_i=0
407         while test $my_i -lt $my_num_commits
408         do
409                 my_i=$(($my_i + 1))
410                 cat >>"$my_append_to_file" <<INPUT_END
411 N inline :$my_i
412 data <<EOF
413 note for commit #$my_i$my_note_append
414 EOF
415
416 INPUT_END
417         done
418 }
419
420
421 rm input expect
422 num_commits=400
423 # Create lots of commits
424 fast_import_commits "refs/heads/many_commits" $num_commits input
425 # Create one note per above commit
426 fast_import_notes "refs/notes/many_notes" $num_commits input
427 # Add a couple of non-notes as well
428 test_tick
429 cat >>input <<INPUT_END
430 commit refs/notes/many_notes
431 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
432 data <<COMMIT
433 committing some non-notes to the notes tree
434 COMMIT
435
436 M 755 inline foobar/non-note.txt
437 data <<EOF
438 This is not a note, but rather a regular file residing in a notes tree
439 EOF
440
441 M 644 inline deadbeef
442 data <<EOF
443 Non-note file
444 EOF
445
446 M 644 inline de/adbeef
447 data <<EOF
448 Another non-note file
449 EOF
450
451 INPUT_END
452 # Finally create the expected output from all these notes and commits
453 i=$num_commits
454 while test $i -gt 0
455 do
456         cat >>expect <<EXPECT_END
457     commit #$i
458     note for commit #$i
459 EXPECT_END
460         i=$(($i - 1))
461 done
462
463 test_expect_success 'add lots of commits and notes' '
464
465         git fast-import <input &&
466         GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
467             grep "^    " > actual &&
468         test_cmp expect actual
469
470 '
471
472 test_expect_success 'verify that lots of notes trigger a fanout scheme' '
473
474         # None of the entries in the top-level notes tree should be a full SHA1
475         git ls-tree --name-only refs/notes/many_notes |
476         while read path
477         do
478                 if test $(expr length "$path") -ge 40
479                 then
480                         return 1
481                 fi
482         done
483
484 '
485
486 # Create another notes tree from the one above
487 SP=" "
488 cat >>input <<INPUT_END
489 commit refs/heads/other_commits
490 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
491 data <<COMMIT
492 commit #$(($num_commit + 1))
493 COMMIT
494
495 from refs/heads/many_commits
496 M 644 inline file
497 data <<EOF
498 file contents in commit #$(($num_commit + 1))
499 EOF
500
501 commit refs/notes/other_notes
502 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
503 data <<COMMIT
504 committing one more note on a tree imported from a previous notes tree
505 COMMIT
506
507 M 040000 $(git log --no-walk --format=%T refs/notes/many_notes)$SP
508 N inline :$(($num_commit + 1))
509 data <<EOF
510 note for commit #$(($num_commit + 1))
511 EOF
512 INPUT_END
513
514 test_expect_success 'verify that importing a notes tree respects the fanout scheme' '
515         git fast-import <input &&
516
517         # None of the entries in the top-level notes tree should be a full SHA1
518         git ls-tree --name-only refs/notes/other_notes |
519         while read path
520         do
521                 if test $(expr length "$path") -ge 40
522                 then
523                         return 1
524                 fi
525         done
526 '
527
528 cat >>expect_non-note1 << EOF
529 This is not a note, but rather a regular file residing in a notes tree
530 EOF
531
532 cat >>expect_non-note2 << EOF
533 Non-note file
534 EOF
535
536 cat >>expect_non-note3 << EOF
537 Another non-note file
538 EOF
539
540 test_expect_success 'verify that non-notes are untouched by a fanout change' '
541
542         git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
543         test_cmp expect_non-note1 actual &&
544         git cat-file -p refs/notes/many_notes:deadbeef > actual &&
545         test_cmp expect_non-note2 actual &&
546         git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
547         test_cmp expect_non-note3 actual
548
549 '
550
551 # Change the notes for the three top commits
552 test_tick
553 cat >input <<INPUT_END
554 commit refs/notes/many_notes
555 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
556 data <<COMMIT
557 changing notes for the top three commits
558 COMMIT
559 from refs/notes/many_notes^0
560 INPUT_END
561
562 rm expect
563 i=$num_commits
564 j=0
565 while test $j -lt 3
566 do
567         cat >>input <<INPUT_END
568 N inline refs/heads/many_commits~$j
569 data <<EOF
570 changed note for commit #$i
571 EOF
572 INPUT_END
573         cat >>expect <<EXPECT_END
574     commit #$i
575     changed note for commit #$i
576 EXPECT_END
577         i=$(($i - 1))
578         j=$(($j + 1))
579 done
580
581 test_expect_success 'change a few existing notes' '
582
583         git fast-import <input &&
584         GIT_NOTES_REF=refs/notes/many_notes git log -n3 refs/heads/many_commits |
585             grep "^    " > actual &&
586         test_cmp expect actual
587
588 '
589
590 test_expect_success 'verify that changing notes respect existing fanout' '
591
592         # None of the entries in the top-level notes tree should be a full SHA1
593         git ls-tree --name-only refs/notes/many_notes |
594         while read path
595         do
596                 if test $(expr length "$path") -ge 40
597                 then
598                         return 1
599                 fi
600         done
601
602 '
603
604 remaining_notes=10
605 test_tick
606 cat >input <<INPUT_END
607 commit refs/notes/many_notes
608 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
609 data <<COMMIT
610 removing all notes but $remaining_notes
611 COMMIT
612 from refs/notes/many_notes^0
613 INPUT_END
614
615 i=$(($num_commits - $remaining_notes))
616 for sha1 in $(git rev-list -n $i refs/heads/many_commits)
617 do
618         cat >>input <<INPUT_END
619 N 0000000000000000000000000000000000000000 $sha1
620 INPUT_END
621 done
622
623 i=$num_commits
624 rm expect
625 while test $i -gt 0
626 do
627         cat >>expect <<EXPECT_END
628     commit #$i
629 EXPECT_END
630         if test $i -le $remaining_notes
631         then
632                 cat >>expect <<EXPECT_END
633     note for commit #$i
634 EXPECT_END
635         fi
636         i=$(($i - 1))
637 done
638
639 test_expect_success 'remove lots of notes' '
640
641         git fast-import <input &&
642         GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
643             grep "^    " > actual &&
644         test_cmp expect actual
645
646 '
647
648 test_expect_success 'verify that removing notes trigger fanout consolidation' '
649
650         # All entries in the top-level notes tree should be a full SHA1
651         git ls-tree --name-only -r refs/notes/many_notes |
652         while read path
653         do
654                 # Explicitly ignore the non-note paths
655                 test "$path" = "foobar/non-note.txt" && continue
656                 test "$path" = "deadbeef" && continue
657                 test "$path" = "de/adbeef" && continue
658
659                 if test $(expr length "$path") -ne 40
660                 then
661                         return 1
662                 fi
663         done
664
665 '
666
667 test_expect_success 'verify that non-notes are untouched by a fanout change' '
668
669         git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
670         test_cmp expect_non-note1 actual &&
671         git cat-file -p refs/notes/many_notes:deadbeef > actual &&
672         test_cmp expect_non-note2 actual &&
673         git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
674         test_cmp expect_non-note3 actual
675
676 '
677
678
679 rm input expect
680 num_notes_refs=10
681 num_commits=16
682 some_commits=8
683 # Create commits
684 fast_import_commits "refs/heads/more_commits" $num_commits input
685 # Create one note per above commit per notes ref
686 i=0
687 while test $i -lt $num_notes_refs
688 do
689         i=$(($i + 1))
690         fast_import_notes "refs/notes/more_notes_$i" $num_commits input
691 done
692 # Trigger branch reloading in git-fast-import by repeating the note creation
693 i=0
694 while test $i -lt $num_notes_refs
695 do
696         i=$(($i + 1))
697         fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
698 done
699 # Finally create the expected output from the notes in refs/notes/more_notes_1
700 i=$num_commits
701 while test $i -gt 0
702 do
703         note_data="note for commit #$i"
704         if test $i -le $some_commits
705         then
706                 note_data="$note_data (2)"
707         fi
708         cat >>expect <<EXPECT_END
709     commit #$i
710     $note_data
711 EXPECT_END
712         i=$(($i - 1))
713 done
714
715 test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
716
717         git fast-import --active-branches=5 <input &&
718         GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
719             grep "^    " > actual &&
720         test_cmp expect actual
721
722 '
723
724 test_done