@matheusbsbs / matheus-bagliano / commits / 6b01b67658
Fork 0

vcs-svn: Implement Prop-delta handling

The rules for what file is used as delta source for each file are not documented in dump-load-format.txt. Luckily, the Apache Software Foundation repository has rich enough examples to figure out most of the rules: Node-action: replace implies the empty property set and empty text as preimage for deltas. Otherwise, if a copyfrom source is given, that node is the preimage for deltas. Lastly, if none of the above applies and the node path exists in the current revision, then that version forms the basis. [jn: refactored, with tests] Signed-off-by: David Barr <david.barr@cordelta.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Barr committed Nov 19, 2010 at 18:57 UTC 6b01b67658e2905b550739f1aee56a00911ca13c
2 files changed +144 -12
t/t9010-svn-fe.sh
+100 -2
@@ -514,7 +514,12 @@ test_expect_success 'deltas not supported' '
514 test_must_fail test-svn-fe delta.dump
515 '
516
517 -test_expect_success 'property deltas not supported' '
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 \
@@ -565,7 +570,100 @@ test_expect_success 'property deltas not supported' '
570 PROPS-END
571 EOF
572 } >propdelta.dump &&
568 - test_must_fail test-svn-fe 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' '
vcs-svn/svndump.c
+44 -10
@@ -115,20 +115,35 @@ static void init_keys(void)
115 keys.prop_delta = pool_intern("Prop-delta");
116 }
117
118 -static void handle_property(uint32_t key, const char *val, uint32_t len)
118 +static void handle_property(uint32_t key, const char *val, uint32_t len,
119 + uint32_t *type_set)
120 {
121 if (key == keys.svn_log) {
122 + if (!val)
123 + die("invalid dump: unsets svn:log");
124 /* Value length excludes terminating nul. */
125 rev_ctx.log = log_copy(len + 1, val);
126 } else if (key == keys.svn_author) {
127 rev_ctx.author = pool_intern(val);
128 } else if (key == keys.svn_date) {
129 + if (!val)
130 + die("invalid dump: unsets svn:date");
131 if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
127 - fprintf(stderr, "Invalid timestamp: %s\n", val);
128 - } else if (key == keys.svn_executable) {
129 - node_ctx.type = REPO_MODE_EXE;
130 - } else if (key == keys.svn_special) {
131 - node_ctx.type = REPO_MODE_LNK;
132 + warning("invalid timestamp: %s", val);
133 + } else if (key == keys.svn_executable || key == keys.svn_special) {
134 + if (*type_set) {
135 + if (!val)
136 + return;
137 + die("invalid dump: sets type twice");
138 + }
139 + if (!val) {
140 + node_ctx.type = REPO_MODE_BLB;
141 + return;
142 + }
143 + *type_set = 1;
144 + node_ctx.type = key == keys.svn_executable ?
145 + REPO_MODE_EXE :
146 + REPO_MODE_LNK;
147 }
148 }
149
@@ -136,6 +151,19 @@ static void read_props(void)
151 {
152 uint32_t key = ~0;
153 const char *t;
154 + /*
155 + * NEEDSWORK: to support simple mode changes like
156 + * K 11
157 + * svn:special
158 + * V 1
159 + * *
160 + * D 14
161 + * svn:executable
162 + * we keep track of whether a mode has been set and reset to
163 + * plain file only if not. We should be keeping track of the
164 + * symlink and executable bits separately instead.
165 + */
166 + uint32_t type_set = 0;
167 while ((t = buffer_read_line()) && strcmp(t, "PROPS-END")) {
168 uint32_t len;
169 const char *val;
@@ -151,8 +179,13 @@ static void read_props(void)
179 case 'K':
180 key = pool_intern(val);
181 continue;
182 + case 'D':
183 + key = pool_intern(val);
184 + val = NULL;
185 + len = 0;
186 + /* fall through */
187 case 'V':
155 - handle_property(key, val, len);
188 + handle_property(key, val, len, &type_set);
189 key = ~0;
190 continue;
191 default:
@@ -167,8 +200,8 @@ static void handle_node(void)
200 const uint32_t type = node_ctx.type;
201 const int have_props = node_ctx.propLength != LENGTH_UNKNOWN;
202
170 - if (node_ctx.text_delta || node_ctx.prop_delta)
171 - die("text and property deltas not supported");
203 + if (node_ctx.text_delta)
204 + die("text deltas not supported");
205 if (node_ctx.textLength != LENGTH_UNKNOWN)
206 mark = next_blob_mark();
207 if (node_ctx.action == NODEACT_DELETE) {
@@ -206,7 +239,8 @@ static void handle_node(void)
239 }
240 if (have_props) {
241 const uint32_t old_mode = node_ctx.type;
209 - node_ctx.type = type;
242 + if (!node_ctx.prop_delta)
243 + node_ctx.type = type;
244 if (node_ctx.propLength)
245 read_props();
246 if (node_ctx.type != old_mode)