vcs-svn: Implement Prop-delta handling
[git] / t / t9010-svn-fe.sh
1 #!/bin/sh
2
3 test_description='check svn dumpfile importer'
4
5 . ./lib-git-svn.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 'change file mode and reiterate content' '
374         reinit_git &&
375         cat >expect <<-\EOF &&
376         OBJID
377         :120000 100644 OBJID OBJID T    greeting
378         OBJID
379         :100644 120000 OBJID OBJID T    greeting
380         OBJID
381         :000000 100644 OBJID OBJID A    greeting
382         EOF
383         echo "link hello" >expect.blob &&
384         echo hello >hello &&
385         cat >filemode.dump <<-\EOF &&
386         SVN-fs-dump-format-version: 3
387
388         Revision-number: 1
389         Prop-content-length: 10
390         Content-length: 10
391
392         PROPS-END
393
394         Node-path: greeting
395         Node-kind: file
396         Node-action: add
397         Prop-content-length: 10
398         Text-content-length: 11
399         Content-length: 21
400
401         PROPS-END
402         link hello
403
404         Revision-number: 2
405         Prop-content-length: 10
406         Content-length: 10
407
408         PROPS-END
409
410         Node-path: greeting
411         Node-kind: file
412         Node-action: change
413         Prop-content-length: 33
414         Text-content-length: 11
415         Content-length: 44
416
417         K 11
418         svn:special
419         V 1
420         *
421         PROPS-END
422         link hello
423
424         Revision-number: 3
425         Prop-content-length: 10
426         Content-length: 10
427
428         PROPS-END
429
430         Node-path: greeting
431         Node-kind: file
432         Node-action: change
433         Prop-content-length: 10
434         Text-content-length: 11
435         Content-length: 21
436
437         PROPS-END
438         link hello
439         EOF
440         test-svn-fe filemode.dump >stream &&
441         git fast-import <stream &&
442         {
443                 git rev-list HEAD |
444                 git diff-tree --root --stdin |
445                 sed "s/$_x40/OBJID/g"
446         } >actual &&
447         git show HEAD:greeting >actual.blob &&
448         git show HEAD^:greeting >actual.target &&
449         test_cmp expect actual &&
450         test_cmp expect.blob actual.blob &&
451         test_cmp hello actual.target
452 '
453
454 test_expect_success 'deltas not supported' '
455         {
456                 # (old) h + (inline) ello + (old) \n
457                 printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
458                 q_to_nul
459         } >delta &&
460         {
461                 properties \
462                         svn:author author@example.com \
463                         svn:date "1999-01-05T00:01:002.000000Z" \
464                         svn:log "add greeting" &&
465                 echo PROPS-END
466         } >props &&
467         {
468                 properties \
469                         svn:author author@example.com \
470                         svn:date "1999-01-06T00:01:002.000000Z" \
471                         svn:log "change it" &&
472                 echo PROPS-END
473         } >props2 &&
474         {
475                 echo SVN-fs-dump-format-version: 3 &&
476                 echo &&
477                 echo Revision-number: 1 &&
478                 echo Prop-content-length: $(wc -c <props) &&
479                 echo Content-length: $(wc -c <props) &&
480                 echo &&
481                 cat props &&
482                 cat <<-\EOF &&
483
484                 Node-path: hello
485                 Node-kind: file
486                 Node-action: add
487                 Prop-content-length: 10
488                 Text-content-length: 3
489                 Content-length: 13
490
491                 PROPS-END
492                 hi
493
494                 EOF
495                 echo Revision-number: 2 &&
496                 echo Prop-content-length: $(wc -c <props2) &&
497                 echo Content-length: $(wc -c <props2) &&
498                 echo &&
499                 cat props2 &&
500                 cat <<-\EOF &&
501
502                 Node-path: hello
503                 Node-kind: file
504                 Node-action: change
505                 Text-delta: true
506                 Prop-content-length: 10
507                 EOF
508                 echo Text-content-length: $(wc -c <delta) &&
509                 echo Content-length: $((10 + $(wc -c <delta))) &&
510                 echo &&
511                 echo PROPS-END &&
512                 cat delta
513         } >delta.dump &&
514         test_must_fail test-svn-fe delta.dump
515 '
516
517 test_expect_success 'property deltas supported' '
518         reinit_git &&
519         cat >expect <<-\EOF &&
520         OBJID
521         :100755 100644 OBJID OBJID M    script.sh
522         EOF
523         {
524                 properties \
525                         svn:author author@example.com \
526                         svn:date "1999-03-06T00:01:002.000000Z" \
527                         svn:log "make an executable, or chmod -x it" &&
528                 echo PROPS-END
529         } >revprops &&
530         {
531                 echo SVN-fs-dump-format-version: 3 &&
532                 echo &&
533                 echo Revision-number: 1 &&
534                 echo Prop-content-length: $(wc -c <revprops) &&
535                 echo Content-length: $(wc -c <revprops) &&
536                 echo &&
537                 cat revprops &&
538                 echo &&
539                 cat <<-\EOF &&
540                 Node-path: script.sh
541                 Node-kind: file
542                 Node-action: add
543                 Text-content-length: 0
544                 Prop-content-length: 39
545                 Content-length: 39
546
547                 K 14
548                 svn:executable
549                 V 4
550                 true
551                 PROPS-END
552
553                 EOF
554                 echo Revision-number: 2 &&
555                 echo Prop-content-length: $(wc -c <revprops) &&
556                 echo Content-length: $(wc -c <revprops) &&
557                 echo &&
558                 cat revprops &&
559                 echo &&
560                 cat <<-\EOF
561                 Node-path: script.sh
562                 Node-kind: file
563                 Node-action: change
564                 Prop-delta: true
565                 Prop-content-length: 30
566                 Content-length: 30
567
568                 D 14
569                 svn:executable
570                 PROPS-END
571                 EOF
572         } >propdelta.dump &&
573         test-svn-fe propdelta.dump >stream &&
574         git fast-import <stream &&
575         {
576                 git rev-list HEAD |
577                 git diff-tree --stdin |
578                 sed "s/$_x40/OBJID/g"
579         } >actual &&
580         test_cmp expect actual
581 '
582
583 test_expect_success 'deltas for typechange' '
584         reinit_git &&
585         cat >expect <<-\EOF &&
586         OBJID
587         :120000 100644 OBJID OBJID T    test-file
588         OBJID
589         :100755 120000 OBJID OBJID T    test-file
590         OBJID
591         :000000 100755 OBJID OBJID A    test-file
592         EOF
593         cat >deleteprop.dump <<-\EOF &&
594         SVN-fs-dump-format-version: 3
595
596         Revision-number: 1
597         Prop-content-length: 10
598         Content-length: 10
599
600         PROPS-END
601
602         Node-path: test-file
603         Node-kind: file
604         Node-action: add
605         Prop-delta: true
606         Prop-content-length: 35
607         Text-content-length: 17
608         Content-length: 52
609
610         K 14
611         svn:executable
612         V 0
613
614         PROPS-END
615         link testing 123
616
617         Revision-number: 2
618         Prop-content-length: 10
619         Content-length: 10
620
621         PROPS-END
622
623         Node-path: test-file
624         Node-kind: file
625         Node-action: change
626         Prop-delta: true
627         Prop-content-length: 53
628         Text-content-length: 17
629         Content-length: 70
630
631         K 11
632         svn:special
633         V 1
634         *
635         D 14
636         svn:executable
637         PROPS-END
638         link testing 231
639
640         Revision-number: 3
641         Prop-content-length: 10
642         Content-length: 10
643
644         PROPS-END
645
646         Node-path: test-file
647         Node-kind: file
648         Node-action: change
649         Prop-delta: true
650         Prop-content-length: 27
651         Text-content-length: 17
652         Content-length: 44
653
654         D 11
655         svn:special
656         PROPS-END
657         link testing 321
658         EOF
659         test-svn-fe deleteprop.dump >stream &&
660         git fast-import <stream &&
661         {
662                 git rev-list HEAD |
663                 git diff-tree --root --stdin |
664                 sed "s/$_x40/OBJID/g"
665         } >actual &&
666         test_cmp expect actual
667 '
668
669 test_expect_success 't9135/svn.dump' '
670         svnadmin create simple-svn &&
671         svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" &&
672         svn_cmd export "file://$PWD/simple-svn" simple-svnco &&
673         git init simple-git &&
674         test-svn-fe "$TEST_DIRECTORY/t9135/svn.dump" >simple.fe &&
675         (
676                 cd simple-git &&
677                 git fast-import <../simple.fe
678         ) &&
679         (
680                 cd simple-svnco &&
681                 git init &&
682                 git add . &&
683                 git fetch ../simple-git master &&
684                 git diff --exit-code FETCH_HEAD
685         )
686 '
687
688 test_done