vcs-svn: Allow simple v3 dumps (no deltas yet)
Since the dumpfile version 1 days, the Subversion dump format gained some new fields: - a unique identifier for the repository (version 2 format) - whether the text and properties for a node should be interpreted as deltas - checksums for a delta's preimage - SHA-1 sums as alternatives to the existing MD5 checksums for copy source and the payload (delta). For now what is relevant to us is the Text-delta and Prop-delta fields, since not noticing these causes a dump file to be misinterpreted (see the previous commit). [jn: 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 17, 2010 at 23:03 UTC
1f05d07c456e23c0827efbbb3e738afc9f3152e7
2 files changed
+365
-6
t/t9010-svn-fe.sh
+347
-3
@@ -9,6 +9,30 @@ reinit_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' '
@@ -18,13 +42,333 @@ test_expect_success 'empty dump' '
42
git fast-import <stream
43
'
44
21
-test_expect_success 'v3 dumps not supported' '
45
+test_expect_success 'v4 dumps not supported' '
46
reinit_git &&
23
- echo "SVN-fs-dump-format-version: 3" >input &&
24
- test_must_fail test-svn-fe input >stream &&
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 'deltas not supported' '
256
+ {
257
+ # (old) h + (inline) ello + (old) \n
258
+ printf "SVNQ%b%b%s" "Q\003\006\005\004" "\001Q\0204\001\002" "ello" |
259
+ q_to_nul
260
+ } >delta &&
261
+ {
262
+ properties \
263
+ svn:author author@example.com \
264
+ svn:date "1999-01-05T00:01:002.000000Z" \
265
+ svn:log "add greeting" &&
266
+ echo PROPS-END
267
+ } >props &&
268
+ {
269
+ properties \
270
+ svn:author author@example.com \
271
+ svn:date "1999-01-06T00:01:002.000000Z" \
272
+ svn:log "change it" &&
273
+ echo PROPS-END
274
+ } >props2 &&
275
+ {
276
+ echo SVN-fs-dump-format-version: 3 &&
277
+ echo &&
278
+ echo Revision-number: 1 &&
279
+ echo Prop-content-length: $(wc -c <props) &&
280
+ echo Content-length: $(wc -c <props) &&
281
+ echo &&
282
+ cat props &&
283
+ cat <<-\EOF &&
284
+
285
+ Node-path: hello
286
+ Node-kind: file
287
+ Node-action: add
288
+ Prop-content-length: 10
289
+ Text-content-length: 3
290
+ Content-length: 13
291
+
292
+ PROPS-END
293
+ hi
294
+
295
+ EOF
296
+ echo Revision-number: 2 &&
297
+ echo Prop-content-length: $(wc -c <props2) &&
298
+ echo Content-length: $(wc -c <props2) &&
299
+ echo &&
300
+ cat props2 &&
301
+ cat <<-\EOF &&
302
+
303
+ Node-path: hello
304
+ Node-kind: file
305
+ Node-action: change
306
+ Text-delta: true
307
+ Prop-content-length: 10
308
+ EOF
309
+ echo Text-content-length: $(wc -c <delta) &&
310
+ echo Content-length: $((10 + $(wc -c <delta))) &&
311
+ echo &&
312
+ echo PROPS-END &&
313
+ cat delta
314
+ } >delta.dump &&
315
+ test_must_fail test-svn-fe delta.dump
316
+'
317
+
318
+test_expect_success 'property deltas not supported' '
319
+ {
320
+ properties \
321
+ svn:author author@example.com \
322
+ svn:date "1999-03-06T00:01:002.000000Z" \
323
+ svn:log "make an executable, or chmod -x it" &&
324
+ echo PROPS-END
325
+ } >revprops &&
326
+ {
327
+ echo SVN-fs-dump-format-version: 3 &&
328
+ echo &&
329
+ echo Revision-number: 1 &&
330
+ echo Prop-content-length: $(wc -c <revprops) &&
331
+ echo Content-length: $(wc -c <revprops) &&
332
+ echo &&
333
+ cat revprops &&
334
+ echo &&
335
+ cat <<-\EOF &&
336
+ Node-path: script.sh
337
+ Node-kind: file
338
+ Node-action: add
339
+ Text-content-length: 0
340
+ Prop-content-length: 39
341
+ Content-length: 39
342
+
343
+ K 14
344
+ svn:executable
345
+ V 4
346
+ true
347
+ PROPS-END
348
+
349
+ EOF
350
+ echo Revision-number: 2 &&
351
+ echo Prop-content-length: $(wc -c <revprops) &&
352
+ echo Content-length: $(wc -c <revprops) &&
353
+ echo &&
354
+ cat revprops &&
355
+ echo &&
356
+ cat <<-\EOF
357
+ Node-path: script.sh
358
+ Node-kind: file
359
+ Node-action: change
360
+ Prop-delta: true
361
+ Prop-content-length: 30
362
+ Content-length: 30
363
+
364
+ D 14
365
+ svn:executable
366
+ PROPS-END
367
+ EOF
368
+ } >propdelta.dump &&
369
+ test_must_fail test-svn-fe propdelta.dump
370
+'
371
+
372
test_expect_success 't9135/svn.dump' '
373
svnadmin create simple-svn &&
374
svnadmin load simple-svn <"$TEST_DIRECTORY/t9135/svn.dump" &&
vcs-svn/svndump.c
+18
-3
@@ -42,6 +42,7 @@ static char* log_copy(uint32_t length, char *log)
42
static struct {
43
uint32_t action, propLength, textLength, srcRev, srcMode, mark, type;
44
uint32_t src[REPO_MAX_PATH_DEPTH], dst[REPO_MAX_PATH_DEPTH];
45
+ uint32_t text_delta, prop_delta;
46
} node_ctx;
47
48
static struct {
@@ -58,7 +59,9 @@ static struct {
59
uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
60
revision_number, node_path, node_kind, node_action,
61
node_copyfrom_path, node_copyfrom_rev, text_content_length,
61
- prop_content_length, content_length, svn_fs_dump_format_version;
62
+ prop_content_length, content_length, svn_fs_dump_format_version,
63
+ /* version 3 format */
64
+ text_delta, prop_delta;
65
} keys;
66
67
static void reset_node_ctx(char *fname)
@@ -72,6 +75,8 @@ static void reset_node_ctx(char *fname)
75
node_ctx.srcMode = 0;
76
pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.dst, "/", fname);
77
node_ctx.mark = 0;
78
+ node_ctx.text_delta = 0;
79
+ node_ctx.prop_delta = 0;
80
}
81
82
static void reset_rev_ctx(uint32_t revision)
@@ -107,6 +112,9 @@ static void init_keys(void)
112
keys.prop_content_length = pool_intern("Prop-content-length");
113
keys.content_length = pool_intern("Content-length");
114
keys.svn_fs_dump_format_version = pool_intern("SVN-fs-dump-format-version");
115
+ /* version 3 format (Subversion 1.1.0) */
116
+ keys.text_delta = pool_intern("Text-delta");
117
+ keys.prop_delta = pool_intern("Prop-delta");
118
}
119
120
static void read_props(void)
@@ -144,6 +152,9 @@ static void read_props(void)
152
153
static void handle_node(void)
154
{
155
+ if (node_ctx.text_delta || node_ctx.prop_delta)
156
+ die("text and property deltas not supported");
157
+
158
if (node_ctx.propLength != LENGTH_UNKNOWN && node_ctx.propLength)
159
read_props();
160
@@ -210,8 +221,8 @@ void svndump_read(const char *url)
221
222
if (key == keys.svn_fs_dump_format_version) {
223
dump_ctx.version = atoi(val);
213
- if (dump_ctx.version > 2)
214
- die("expected svn dump format version <= 2, found %d",
224
+ if (dump_ctx.version > 3)
225
+ die("expected svn dump format version <= 3, found %d",
226
dump_ctx.version);
227
} else if (key == keys.uuid) {
228
dump_ctx.uuid = pool_intern(val);
@@ -255,6 +266,10 @@ void svndump_read(const char *url)
266
node_ctx.textLength = atoi(val);
267
} else if (key == keys.prop_content_length) {
268
node_ctx.propLength = atoi(val);
269
+ } else if (key == keys.text_delta) {
270
+ node_ctx.text_delta = !strcmp(val, "true");
271
+ } else if (key == keys.prop_delta) {
272
+ node_ctx.prop_delta = !strcmp(val, "true");
273
} else if (key == keys.content_length) {
274
len = atoi(val);
275
buffer_read_line();