Merge branch 'mt/fix-add-rm-with-sparse-index'
[git/debian.git] / t / t9301-fast-import-notes.sh
blob1ae4d7c0d37db2d10cbc08ce90505b291e70171b
1 #!/bin/sh
3 # Copyright (c) 2009 Johan Herland
6 test_description='test git fast-import of notes objects'
7 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
8 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
10 . ./test-lib.sh
13 test_tick
14 cat >input <<INPUT_END
15 commit refs/heads/main
16 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
17 data <<COMMIT
18 first commit
19 COMMIT
21 M 644 inline foo
22 data <<EOF
23 file foo in first commit
24 EOF
26 M 755 inline bar
27 data <<EOF
28 file bar in first commit
29 EOF
31 M 644 inline baz/xyzzy
32 data <<EOF
33 file baz/xyzzy in first commit
34 EOF
36 commit refs/heads/main
37 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
38 data <<COMMIT
39 second commit
40 COMMIT
42 M 644 inline foo
43 data <<EOF
44 file foo in second commit
45 EOF
47 M 755 inline baz/xyzzy
48 data <<EOF
49 file baz/xyzzy in second commit
50 EOF
52 commit refs/heads/main
53 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
54 data <<COMMIT
55 third commit
56 COMMIT
58 M 644 inline foo
59 data <<EOF
60 file foo in third commit
61 EOF
63 commit refs/heads/main
64 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
65 data <<COMMIT
66 fourth commit
67 COMMIT
69 M 755 inline bar
70 data <<EOF
71 file bar in fourth commit
72 EOF
74 INPUT_END
76 test_expect_success 'set up main branch' '
78 git fast-import <input &&
79 git whatchanged main
82 commit4=$(git rev-parse refs/heads/main)
83 commit3=$(git rev-parse "$commit4^")
84 commit2=$(git rev-parse "$commit4~2")
85 commit1=$(git rev-parse "$commit4~3")
87 test_tick
88 cat >input <<INPUT_END
89 commit refs/notes/test
90 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
91 data <<COMMIT
92 first notes commit
93 COMMIT
95 M 644 inline $commit1
96 data <<EOF
97 first note for first commit
98 EOF
100 M 755 inline $commit2
101 data <<EOF
102 first note for second commit
105 INPUT_END
107 cat >expect <<EXPECT_END
108 fourth commit
109 third commit
110 second commit
111 first note for second commit
112 first commit
113 first note for first commit
114 EXPECT_END
116 test_expect_success 'add notes with simple M command' '
118 git fast-import <input &&
119 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
120 test_cmp expect actual
124 test_tick
125 cat >input <<INPUT_END
126 feature notes
127 commit refs/notes/test
128 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
129 data <<COMMIT
130 second notes commit
131 COMMIT
133 from refs/notes/test^0
134 N inline $commit3
135 data <<EOF
136 first note for third commit
139 N inline $commit4
140 data <<EOF
141 first note for fourth commit
144 INPUT_END
146 cat >expect <<EXPECT_END
147 fourth commit
148 first note for fourth commit
149 third commit
150 first note for third commit
151 second commit
152 first note for second commit
153 first commit
154 first note for first commit
155 EXPECT_END
157 test_expect_success 'add notes with simple N command' '
159 git fast-import <input &&
160 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
161 test_cmp expect actual
165 test_tick
166 cat >input <<INPUT_END
167 commit refs/notes/test
168 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
169 data <<COMMIT
170 third notes commit
171 COMMIT
173 from refs/notes/test^0
174 N inline $commit1
175 data <<EOF
176 second note for first commit
179 N inline $commit2
180 data <<EOF
181 second note for second commit
184 N inline $commit3
185 data <<EOF
186 second note for third commit
189 N inline $commit4
190 data <<EOF
191 second note for fourth commit
194 INPUT_END
196 cat >expect <<EXPECT_END
197 fourth commit
198 second note for fourth commit
199 third commit
200 second note for third commit
201 second commit
202 second note for second commit
203 first commit
204 second note for first commit
205 EXPECT_END
207 test_expect_success 'update existing notes with N command' '
209 git fast-import <input &&
210 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
211 test_cmp expect actual
215 test_tick
216 cat >input <<INPUT_END
217 commit refs/notes/test
218 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
219 data <<COMMIT
220 fourth notes commit
221 COMMIT
223 from refs/notes/test^0
224 M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
225 data <<EOF
226 prefix of note for third commit
229 M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
230 data <<EOF
231 prefix of note for fourth commit
234 M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
235 data <<EOF
236 pre-prefix of note for fourth commit
239 N inline $commit1
240 data <<EOF
241 third note for first commit
244 N inline $commit2
245 data <<EOF
246 third note for second commit
249 N inline $commit3
250 data <<EOF
251 third note for third commit
254 N inline $commit4
255 data <<EOF
256 third note for fourth commit
260 INPUT_END
262 whitespace=" "
264 cat >expect <<EXPECT_END
265 fourth commit
266 pre-prefix of note for fourth commit
267 $whitespace
268 prefix of note for fourth commit
269 $whitespace
270 third note for fourth commit
271 third commit
272 prefix of note for third commit
273 $whitespace
274 third note for third commit
275 second commit
276 third note for second commit
277 first commit
278 third note for first commit
279 EXPECT_END
281 test_expect_success 'add concatenation notes with M command' '
283 git fast-import <input &&
284 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
285 test_cmp expect actual
289 test_tick
290 cat >input <<INPUT_END
291 commit refs/notes/test
292 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
293 data <<COMMIT
294 fifth notes commit
295 COMMIT
297 from refs/notes/test^0
298 deleteall
300 INPUT_END
302 cat >expect <<EXPECT_END
303 fourth commit
304 third commit
305 second commit
306 first commit
307 EXPECT_END
309 test_expect_success 'verify that deleteall also removes notes' '
311 git fast-import <input &&
312 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
313 test_cmp expect actual
317 test_tick
318 cat >input <<INPUT_END
319 commit refs/notes/test
320 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
321 data <<COMMIT
322 sixth notes commit
323 COMMIT
325 from refs/notes/test^0
326 M 644 inline $commit1
327 data <<EOF
328 third note for first commit
331 M 644 inline $commit3
332 data <<EOF
333 third note for third commit
336 N inline $commit1
337 data <<EOF
338 fourth note for first commit
341 N inline $commit3
342 data <<EOF
343 fourth note for third commit
346 INPUT_END
348 cat >expect <<EXPECT_END
349 fourth commit
350 third commit
351 fourth note for third commit
352 second commit
353 first commit
354 fourth note for first commit
355 EXPECT_END
357 test_expect_success 'verify that later N commands override earlier M commands' '
359 git fast-import <input &&
360 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
361 test_cmp expect actual
365 # Write fast-import commands to create the given number of commits
366 fast_import_commits () {
367 my_ref=$1
368 my_num_commits=$2
369 my_append_to_file=$3
370 my_i=0
371 while test $my_i -lt $my_num_commits
373 my_i=$(($my_i + 1))
374 test_tick
375 cat >>"$my_append_to_file" <<INPUT_END
376 commit $my_ref
377 mark :$my_i
378 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
379 data <<COMMIT
380 commit #$my_i
381 COMMIT
383 M 644 inline file
384 data <<EOF
385 file contents in commit #$my_i
388 INPUT_END
389 done
392 # Write fast-import commands to create the given number of notes annotating
393 # the commits created by fast_import_commits()
394 fast_import_notes () {
395 my_notes_ref=$1
396 my_num_commits=$2
397 my_append_to_file=$3
398 my_note_append=$4
399 test_tick
400 cat >>"$my_append_to_file" <<INPUT_END
401 commit $my_notes_ref
402 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
403 data <<COMMIT
404 committing $my_num_commits notes
405 COMMIT
407 INPUT_END
409 my_i=0
410 while test $my_i -lt $my_num_commits
412 my_i=$(($my_i + 1))
413 cat >>"$my_append_to_file" <<INPUT_END
414 N inline :$my_i
415 data <<EOF
416 note for commit #$my_i$my_note_append
419 INPUT_END
420 done
424 rm input expect
425 num_commits=400
426 # Create lots of commits
427 fast_import_commits "refs/heads/many_commits" $num_commits input
428 # Create one note per above commit
429 fast_import_notes "refs/notes/many_notes" $num_commits input
430 # Add a couple of non-notes as well
431 test_tick
432 cat >>input <<INPUT_END
433 commit refs/notes/many_notes
434 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
435 data <<COMMIT
436 committing some non-notes to the notes tree
437 COMMIT
439 M 755 inline foobar/non-note.txt
440 data <<EOF
441 This is not a note, but rather a regular file residing in a notes tree
444 M 644 inline deadbeef
445 data <<EOF
446 Non-note file
449 M 644 inline de/adbeef
450 data <<EOF
451 Another non-note file
454 INPUT_END
455 # Finally create the expected output from all these notes and commits
456 i=$num_commits
457 while test $i -gt 0
459 cat >>expect <<EXPECT_END
460 commit #$i
461 note for commit #$i
462 EXPECT_END
463 i=$(($i - 1))
464 done
466 test_expect_success 'add lots of commits and notes' '
468 git fast-import <input &&
469 GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
470 grep "^ " > actual &&
471 test_cmp expect actual
475 test_expect_success 'verify that lots of notes trigger a fanout scheme' '
476 hexsz=$(test_oid hexsz) &&
478 # None of the entries in the top-level notes tree should be a full SHA1
479 git ls-tree --name-only refs/notes/many_notes |
480 while read path
482 if test $(expr length "$path") -ge $hexsz
483 then
484 return 1
486 done
490 # Create another notes tree from the one above
491 SP=" "
492 cat >>input <<INPUT_END
493 commit refs/heads/other_commits
494 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
495 data <<COMMIT
496 commit #$(($num_commit + 1))
497 COMMIT
499 from refs/heads/many_commits
500 M 644 inline file
501 data <<EOF
502 file contents in commit #$(($num_commit + 1))
505 commit refs/notes/other_notes
506 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
507 data <<COMMIT
508 committing one more note on a tree imported from a previous notes tree
509 COMMIT
511 M 040000 $(git log --no-walk --format=%T refs/notes/many_notes)$SP
512 N inline :$(($num_commit + 1))
513 data <<EOF
514 note for commit #$(($num_commit + 1))
516 INPUT_END
518 test_expect_success 'verify that importing a notes tree respects the fanout scheme' '
519 git fast-import <input &&
521 # None of the entries in the top-level notes tree should be a full SHA1
522 git ls-tree --name-only refs/notes/other_notes |
523 while read path
525 if test $(expr length "$path") -ge $hexsz
526 then
527 return 1
529 done
532 cat >>expect_non-note1 << EOF
533 This is not a note, but rather a regular file residing in a notes tree
536 cat >>expect_non-note2 << EOF
537 Non-note file
540 cat >>expect_non-note3 << EOF
541 Another non-note file
544 test_expect_success 'verify that non-notes are untouched by a fanout change' '
546 git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
547 test_cmp expect_non-note1 actual &&
548 git cat-file -p refs/notes/many_notes:deadbeef > actual &&
549 test_cmp expect_non-note2 actual &&
550 git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
551 test_cmp expect_non-note3 actual
555 # Change the notes for the three top commits
556 test_tick
557 cat >input <<INPUT_END
558 commit refs/notes/many_notes
559 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
560 data <<COMMIT
561 changing notes for the top three commits
562 COMMIT
563 from refs/notes/many_notes^0
564 INPUT_END
566 rm expect
567 i=$num_commits
569 while test $j -lt 3
571 cat >>input <<INPUT_END
572 N inline refs/heads/many_commits~$j
573 data <<EOF
574 changed note for commit #$i
576 INPUT_END
577 cat >>expect <<EXPECT_END
578 commit #$i
579 changed note for commit #$i
580 EXPECT_END
581 i=$(($i - 1))
582 j=$(($j + 1))
583 done
585 test_expect_success 'change a few existing notes' '
587 git fast-import <input &&
588 GIT_NOTES_REF=refs/notes/many_notes git log -n3 refs/heads/many_commits |
589 grep "^ " > actual &&
590 test_cmp expect actual
594 test_expect_success 'verify that changing notes respect existing fanout' '
596 # None of the entries in the top-level notes tree should be a full SHA1
597 git ls-tree --name-only refs/notes/many_notes |
598 while read path
600 if test $(expr length "$path") -ge $hexsz
601 then
602 return 1
604 done
608 remaining_notes=10
609 test_tick
610 cat >input <<INPUT_END
611 commit refs/notes/many_notes
612 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
613 data <<COMMIT
614 removing all notes but $remaining_notes
615 COMMIT
616 from refs/notes/many_notes^0
617 INPUT_END
619 i=$(($num_commits - $remaining_notes))
620 for sha1 in $(git rev-list -n $i refs/heads/many_commits)
622 cat >>input <<INPUT_END
623 N $ZERO_OID $sha1
624 INPUT_END
625 done
627 i=$num_commits
628 rm expect
629 while test $i -gt 0
631 cat >>expect <<EXPECT_END
632 commit #$i
633 EXPECT_END
634 if test $i -le $remaining_notes
635 then
636 cat >>expect <<EXPECT_END
637 note for commit #$i
638 EXPECT_END
640 i=$(($i - 1))
641 done
643 test_expect_success 'remove lots of notes' '
645 git fast-import <input &&
646 GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
647 grep "^ " > actual &&
648 test_cmp expect actual
652 test_expect_success 'verify that removing notes trigger fanout consolidation' '
653 # All entries in the top-level notes tree should be a full SHA1
654 git ls-tree --name-only -r refs/notes/many_notes |
655 while read path
657 # Explicitly ignore the non-note paths
658 test "$path" = "foobar/non-note.txt" && continue
659 test "$path" = "deadbeef" && continue
660 test "$path" = "de/adbeef" && continue
662 if test $(expr length "$path") -ne $hexsz
663 then
664 return 1
666 done
670 test_expect_success 'verify that non-notes are untouched by a fanout change' '
672 git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
673 test_cmp expect_non-note1 actual &&
674 git cat-file -p refs/notes/many_notes:deadbeef > actual &&
675 test_cmp expect_non-note2 actual &&
676 git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
677 test_cmp expect_non-note3 actual
682 rm input expect
683 num_notes_refs=10
684 num_commits=16
685 some_commits=8
686 # Create commits
687 fast_import_commits "refs/heads/more_commits" $num_commits input
688 # Create one note per above commit per notes ref
690 while test $i -lt $num_notes_refs
692 i=$(($i + 1))
693 fast_import_notes "refs/notes/more_notes_$i" $num_commits input
694 done
695 # Trigger branch reloading in git-fast-import by repeating the note creation
697 while test $i -lt $num_notes_refs
699 i=$(($i + 1))
700 fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
701 done
702 # Finally create the expected output from the notes in refs/notes/more_notes_1
703 i=$num_commits
704 while test $i -gt 0
706 note_data="note for commit #$i"
707 if test $i -le $some_commits
708 then
709 note_data="$note_data (2)"
711 cat >>expect <<EXPECT_END
712 commit #$i
713 $note_data
714 EXPECT_END
715 i=$(($i - 1))
716 done
718 test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
720 git fast-import --active-branches=5 <input &&
721 GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
722 grep "^ " > actual &&
723 test_cmp expect actual
727 test_done