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