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
258whitespace=" "
259
260cat >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
275EXPECT_END
276
277test_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
285test_tick
286cat >input <<INPUT_END
287commit refs/notes/test
288committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
289data <<COMMIT
290fifth notes commit
291COMMIT
292
293from refs/notes/test^0
294deleteall
295
296INPUT_END
297
298cat >expect <<EXPECT_END
299 fourth commit
300 third commit
301 second commit
302 first commit
303EXPECT_END
304
305test_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
313test_tick
314cat >input <<INPUT_END
315commit refs/notes/test
316committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
317data <<COMMIT
318sixth notes commit
319COMMIT
320
321from refs/notes/test^0
322M 644 inline $commit1
323data <<EOF
324third note for first commit
325EOF
326
327M 644 inline $commit3
328data <<EOF
329third note for third commit
330EOF
331
332N inline $commit1
333data <<EOF
334fourth note for first commit
335EOF
336
337N inline $commit3
338data <<EOF
339fourth note for third commit
340EOF
341
342INPUT_END
343
344cat >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
351EXPECT_END
352
353test_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
362fast_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
372commit $my_ref
373mark :$my_i
374committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
375data <<COMMIT
376commit #$my_i
377COMMIT
378
379M 644 inline file
380data <<EOF
381file contents in commit #$my_i
382EOF
383
384INPUT_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()
390fast_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
397commit $my_notes_ref
398committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
399data <<COMMIT
400committing $my_num_commits notes
401COMMIT
402
403INPUT_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
410N inline :$my_i
411data <<EOF
412note for commit #$my_i$my_note_append
413EOF
414
415INPUT_END
416 done
417}
418
419
420rm input expect
421num_commits=400
422# Create lots of commits
423fast_import_commits "refs/heads/many_commits" $num_commits input
424# Create one note per above commit
425fast_import_notes "refs/notes/many_notes" $num_commits input
426# Add a couple of non-notes as well
427test_tick
428cat >>input <<INPUT_END
429commit refs/notes/many_notes
430committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
431data <<COMMIT
432committing some non-notes to the notes tree
433COMMIT
434
435M 755 inline foobar/non-note.txt
436data <<EOF
437This is not a note, but rather a regular file residing in a notes tree
438EOF
439
440M 644 inline deadbeef
441data <<EOF
442Non-note file
443EOF
444
445M 644 inline de/adbeef
446data <<EOF
447Another non-note file
448EOF
449
450INPUT_END
451# Finally create the expected output from all these notes and commits
452i=$num_commits
453while test $i -gt 0
454do
455 cat >>expect <<EXPECT_END
456 commit #$i
457 note for commit #$i
458EXPECT_END
459 i=$(($i - 1))
460done
461
462test_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
471test_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
485cat >>expect_non-note1 << EOF
486This is not a note, but rather a regular file residing in a notes tree
487EOF
488
489cat >>expect_non-note2 << EOF
490Non-note file
491EOF
492
493cat >>expect_non-note3 << EOF
494Another non-note file
495EOF
496
497test_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'
507remaining_notes=10
508test_tick
509cat >>input <<INPUT_END
510commit refs/notes/many_notes
511committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
512data <<COMMIT
513removing all notes but $remaining_notes
514COMMIT
515from refs/notes/many_notes^0
516INPUT_END
517
518i=$remaining_notes
519while test $i -lt $num_commits
520do
521 i=$(($i + 1))
522 cat >>input <<INPUT_END
523N 0000000000000000000000000000000000000000 :$i
524INPUT_END
525done
526
527i=$num_commits
528rm expect
529while test $i -gt 0
530do
531 cat >>expect <<EXPECT_END
532 commit #$i
533EXPECT_END
534 if test $i -le $remaining_notes
535 then
536 cat >>expect <<EXPECT_END
537 note for commit #$i
538EXPECT_END
539 fi
540 i=$(($i - 1))
541done
542
543test_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
552test_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
571test_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
583rm input expect
584num_notes_refs=10
585num_commits=16
586some_commits=8
587# Create commits
588fast_import_commits "refs/heads/more_commits" $num_commits input
589# Create one note per above commit per notes ref
590i=0
591while test $i -lt $num_notes_refs
592do
593 i=$(($i + 1))
594 fast_import_notes "refs/notes/more_notes_$i" $num_commits input
595done
596# Trigger branch reloading in git-fast-import by repeating the note creation
597i=0
598while test $i -lt $num_notes_refs
599do
600 i=$(($i + 1))
601 fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
602done
603# Finally create the expected output from the notes in refs/notes/more_notes_1
604i=$num_commits
605while test $i -gt 0
606do
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
615EXPECT_END
616 i=$(($i - 1))
617done
618
619test_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
628test_done