Git 2.45
[git/gitster.git] / t / t9301-fast-import-notes.sh
blob58413221e6a73dcb464f0f226616b0bba4ea30dd
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_PASSES_SANITIZE_LEAK=true
11 . ./test-lib.sh
14 test_tick
15 cat >input <<INPUT_END
16 commit refs/heads/main
17 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
18 data <<COMMIT
19 first commit
20 COMMIT
22 M 644 inline foo
23 data <<EOF
24 file foo in first commit
25 EOF
27 M 755 inline bar
28 data <<EOF
29 file bar in first commit
30 EOF
32 M 644 inline baz/xyzzy
33 data <<EOF
34 file baz/xyzzy in first commit
35 EOF
37 commit refs/heads/main
38 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
39 data <<COMMIT
40 second commit
41 COMMIT
43 M 644 inline foo
44 data <<EOF
45 file foo in second commit
46 EOF
48 M 755 inline baz/xyzzy
49 data <<EOF
50 file baz/xyzzy in second commit
51 EOF
53 commit refs/heads/main
54 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
55 data <<COMMIT
56 third commit
57 COMMIT
59 M 644 inline foo
60 data <<EOF
61 file foo in third commit
62 EOF
64 commit refs/heads/main
65 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
66 data <<COMMIT
67 fourth commit
68 COMMIT
70 M 755 inline bar
71 data <<EOF
72 file bar in fourth commit
73 EOF
75 INPUT_END
77 test_expect_success 'set up main branch' '
79 git fast-import <input &&
80 git whatchanged main
83 commit4=$(git rev-parse refs/heads/main)
84 commit3=$(git rev-parse "$commit4^")
85 commit2=$(git rev-parse "$commit4~2")
86 commit1=$(git rev-parse "$commit4~3")
88 test_tick
89 cat >input <<INPUT_END
90 commit refs/notes/test
91 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
92 data <<COMMIT
93 first notes commit
94 COMMIT
96 M 644 inline $commit1
97 data <<EOF
98 first note for first commit
99 EOF
101 M 755 inline $commit2
102 data <<EOF
103 first note for second commit
106 INPUT_END
108 cat >expect <<EXPECT_END
109 fourth commit
110 third commit
111 second commit
112 first note for second commit
113 first commit
114 first note for first commit
115 EXPECT_END
117 test_expect_success 'add notes with simple M command' '
119 git fast-import <input &&
120 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
121 test_cmp expect actual
125 test_tick
126 cat >input <<INPUT_END
127 feature notes
128 commit refs/notes/test
129 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
130 data <<COMMIT
131 second notes commit
132 COMMIT
134 from refs/notes/test^0
135 N inline $commit3
136 data <<EOF
137 first note for third commit
140 N inline $commit4
141 data <<EOF
142 first note for fourth commit
145 INPUT_END
147 cat >expect <<EXPECT_END
148 fourth commit
149 first note for fourth commit
150 third commit
151 first note for third commit
152 second commit
153 first note for second commit
154 first commit
155 first note for first commit
156 EXPECT_END
158 test_expect_success 'add notes with simple N command' '
160 git fast-import <input &&
161 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
162 test_cmp expect actual
166 test_tick
167 cat >input <<INPUT_END
168 commit refs/notes/test
169 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
170 data <<COMMIT
171 third notes commit
172 COMMIT
174 from refs/notes/test^0
175 N inline $commit1
176 data <<EOF
177 second note for first commit
180 N inline $commit2
181 data <<EOF
182 second note for second commit
185 N inline $commit3
186 data <<EOF
187 second note for third commit
190 N inline $commit4
191 data <<EOF
192 second note for fourth commit
195 INPUT_END
197 cat >expect <<EXPECT_END
198 fourth commit
199 second note for fourth commit
200 third commit
201 second note for third commit
202 second commit
203 second note for second commit
204 first commit
205 second note for first commit
206 EXPECT_END
208 test_expect_success 'update existing notes with N command' '
210 git fast-import <input &&
211 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
212 test_cmp expect actual
216 test_tick
217 cat >input <<INPUT_END
218 commit refs/notes/test
219 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
220 data <<COMMIT
221 fourth notes commit
222 COMMIT
224 from refs/notes/test^0
225 M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
226 data <<EOF
227 prefix of note for third commit
230 M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
231 data <<EOF
232 prefix of note for fourth commit
235 M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
236 data <<EOF
237 pre-prefix of note for fourth commit
240 N inline $commit1
241 data <<EOF
242 third note for first commit
245 N inline $commit2
246 data <<EOF
247 third note for second commit
250 N inline $commit3
251 data <<EOF
252 third note for third commit
255 N inline $commit4
256 data <<EOF
257 third note for fourth commit
261 INPUT_END
263 whitespace=" "
265 cat >expect <<EXPECT_END
266 fourth commit
267 pre-prefix of note for fourth commit
268 $whitespace
269 prefix of note for fourth commit
270 $whitespace
271 third note for fourth commit
272 third commit
273 prefix of note for third commit
274 $whitespace
275 third note for third commit
276 second commit
277 third note for second commit
278 first commit
279 third note for first commit
280 EXPECT_END
282 test_expect_success 'add concatenation notes with M command' '
284 git fast-import <input &&
285 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
286 test_cmp expect actual
290 test_tick
291 cat >input <<INPUT_END
292 commit refs/notes/test
293 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
294 data <<COMMIT
295 fifth notes commit
296 COMMIT
298 from refs/notes/test^0
299 deleteall
301 INPUT_END
303 cat >expect <<EXPECT_END
304 fourth commit
305 third commit
306 second commit
307 first commit
308 EXPECT_END
310 test_expect_success 'verify that deleteall also removes notes' '
312 git fast-import <input &&
313 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
314 test_cmp expect actual
318 test_tick
319 cat >input <<INPUT_END
320 commit refs/notes/test
321 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
322 data <<COMMIT
323 sixth notes commit
324 COMMIT
326 from refs/notes/test^0
327 M 644 inline $commit1
328 data <<EOF
329 third note for first commit
332 M 644 inline $commit3
333 data <<EOF
334 third note for third commit
337 N inline $commit1
338 data <<EOF
339 fourth note for first commit
342 N inline $commit3
343 data <<EOF
344 fourth note for third commit
347 INPUT_END
349 cat >expect <<EXPECT_END
350 fourth commit
351 third commit
352 fourth note for third commit
353 second commit
354 first commit
355 fourth note for first commit
356 EXPECT_END
358 test_expect_success 'verify that later N commands override earlier M commands' '
360 git fast-import <input &&
361 GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
362 test_cmp expect actual
366 # Write fast-import commands to create the given number of commits
367 fast_import_commits () {
368 my_ref=$1
369 my_num_commits=$2
370 my_append_to_file=$3
371 my_i=0
372 while test $my_i -lt $my_num_commits
374 my_i=$(($my_i + 1))
375 test_tick
376 cat >>"$my_append_to_file" <<INPUT_END
377 commit $my_ref
378 mark :$my_i
379 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
380 data <<COMMIT
381 commit #$my_i
382 COMMIT
384 M 644 inline file
385 data <<EOF
386 file contents in commit #$my_i
389 INPUT_END
390 done
393 # Write fast-import commands to create the given number of notes annotating
394 # the commits created by fast_import_commits()
395 fast_import_notes () {
396 my_notes_ref=$1
397 my_num_commits=$2
398 my_append_to_file=$3
399 my_note_append=$4
400 test_tick
401 cat >>"$my_append_to_file" <<INPUT_END
402 commit $my_notes_ref
403 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
404 data <<COMMIT
405 committing $my_num_commits notes
406 COMMIT
408 INPUT_END
410 my_i=0
411 while test $my_i -lt $my_num_commits
413 my_i=$(($my_i + 1))
414 cat >>"$my_append_to_file" <<INPUT_END
415 N inline :$my_i
416 data <<EOF
417 note for commit #$my_i$my_note_append
420 INPUT_END
421 done
425 rm input expect
426 num_commits=400
427 # Create lots of commits
428 fast_import_commits "refs/heads/many_commits" $num_commits input
429 # Create one note per above commit
430 fast_import_notes "refs/notes/many_notes" $num_commits input
431 # Add a couple of non-notes as well
432 test_tick
433 cat >>input <<INPUT_END
434 commit refs/notes/many_notes
435 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
436 data <<COMMIT
437 committing some non-notes to the notes tree
438 COMMIT
440 M 755 inline foobar/non-note.txt
441 data <<EOF
442 This is not a note, but rather a regular file residing in a notes tree
445 M 644 inline deadbeef
446 data <<EOF
447 Non-note file
450 M 644 inline de/adbeef
451 data <<EOF
452 Another non-note file
455 INPUT_END
456 # Finally create the expected output from all these notes and commits
457 i=$num_commits
458 while test $i -gt 0
460 cat >>expect <<EXPECT_END
461 commit #$i
462 note for commit #$i
463 EXPECT_END
464 i=$(($i - 1))
465 done
467 test_expect_success 'add lots of commits and notes' '
469 git fast-import <input &&
470 GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
471 grep "^ " > actual &&
472 test_cmp expect actual
476 test_expect_success 'verify that lots of notes trigger a fanout scheme' '
477 hexsz=$(test_oid hexsz) &&
479 # None of the entries in the top-level notes tree should be a full SHA1
480 git ls-tree --name-only refs/notes/many_notes |
481 while read path
483 if test $(expr length "$path") -ge $hexsz
484 then
485 return 1
487 done
491 # Create another notes tree from the one above
492 SP=" "
493 cat >>input <<INPUT_END
494 commit refs/heads/other_commits
495 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
496 data <<COMMIT
497 commit #$(($num_commit + 1))
498 COMMIT
500 from refs/heads/many_commits
501 M 644 inline file
502 data <<EOF
503 file contents in commit #$(($num_commit + 1))
506 commit refs/notes/other_notes
507 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
508 data <<COMMIT
509 committing one more note on a tree imported from a previous notes tree
510 COMMIT
512 M 040000 $(git log --no-walk --format=%T refs/notes/many_notes)$SP
513 N inline :$(($num_commit + 1))
514 data <<EOF
515 note for commit #$(($num_commit + 1))
517 INPUT_END
519 test_expect_success 'verify that importing a notes tree respects the fanout scheme' '
520 git fast-import <input &&
522 # None of the entries in the top-level notes tree should be a full SHA1
523 git ls-tree --name-only refs/notes/other_notes |
524 while read path
526 if test $(expr length "$path") -ge $hexsz
527 then
528 return 1
530 done
533 cat >>expect_non-note1 << EOF
534 This is not a note, but rather a regular file residing in a notes tree
537 cat >>expect_non-note2 << EOF
538 Non-note file
541 cat >>expect_non-note3 << EOF
542 Another non-note file
545 test_expect_success 'verify that non-notes are untouched by a fanout change' '
547 git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
548 test_cmp expect_non-note1 actual &&
549 git cat-file -p refs/notes/many_notes:deadbeef > actual &&
550 test_cmp expect_non-note2 actual &&
551 git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
552 test_cmp expect_non-note3 actual
556 # Change the notes for the three top commits
557 test_tick
558 cat >input <<INPUT_END
559 commit refs/notes/many_notes
560 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
561 data <<COMMIT
562 changing notes for the top three commits
563 COMMIT
564 from refs/notes/many_notes^0
565 INPUT_END
567 rm expect
568 i=$num_commits
570 while test $j -lt 3
572 cat >>input <<INPUT_END
573 N inline refs/heads/many_commits~$j
574 data <<EOF
575 changed note for commit #$i
577 INPUT_END
578 cat >>expect <<EXPECT_END
579 commit #$i
580 changed note for commit #$i
581 EXPECT_END
582 i=$(($i - 1))
583 j=$(($j + 1))
584 done
586 test_expect_success 'change a few existing notes' '
588 git fast-import <input &&
589 GIT_NOTES_REF=refs/notes/many_notes git log -n3 refs/heads/many_commits |
590 grep "^ " > actual &&
591 test_cmp expect actual
595 test_expect_success 'verify that changing notes respect existing fanout' '
597 # None of the entries in the top-level notes tree should be a full SHA1
598 git ls-tree --name-only refs/notes/many_notes |
599 while read path
601 if test $(expr length "$path") -ge $hexsz
602 then
603 return 1
605 done
609 remaining_notes=10
610 test_tick
611 cat >input <<INPUT_END
612 commit refs/notes/many_notes
613 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
614 data <<COMMIT
615 removing all notes but $remaining_notes
616 COMMIT
617 from refs/notes/many_notes^0
618 INPUT_END
620 i=$(($num_commits - $remaining_notes))
621 for sha1 in $(git rev-list -n $i refs/heads/many_commits)
623 cat >>input <<INPUT_END
624 N $ZERO_OID $sha1
625 INPUT_END
626 done
628 i=$num_commits
629 rm expect
630 while test $i -gt 0
632 cat >>expect <<EXPECT_END
633 commit #$i
634 EXPECT_END
635 if test $i -le $remaining_notes
636 then
637 cat >>expect <<EXPECT_END
638 note for commit #$i
639 EXPECT_END
641 i=$(($i - 1))
642 done
644 test_expect_success 'remove lots of notes' '
646 git fast-import <input &&
647 GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
648 grep "^ " > actual &&
649 test_cmp expect actual
653 test_expect_success 'verify that removing notes trigger fanout consolidation' '
654 # All entries in the top-level notes tree should be a full SHA1
655 git ls-tree --name-only -r refs/notes/many_notes |
656 while read path
658 # Explicitly ignore the non-note paths
659 test "$path" = "foobar/non-note.txt" && continue
660 test "$path" = "deadbeef" && continue
661 test "$path" = "de/adbeef" && continue
663 if test $(expr length "$path") -ne $hexsz
664 then
665 return 1
667 done
671 test_expect_success 'verify that non-notes are untouched by a fanout change' '
673 git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
674 test_cmp expect_non-note1 actual &&
675 git cat-file -p refs/notes/many_notes:deadbeef > actual &&
676 test_cmp expect_non-note2 actual &&
677 git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
678 test_cmp expect_non-note3 actual
683 rm input expect
684 num_notes_refs=10
685 num_commits=16
686 some_commits=8
687 # Create commits
688 fast_import_commits "refs/heads/more_commits" $num_commits input
689 # Create one note per above commit per notes ref
691 while test $i -lt $num_notes_refs
693 i=$(($i + 1))
694 fast_import_notes "refs/notes/more_notes_$i" $num_commits input
695 done
696 # Trigger branch reloading in git-fast-import by repeating the note creation
698 while test $i -lt $num_notes_refs
700 i=$(($i + 1))
701 fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
702 done
703 # Finally create the expected output from the notes in refs/notes/more_notes_1
704 i=$num_commits
705 while test $i -gt 0
707 note_data="note for commit #$i"
708 if test $i -le $some_commits
709 then
710 note_data="$note_data (2)"
712 cat >>expect <<EXPECT_END
713 commit #$i
714 $note_data
715 EXPECT_END
716 i=$(($i - 1))
717 done
719 test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
721 git fast-import --active-branches=5 <input &&
722 GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
723 grep "^ " > actual &&
724 test_cmp expect actual
728 test_done