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