vcs-svn: add a comment before each commit
[git] / t / t9010-svn-fe.sh
1 #!/bin/sh
2
3 test_description='check svn dumpfile importer'
4
5 . ./test-lib.sh
6
7 reinit_git () {
8         if ! test_declared_prereq PIPE
9         then
10                 echo >&4 "reinit_git: need to declare PIPE prerequisite"
11                 return 127
12         fi
13         rm -fr .git &&
14         rm -f stream backflow &&
15         git init &&
16         mkfifo stream backflow
17 }
18
19 try_dump () {
20         input=$1 &&
21         maybe_fail=${2:+test_$2} &&
22
23         {
24                 $maybe_fail test-svn-fe "$input" >stream 3<backflow &
25         } &&
26         git fast-import --cat-blob-fd=3 <stream 3>backflow &&
27         wait $!
28 }
29
30 properties () {
31         while test "$#" -ne 0
32         do
33                 property="$1" &&
34                 value="$2" &&
35                 printf "%s\n" "K ${#property}" &&
36                 printf "%s\n" "$property" &&
37                 printf "%s\n" "V ${#value}" &&
38                 printf "%s\n" "$value" &&
39                 shift 2 ||
40                 return 1
41         done
42 }
43
44 text_no_props () {
45         text="$1
46 " &&
47         printf "%s\n" "Prop-content-length: 10" &&
48         printf "%s\n" "Text-content-length: ${#text}" &&
49         printf "%s\n" "Content-length: $((${#text} + 10))" &&
50         printf "%s\n" "" "PROPS-END" &&
51         printf "%s\n" "$text"
52 }
53
54 >empty
55
56 test_expect_success 'setup: have pipes?' '
57         rm -f frob &&
58         if mkfifo frob
59         then
60                 test_set_prereq PIPE
61         fi
62 '
63
64 test_expect_success PIPE 'empty dump' '
65         reinit_git &&
66         echo "SVN-fs-dump-format-version: 2" >input &&
67         try_dump input
68 '
69
70 test_expect_success PIPE 'v4 dumps not supported' '
71         reinit_git &&
72         echo "SVN-fs-dump-format-version: 4" >v4.dump &&
73         try_dump v4.dump must_fail
74 '
75
76 test_expect_failure PIPE 'empty revision' '
77         reinit_git &&
78         printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
79         cat >emptyrev.dump <<-\EOF &&
80         SVN-fs-dump-format-version: 3
81
82         Revision-number: 1
83         Prop-content-length: 0
84         Content-length: 0
85
86         Revision-number: 2
87         Prop-content-length: 0
88         Content-length: 0
89
90         EOF
91         try_dump emptyrev.dump &&
92         git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
93         test_cmp expect actual
94 '
95
96 test_expect_success PIPE 'empty properties' '
97         reinit_git &&
98         printf "rev <nobody, nobody@local>: %s\n" "" "" >expect &&
99         cat >emptyprop.dump <<-\EOF &&
100         SVN-fs-dump-format-version: 3
101
102         Revision-number: 1
103         Prop-content-length: 10
104         Content-length: 10
105
106         PROPS-END
107
108         Revision-number: 2
109         Prop-content-length: 10
110         Content-length: 10
111
112         PROPS-END
113         EOF
114         try_dump emptyprop.dump &&
115         git log -p --format="rev <%an, %ae>: %s" HEAD >actual &&
116         test_cmp expect actual
117 '
118
119 test_expect_success PIPE 'author name and commit message' '
120         reinit_git &&
121         echo "<author@example.com, author@example.com@local>" >expect.author &&
122         cat >message <<-\EOF &&
123         A concise summary of the change
124
125         A detailed description of the change, why it is needed, what
126         was broken and why applying this is the best course of action.
127
128         * file.c
129             Details pertaining to an individual file.
130         EOF
131         {
132                 properties \
133                         svn:author author@example.com \
134                         svn:log "$(cat message)" &&
135                 echo PROPS-END
136         } >props &&
137         {
138                 echo "SVN-fs-dump-format-version: 3" &&
139                 echo &&
140                 echo "Revision-number: 1" &&
141                 echo Prop-content-length: $(wc -c <props) &&
142                 echo Content-length: $(wc -c <props) &&
143                 echo &&
144                 cat props
145         } >log.dump &&
146         try_dump log.dump &&
147         git log -p --format="%B" HEAD >actual.log &&
148         git log --format="<%an, %ae>" >actual.author &&
149         test_cmp message actual.log &&
150         test_cmp expect.author actual.author
151 '
152
153 test_expect_success PIPE 'unsupported properties are ignored' '
154         reinit_git &&
155         echo author >expect &&
156         cat >extraprop.dump <<-\EOF &&
157         SVN-fs-dump-format-version: 3
158
159         Revision-number: 1
160         Prop-content-length: 56
161         Content-length: 56
162
163         K 8
164         nonsense
165         V 1
166         y
167         K 10
168         svn:author
169         V 6
170         author
171         PROPS-END
172         EOF
173         try_dump extraprop.dump &&
174         git log -p --format=%an HEAD >actual &&
175         test_cmp expect actual
176 '
177
178 test_expect_failure PIPE 'timestamp and empty file' '
179         echo author@example.com >expect.author &&
180         echo 1999-01-01 >expect.date &&
181         echo file >expect.files &&
182         reinit_git &&
183         {
184                 properties \
185                         svn:author author@example.com \
186                         svn:date "1999-01-01T00:01:002.000000Z" \
187                         svn:log "add empty file" &&
188                 echo PROPS-END
189         } >props &&
190         {
191                 cat <<-EOF &&
192                 SVN-fs-dump-format-version: 3
193
194                 Revision-number: 1
195                 EOF
196                 echo Prop-content-length: $(wc -c <props) &&
197                 echo Content-length: $(wc -c <props) &&
198                 echo &&
199                 cat props &&
200                 cat <<-\EOF
201
202                 Node-path: empty-file
203                 Node-kind: file
204                 Node-action: add
205                 Content-length: 0
206
207                 EOF
208         } >emptyfile.dump &&
209         try_dump emptyfile.dump &&
210         git log --format=%an HEAD >actual.author &&
211         git log --date=short --format=%ad HEAD >actual.date &&
212         git ls-tree -r --name-only HEAD >actual.files &&
213         test_cmp expect.author actual.author &&
214         test_cmp expect.date actual.date &&
215         test_cmp expect.files actual.files &&
216         git checkout HEAD empty-file &&
217         test_cmp empty file
218 '
219
220 test_expect_success PIPE 'directory with files' '
221         reinit_git &&
222         printf "%s\n" directory/file1 directory/file2 >expect.files &&
223         echo hi >hi &&
224         echo hello >hello &&
225         {
226                 properties \
227                         svn:author author@example.com \
228                         svn:date "1999-02-01T00:01:002.000000Z" \
229                         svn:log "add directory with some files in it" &&
230                 echo PROPS-END
231         } >props &&
232         {
233                 cat <<-EOF &&
234                 SVN-fs-dump-format-version: 3
235
236                 Revision-number: 1
237                 EOF
238                 echo Prop-content-length: $(wc -c <props) &&
239                 echo Content-length: $(wc -c <props) &&
240                 echo &&
241                 cat props &&
242                 cat <<-\EOF &&
243
244                 Node-path: directory
245                 Node-kind: dir
246                 Node-action: add
247                 Prop-content-length: 10
248                 Content-length: 10
249
250                 PROPS-END
251
252                 Node-path: directory/file1
253                 Node-kind: file
254                 Node-action: add
255                 EOF
256                 text_no_props hello &&
257                 cat <<-\EOF &&
258                 Node-path: directory/file2
259                 Node-kind: file
260                 Node-action: add
261                 EOF
262                 text_no_props hi
263         } >directory.dump &&
264         try_dump directory.dump &&
265
266         git ls-tree -r --name-only HEAD >actual.files &&
267         git checkout HEAD directory &&
268         test_cmp expect.files actual.files &&
269         test_cmp hello directory/file1 &&
270         test_cmp hi directory/file2
271 '
272
273 test_expect_success PIPE 'node without action' '
274         reinit_git &&
275         cat >inaction.dump <<-\EOF &&
276         SVN-fs-dump-format-version: 3
277
278         Revision-number: 1
279         Prop-content-length: 10
280         Content-length: 10
281
282         PROPS-END
283
284         Node-path: directory
285         Node-kind: dir
286         Prop-content-length: 10
287         Content-length: 10
288
289         PROPS-END
290         EOF
291         try_dump inaction.dump must_fail
292 '
293
294 test_expect_success PIPE 'action: add node without text' '
295         reinit_git &&
296         cat >textless.dump <<-\EOF &&
297         SVN-fs-dump-format-version: 3
298
299         Revision-number: 1
300         Prop-content-length: 10
301         Content-length: 10
302
303         PROPS-END
304
305         Node-path: textless
306         Node-kind: file
307         Node-action: add
308         Prop-content-length: 10
309         Content-length: 10
310
311         PROPS-END
312         EOF
313         try_dump textless.dump must_fail
314 '
315
316 test_expect_failure PIPE 'change file mode but keep old content' '
317         reinit_git &&
318         cat >expect <<-\EOF &&
319         OBJID
320         :120000 100644 OBJID OBJID T    greeting
321         OBJID
322         :100644 120000 OBJID OBJID T    greeting
323         OBJID
324         :000000 100644 OBJID OBJID A    greeting
325         EOF
326         echo "link hello" >expect.blob &&
327         echo hello >hello &&
328         cat >filemode.dump <<-\EOF &&
329         SVN-fs-dump-format-version: 3
330
331         Revision-number: 1
332         Prop-content-length: 10
333         Content-length: 10
334
335         PROPS-END
336
337         Node-path: greeting
338         Node-kind: file
339         Node-action: add
340         Prop-content-length: 10
341         Text-content-length: 11
342         Content-length: 21
343
344         PROPS-END
345         link hello
346
347         Revision-number: 2
348         Prop-content-length: 10
349         Content-length: 10
350
351         PROPS-END
352
353         Node-path: greeting
354         Node-kind: file
355         Node-action: change
356         Prop-content-length: 33
357         Content-length: 33
358
359         K 11
360         svn:special
361         V 1
362         *
363         PROPS-END
364
365         Revision-number: 3
366         Prop-content-length: 10
367         Content-length: 10
368
369         PROPS-END
370
371         Node-path: greeting
372         Node-kind: file
373         Node-action: change
374         Prop-content-length: 10
375         Content-length: 10
376
377         PROPS-END
378         EOF
379         try_dump filemode.dump &&
380         {
381                 git rev-list HEAD |
382                 git diff-tree --root --stdin |
383                 sed "s/$_x40/OBJID/g"
384         } >actual &&
385         git show HEAD:greeting >actual.blob &&
386         git show HEAD^:greeting >actual.target &&
387         test_cmp expect actual &&
388         test_cmp expect.blob actual.blob &&
389         test_cmp hello actual.target
390 '
391
392 test_expect_success PIPE 'change file mode and reiterate content' '
393         reinit_git &&
394         cat >expect <<-\EOF &&
395         OBJID
396         :120000 100644 OBJID OBJID T    greeting
397         OBJID
398         :100644 120000 OBJID OBJID T    greeting
399         OBJID
400         :000000 100644 OBJID OBJID A    greeting
401         EOF
402         echo "link hello" >expect.blob &&
403         echo hello >hello &&
404         cat >filemode2.dump <<-\EOF &&
405         SVN-fs-dump-format-version: 3
406
407         Revision-number: 1
408         Prop-content-length: 10
409         Content-length: 10
410
411         PROPS-END
412
413         Node-path: greeting
414         Node-kind: file
415         Node-action: add
416         Prop-content-length: 10
417         Text-content-length: 11
418         Content-length: 21
419
420         PROPS-END
421         link hello
422
423         Revision-number: 2
424         Prop-content-length: 10
425         Content-length: 10
426
427         PROPS-END
428
429         Node-path: greeting
430         Node-kind: file
431         Node-action: change
432         Prop-content-length: 33
433         Text-content-length: 11
434         Content-length: 44
435
436         K 11
437         svn:special
438         V 1
439         *
440         PROPS-END
441         link hello
442
443         Revision-number: 3
444         Prop-content-length: 10
445         Content-length: 10
446
447         PROPS-END
448
449         Node-path: greeting
450         Node-kind: file
451         Node-action: change
452         Prop-content-length: 10
453         Text-content-length: 11
454         Content-length: 21
455
456         PROPS-END
457         link hello
458         EOF
459         try_dump filemode2.dump &&
460         {
461                 git rev-list HEAD |
462                 git diff-tree --root --stdin |
463                 sed "s/$_x40/OBJID/g"
464         } >actual &&
465         git show HEAD:greeting >actual.blob &&
466         git show HEAD^:greeting >actual.target &&
467         test_cmp expect actual &&
468         test_cmp expect.blob actual.blob &&
469         test_cmp hello actual.target
470 '
471
472 test_expect_success PIPE 'deltas not supported' '
473         reinit_git &&
474         {
475                 # (old) h + (inline) ello + (old) \n
476                 printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
477                 q_to_nul
478         } >delta &&
479         {
480                 properties \
481                         svn:author author@example.com \
482                         svn:date "1999-01-05T00:01:002.000000Z" \
483                         svn:log "add greeting" &&
484                 echo PROPS-END
485         } >props &&
486         {
487                 properties \
488                         svn:author author@example.com \
489                         svn:date "1999-01-06T00:01:002.000000Z" \
490                         svn:log "change it" &&
491                 echo PROPS-END
492         } >props2 &&
493         {
494                 echo SVN-fs-dump-format-version: 3 &&
495                 echo &&
496                 echo Revision-number: 1 &&
497                 echo Prop-content-length: $(wc -c <props) &&
498                 echo Content-length: $(wc -c <props) &&
499                 echo &&
500                 cat props &&
501                 cat <<-\EOF &&
502
503                 Node-path: hello
504                 Node-kind: file
505                 Node-action: add
506                 Prop-content-length: 10
507                 Text-content-length: 3
508                 Content-length: 13
509
510                 PROPS-END
511                 hi
512
513                 EOF
514                 echo Revision-number: 2 &&
515                 echo Prop-content-length: $(wc -c <props2) &&
516                 echo Content-length: $(wc -c <props2) &&
517                 echo &&
518                 cat props2 &&
519                 cat <<-\EOF &&
520
521                 Node-path: hello
522                 Node-kind: file
523                 Node-action: change
524                 Text-delta: true
525                 Prop-content-length: 10
526                 EOF
527                 echo Text-content-length: $(wc -c <delta) &&
528                 echo Content-length: $((10 + $(wc -c <delta))) &&
529                 echo &&
530                 echo PROPS-END &&
531                 cat delta
532         } >delta.dump &&
533         test_must_fail try_dump delta.dump
534 '
535
536 test_expect_success PIPE 'property deltas supported' '
537         reinit_git &&
538         cat >expect <<-\EOF &&
539         OBJID
540         :100755 100644 OBJID OBJID M    script.sh
541         EOF
542         {
543                 properties \
544                         svn:author author@example.com \
545                         svn:date "1999-03-06T00:01:002.000000Z" \
546                         svn:log "make an executable, or chmod -x it" &&
547                 echo PROPS-END
548         } >revprops &&
549         {
550                 echo SVN-fs-dump-format-version: 3 &&
551                 echo &&
552                 echo Revision-number: 1 &&
553                 echo Prop-content-length: $(wc -c <revprops) &&
554                 echo Content-length: $(wc -c <revprops) &&
555                 echo &&
556                 cat revprops &&
557                 echo &&
558                 cat <<-\EOF &&
559                 Node-path: script.sh
560                 Node-kind: file
561                 Node-action: add
562                 Text-content-length: 0
563                 Prop-content-length: 39
564                 Content-length: 39
565
566                 K 14
567                 svn:executable
568                 V 4
569                 true
570                 PROPS-END
571
572                 EOF
573                 echo Revision-number: 2 &&
574                 echo Prop-content-length: $(wc -c <revprops) &&
575                 echo Content-length: $(wc -c <revprops) &&
576                 echo &&
577                 cat revprops &&
578                 echo &&
579                 cat <<-\EOF
580                 Node-path: script.sh
581                 Node-kind: file
582                 Node-action: change
583                 Prop-delta: true
584                 Prop-content-length: 30
585                 Content-length: 30
586
587                 D 14
588                 svn:executable
589                 PROPS-END
590                 EOF
591         } >propdelta.dump &&
592         try_dump propdelta.dump &&
593         {
594                 git rev-list HEAD |
595                 git diff-tree --stdin |
596                 sed "s/$_x40/OBJID/g"
597         } >actual &&
598         test_cmp expect actual
599 '
600
601 test_expect_success PIPE 'properties on /' '
602         reinit_git &&
603         cat <<-\EOF >expect &&
604         OBJID
605         OBJID
606         :000000 100644 OBJID OBJID A    greeting
607         EOF
608         sed -e "s/X$//" <<-\EOF >changeroot.dump &&
609         SVN-fs-dump-format-version: 3
610
611         Revision-number: 1
612         Prop-content-length: 10
613         Content-length: 10
614
615         PROPS-END
616
617         Node-path: greeting
618         Node-kind: file
619         Node-action: add
620         Text-content-length: 0
621         Prop-content-length: 10
622         Content-length: 10
623
624         PROPS-END
625
626         Revision-number: 2
627         Prop-content-length: 10
628         Content-length: 10
629
630         PROPS-END
631
632         Node-path: X
633         Node-kind: dir
634         Node-action: change
635         Prop-delta: true
636         Prop-content-length: 43
637         Content-length: 43
638
639         K 10
640         svn:ignore
641         V 11
642         build-area
643
644         PROPS-END
645         EOF
646         try_dump changeroot.dump &&
647         {
648                 git rev-list HEAD |
649                 git diff-tree --root --always --stdin |
650                 sed "s/$_x40/OBJID/g"
651         } >actual &&
652         test_cmp expect actual
653 '
654
655 test_expect_success PIPE 'deltas for typechange' '
656         reinit_git &&
657         cat >expect <<-\EOF &&
658         OBJID
659         :120000 100644 OBJID OBJID T    test-file
660         OBJID
661         :100755 120000 OBJID OBJID T    test-file
662         OBJID
663         :000000 100755 OBJID OBJID A    test-file
664         EOF
665         cat >deleteprop.dump <<-\EOF &&
666         SVN-fs-dump-format-version: 3
667
668         Revision-number: 1
669         Prop-content-length: 10
670         Content-length: 10
671
672         PROPS-END
673
674         Node-path: test-file
675         Node-kind: file
676         Node-action: add
677         Prop-delta: true
678         Prop-content-length: 35
679         Text-content-length: 17
680         Content-length: 52
681
682         K 14
683         svn:executable
684         V 0
685
686         PROPS-END
687         link testing 123
688
689         Revision-number: 2
690         Prop-content-length: 10
691         Content-length: 10
692
693         PROPS-END
694
695         Node-path: test-file
696         Node-kind: file
697         Node-action: change
698         Prop-delta: true
699         Prop-content-length: 53
700         Text-content-length: 17
701         Content-length: 70
702
703         K 11
704         svn:special
705         V 1
706         *
707         D 14
708         svn:executable
709         PROPS-END
710         link testing 231
711
712         Revision-number: 3
713         Prop-content-length: 10
714         Content-length: 10
715
716         PROPS-END
717
718         Node-path: test-file
719         Node-kind: file
720         Node-action: change
721         Prop-delta: true
722         Prop-content-length: 27
723         Text-content-length: 17
724         Content-length: 44
725
726         D 11
727         svn:special
728         PROPS-END
729         link testing 321
730         EOF
731         try_dump deleteprop.dump &&
732         {
733                 git rev-list HEAD |
734                 git diff-tree --root --stdin |
735                 sed "s/$_x40/OBJID/g"
736         } >actual &&
737         test_cmp expect actual
738 '
739
740
741 test_expect_success 'set up svn repo' '
742         svnconf=$PWD/svnconf &&
743         mkdir -p "$svnconf" &&
744
745         if
746                 svnadmin -h >/dev/null 2>&1 &&
747                 svnadmin create simple-svn &&
748                 svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" &&
749                 svn export --config-dir "$svnconf" "file://$PWD/simple-svn" simple-svnco
750         then
751                 test_set_prereq SVNREPO
752         fi
753 '
754
755 test_expect_success SVNREPO,PIPE 't9135/svn.dump' '
756         mkdir -p simple-git &&
757         (
758                 cd simple-git &&
759                 reinit_git &&
760                 try_dump "$TEST_DIRECTORY/t9135/svn.dump"
761         ) &&
762         (
763                 cd simple-svnco &&
764                 git init &&
765                 git add . &&
766                 git fetch ../simple-git master &&
767                 git diff --exit-code FETCH_HEAD
768         )
769 '
770
771 test_done