]>
Commit | Line | Data |
---|---|---|
21746aa3 DB |
1 | /* |
2 | * Parse and rearrange a svnadmin dump. | |
3 | * Create the dump with: | |
4 | * svnadmin dump --incremental -r<startrev>:<endrev> <repository> >outfile | |
5 | * | |
6 | * Licensed under a two-clause BSD-style license. | |
7 | * See LICENSE for details. | |
8 | */ | |
9 | ||
10 | #include "cache.h" | |
21746aa3 DB |
11 | #include "fast_export.h" |
12 | #include "line_buffer.h" | |
dce33c9c | 13 | #include "strbuf.h" |
c5147722 | 14 | #include "svndump.h" |
21746aa3 | 15 | |
044ad290 DB |
16 | /* |
17 | * Compare start of string to literal of equal length; | |
18 | * must be guarded by length test. | |
19 | */ | |
20 | #define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1) | |
21 | ||
41529bbc DB |
22 | #define REPORT_FILENO 3 |
23 | ||
21746aa3 DB |
24 | #define NODEACT_REPLACE 4 |
25 | #define NODEACT_DELETE 3 | |
26 | #define NODEACT_ADD 2 | |
27 | #define NODEACT_CHANGE 1 | |
28 | #define NODEACT_UNKNOWN 0 | |
29 | ||
7e11902c JN |
30 | /* States: */ |
31 | #define DUMP_CTX 0 /* dump metadata */ | |
32 | #define REV_CTX 1 /* revision metadata */ | |
33 | #define NODE_CTX 2 /* node metadata */ | |
34 | #define INTERNODE_CTX 3 /* between nodes */ | |
21746aa3 | 35 | |
21746aa3 DB |
36 | #define DATE_RFC2822_LEN 31 |
37 | ||
e5e45ca1 JN |
38 | static struct line_buffer input = LINE_BUFFER_INIT; |
39 | ||
21746aa3 | 40 | static struct { |
e32b79cb JN |
41 | uint32_t action, srcRev, type; |
42 | off_t prop_length, text_length; | |
03087971 | 43 | struct strbuf src, dst; |
1f05d07c | 44 | uint32_t text_delta, prop_delta; |
21746aa3 DB |
45 | } node_ctx; |
46 | ||
47 | static struct { | |
7c5817d3 | 48 | uint32_t revision; |
dddbad72 | 49 | timestamp_t timestamp; |
a9a55613 | 50 | struct strbuf log, author, note; |
21746aa3 DB |
51 | } rev_ctx; |
52 | ||
53 | static struct { | |
7c5817d3 DB |
54 | uint32_t version; |
55 | struct strbuf uuid, url; | |
21746aa3 DB |
56 | } dump_ctx; |
57 | ||
21746aa3 DB |
58 | static void reset_node_ctx(char *fname) |
59 | { | |
60 | node_ctx.type = 0; | |
61 | node_ctx.action = NODEACT_UNKNOWN; | |
e32b79cb | 62 | node_ctx.prop_length = -1; |
150f7546 | 63 | node_ctx.text_length = -1; |
03087971 | 64 | strbuf_reset(&node_ctx.src); |
21746aa3 | 65 | node_ctx.srcRev = 0; |
03087971 DB |
66 | strbuf_reset(&node_ctx.dst); |
67 | if (fname) | |
68 | strbuf_addstr(&node_ctx.dst, fname); | |
1f05d07c DB |
69 | node_ctx.text_delta = 0; |
70 | node_ctx.prop_delta = 0; | |
21746aa3 DB |
71 | } |
72 | ||
73 | static void reset_rev_ctx(uint32_t revision) | |
74 | { | |
75 | rev_ctx.revision = revision; | |
76 | rev_ctx.timestamp = 0; | |
dce33c9c | 77 | strbuf_reset(&rev_ctx.log); |
7c5817d3 | 78 | strbuf_reset(&rev_ctx.author); |
a9a55613 | 79 | strbuf_reset(&rev_ctx.note); |
21746aa3 DB |
80 | } |
81 | ||
7c5817d3 | 82 | static void reset_dump_ctx(const char *url) |
21746aa3 | 83 | { |
7c5817d3 DB |
84 | strbuf_reset(&dump_ctx.url); |
85 | if (url) | |
86 | strbuf_addstr(&dump_ctx.url, url); | |
b3e5bce1 | 87 | dump_ctx.version = 1; |
7c5817d3 | 88 | strbuf_reset(&dump_ctx.uuid); |
21746aa3 DB |
89 | } |
90 | ||
044ad290 | 91 | static void handle_property(const struct strbuf *key_buf, |
4c3169b0 | 92 | struct strbuf *val, |
6b01b676 | 93 | uint32_t *type_set) |
2a48afe1 | 94 | { |
044ad290 DB |
95 | const char *key = key_buf->buf; |
96 | size_t keylen = key_buf->len; | |
97 | ||
98 | switch (keylen + 1) { | |
99 | case sizeof("svn:log"): | |
100 | if (constcmp(key, "svn:log")) | |
101 | break; | |
6b01b676 DB |
102 | if (!val) |
103 | die("invalid dump: unsets svn:log"); | |
4c3169b0 | 104 | strbuf_swap(&rev_ctx.log, val); |
044ad290 DB |
105 | break; |
106 | case sizeof("svn:author"): | |
107 | if (constcmp(key, "svn:author")) | |
108 | break; | |
4c3169b0 JN |
109 | if (!val) |
110 | strbuf_reset(&rev_ctx.author); | |
111 | else | |
112 | strbuf_swap(&rev_ctx.author, val); | |
044ad290 DB |
113 | break; |
114 | case sizeof("svn:date"): | |
115 | if (constcmp(key, "svn:date")) | |
116 | break; | |
6b01b676 DB |
117 | if (!val) |
118 | die("invalid dump: unsets svn:date"); | |
4c3169b0 JN |
119 | if (parse_date_basic(val->buf, &rev_ctx.timestamp, NULL)) |
120 | warning("invalid timestamp: %s", val->buf); | |
044ad290 DB |
121 | break; |
122 | case sizeof("svn:executable"): | |
123 | case sizeof("svn:special"): | |
124 | if (keylen == strlen("svn:executable") && | |
125 | constcmp(key, "svn:executable")) | |
126 | break; | |
127 | if (keylen == strlen("svn:special") && | |
128 | constcmp(key, "svn:special")) | |
129 | break; | |
6b01b676 DB |
130 | if (*type_set) { |
131 | if (!val) | |
132 | return; | |
133 | die("invalid dump: sets type twice"); | |
134 | } | |
135 | if (!val) { | |
21c7c2d9 | 136 | node_ctx.type = S_IFREG | 0644; |
6b01b676 DB |
137 | return; |
138 | } | |
139 | *type_set = 1; | |
044ad290 | 140 | node_ctx.type = keylen == strlen("svn:executable") ? |
21c7c2d9 JN |
141 | (S_IFREG | 0755) : |
142 | S_IFLNK; | |
2a48afe1 | 143 | } |
21746aa3 DB |
144 | } |
145 | ||
c9d1c8ba JN |
146 | static void die_short_read(void) |
147 | { | |
148 | if (buffer_ferror(&input)) | |
149 | die_errno("error reading dump file"); | |
150 | die("invalid dump: unexpected end of file"); | |
151 | } | |
152 | ||
21746aa3 DB |
153 | static void read_props(void) |
154 | { | |
044ad290 | 155 | static struct strbuf key = STRBUF_INIT; |
e7d04ee1 | 156 | static struct strbuf val = STRBUF_INIT; |
6263c06d | 157 | const char *t; |
6b01b676 DB |
158 | /* |
159 | * NEEDSWORK: to support simple mode changes like | |
160 | * K 11 | |
161 | * svn:special | |
162 | * V 1 | |
163 | * * | |
164 | * D 14 | |
165 | * svn:executable | |
166 | * we keep track of whether a mode has been set and reset to | |
167 | * plain file only if not. We should be keeping track of the | |
168 | * symlink and executable bits separately instead. | |
169 | */ | |
170 | uint32_t type_set = 0; | |
e5e45ca1 | 171 | while ((t = buffer_read_line(&input)) && strcmp(t, "PROPS-END")) { |
6263c06d | 172 | uint32_t len; |
6263c06d | 173 | const char type = t[0]; |
c9d1c8ba | 174 | int ch; |
6263c06d JN |
175 | |
176 | if (!type || t[1] != ' ') | |
82247e9b | 177 | die("invalid property line: %s", t); |
6263c06d | 178 | len = atoi(&t[2]); |
e7d04ee1 JN |
179 | strbuf_reset(&val); |
180 | buffer_read_binary(&input, &val, len); | |
181 | if (val.len < len) | |
c9d1c8ba JN |
182 | die_short_read(); |
183 | ||
184 | /* Discard trailing newline. */ | |
185 | ch = buffer_read_char(&input); | |
186 | if (ch == EOF) | |
187 | die_short_read(); | |
188 | if (ch != '\n') | |
e7d04ee1 | 189 | die("invalid dump: expected newline after %s", val.buf); |
6263c06d JN |
190 | |
191 | switch (type) { | |
192 | case 'K': | |
e7d04ee1 JN |
193 | strbuf_swap(&key, &val); |
194 | continue; | |
6b01b676 | 195 | case 'D': |
4c3169b0 | 196 | handle_property(&val, NULL, &type_set); |
e7d04ee1 | 197 | continue; |
6263c06d | 198 | case 'V': |
4c3169b0 | 199 | handle_property(&key, &val, &type_set); |
044ad290 | 200 | strbuf_reset(&key); |
6263c06d JN |
201 | continue; |
202 | default: | |
82247e9b | 203 | die("invalid property line: %s", t); |
21746aa3 DB |
204 | } |
205 | } | |
206 | } | |
207 | ||
208 | static void handle_node(void) | |
209 | { | |
1c7bb316 | 210 | const uint32_t type = node_ctx.type; |
e32b79cb | 211 | const int have_props = node_ctx.prop_length != -1; |
150f7546 | 212 | const int have_text = node_ctx.text_length != -1; |
723b7a27 JN |
213 | /* |
214 | * Old text for this node: | |
215 | * NULL - directory or bug | |
216 | * empty_blob - empty | |
217 | * "<dataref>" - data retrievable from fast-import | |
218 | */ | |
219 | static const char *const empty_blob = "::empty::"; | |
220 | const char *old_data = NULL; | |
21c7c2d9 | 221 | uint32_t old_mode = S_IFREG | 0644; |
21746aa3 DB |
222 | |
223 | if (node_ctx.action == NODEACT_DELETE) { | |
5a38b186 | 224 | if (have_text || have_props || node_ctx.srcRev) |
5af8fae2 JN |
225 | die("invalid dump: deletion node has " |
226 | "copyfrom info, text, or properties"); | |
9b0db335 | 227 | fast_export_delete(node_ctx.dst.buf); |
9e113988 | 228 | return; |
5af8fae2 | 229 | } |
6ee4a9be | 230 | if (node_ctx.action == NODEACT_REPLACE) { |
9b0db335 | 231 | fast_export_delete(node_ctx.dst.buf); |
6ee4a9be JN |
232 | node_ctx.action = NODEACT_ADD; |
233 | } | |
1c7bb316 | 234 | if (node_ctx.srcRev) { |
b8f43b12 | 235 | fast_export_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf); |
414e569e JN |
236 | if (node_ctx.action == NODEACT_ADD) |
237 | node_ctx.action = NODEACT_CHANGE; | |
1c7bb316 | 238 | } |
21c7c2d9 | 239 | if (have_text && type == S_IFDIR) |
462e1f51 | 240 | die("invalid dump: directories cannot have text attached"); |
5a38b186 JN |
241 | |
242 | /* | |
723b7a27 | 243 | * Find old content (old_data) and decide on the new mode. |
5a38b186 | 244 | */ |
03087971 | 245 | if (node_ctx.action == NODEACT_CHANGE && !*node_ctx.dst.buf) { |
21c7c2d9 | 246 | if (type != S_IFDIR) |
9e8c5321 | 247 | die("invalid dump: root of tree is not a regular file"); |
723b7a27 | 248 | old_data = NULL; |
9e8c5321 | 249 | } else if (node_ctx.action == NODEACT_CHANGE) { |
5a38b186 | 250 | uint32_t mode; |
b8f43b12 | 251 | old_data = fast_export_read_path(node_ctx.dst.buf, &mode); |
21c7c2d9 | 252 | if (mode == S_IFDIR && type != S_IFDIR) |
c7dbf35e | 253 | die("invalid dump: cannot modify a directory into a file"); |
21c7c2d9 | 254 | if (mode != S_IFDIR && type == S_IFDIR) |
c7dbf35e JN |
255 | die("invalid dump: cannot modify a file into a directory"); |
256 | node_ctx.type = mode; | |
7a75e661 | 257 | old_mode = mode; |
21746aa3 | 258 | } else if (node_ctx.action == NODEACT_ADD) { |
21c7c2d9 | 259 | if (type == S_IFDIR) |
723b7a27 JN |
260 | old_data = NULL; |
261 | else if (have_text) | |
262 | old_data = empty_blob; | |
263 | else | |
c7dbf35e | 264 | die("invalid dump: adds node without text"); |
c7dbf35e | 265 | } else { |
414e569e | 266 | die("invalid dump: Node-path block lacks Node-action"); |
21746aa3 | 267 | } |
5a38b186 JN |
268 | |
269 | /* | |
270 | * Adjust mode to reflect properties. | |
271 | */ | |
1c7bb316 | 272 | if (have_props) { |
6b01b676 DB |
273 | if (!node_ctx.prop_delta) |
274 | node_ctx.type = type; | |
e32b79cb | 275 | if (node_ctx.prop_length) |
1c7bb316 | 276 | read_props(); |
21746aa3 | 277 | } |
5a38b186 JN |
278 | |
279 | /* | |
280 | * Save the result. | |
281 | */ | |
21c7c2d9 | 282 | if (type == S_IFDIR) /* directories are not tracked. */ |
723b7a27 JN |
283 | return; |
284 | assert(old_data); | |
285 | if (old_data == empty_blob) | |
286 | /* For the fast_export_* functions, NULL means empty. */ | |
287 | old_data = NULL; | |
288 | if (!have_text) { | |
03087971 | 289 | fast_export_modify(node_ctx.dst.buf, node_ctx.type, old_data); |
723b7a27 JN |
290 | return; |
291 | } | |
7a75e661 DB |
292 | if (!node_ctx.text_delta) { |
293 | fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline"); | |
150f7546 | 294 | fast_export_data(node_ctx.type, node_ctx.text_length, &input); |
7a75e661 DB |
295 | return; |
296 | } | |
03087971 | 297 | fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline"); |
7a75e661 | 298 | fast_export_blob_delta(node_ctx.type, old_mode, old_data, |
150f7546 | 299 | node_ctx.text_length, &input); |
21746aa3 DB |
300 | } |
301 | ||
271fd1fc | 302 | static void begin_revision(const char *remote_ref) |
7e11902c JN |
303 | { |
304 | if (!rev_ctx.revision) /* revision 0 gets no git commit. */ | |
305 | return; | |
9ecfa8ae JN |
306 | fast_export_begin_commit(rev_ctx.revision, rev_ctx.author.buf, |
307 | &rev_ctx.log, dump_ctx.uuid.buf, dump_ctx.url.buf, | |
271fd1fc | 308 | rev_ctx.timestamp, remote_ref); |
21746aa3 DB |
309 | } |
310 | ||
8e43a1d0 | 311 | static void end_revision(const char *note_ref) |
21746aa3 | 312 | { |
a9a55613 FA |
313 | struct strbuf mark = STRBUF_INIT; |
314 | if (rev_ctx.revision) { | |
723b7a27 | 315 | fast_export_end_commit(rev_ctx.revision); |
a9a55613 | 316 | fast_export_begin_note(rev_ctx.revision, "remote-svn", |
8e43a1d0 | 317 | "Note created by remote-svn.", rev_ctx.timestamp, note_ref); |
a9a55613 FA |
318 | strbuf_addf(&mark, ":%"PRIu32, rev_ctx.revision); |
319 | fast_export_note(mark.buf, "inline"); | |
320 | fast_export_buf_to_data(&rev_ctx.note); | |
9f004921 | 321 | strbuf_release(&mark); |
a9a55613 | 322 | } |
21746aa3 DB |
323 | } |
324 | ||
8e43a1d0 | 325 | void svndump_read(const char *url, const char *local_ref, const char *notes_ref) |
21746aa3 DB |
326 | { |
327 | char *val; | |
328 | char *t; | |
329 | uint32_t active_ctx = DUMP_CTX; | |
330 | uint32_t len; | |
21746aa3 | 331 | |
7c5817d3 | 332 | reset_dump_ctx(url); |
e5e45ca1 | 333 | while ((t = buffer_read_line(&input))) { |
f1602054 | 334 | val = strchr(t, ':'); |
21746aa3 DB |
335 | if (!val) |
336 | continue; | |
f1602054 DB |
337 | val++; |
338 | if (*val != ' ') | |
339 | continue; | |
340 | val++; | |
21746aa3 | 341 | |
90c0a3cf DB |
342 | /* strlen(key) + 1 */ |
343 | switch (val - t - 1) { | |
344 | case sizeof("SVN-fs-dump-format-version"): | |
345 | if (constcmp(t, "SVN-fs-dump-format-version")) | |
346 | continue; | |
b3e5bce1 | 347 | dump_ctx.version = atoi(val); |
1f05d07c | 348 | if (dump_ctx.version > 3) |
a62bbf8f | 349 | die("expected svn dump format version <= 3, found %"PRIu32, |
b3e5bce1 | 350 | dump_ctx.version); |
90c0a3cf DB |
351 | break; |
352 | case sizeof("UUID"): | |
353 | if (constcmp(t, "UUID")) | |
354 | continue; | |
7c5817d3 DB |
355 | strbuf_reset(&dump_ctx.uuid); |
356 | strbuf_addstr(&dump_ctx.uuid, val); | |
90c0a3cf DB |
357 | break; |
358 | case sizeof("Revision-number"): | |
359 | if (constcmp(t, "Revision-number")) | |
360 | continue; | |
21746aa3 DB |
361 | if (active_ctx == NODE_CTX) |
362 | handle_node(); | |
7e11902c | 363 | if (active_ctx == REV_CTX) |
271fd1fc | 364 | begin_revision(local_ref); |
21746aa3 | 365 | if (active_ctx != DUMP_CTX) |
8e43a1d0 | 366 | end_revision(notes_ref); |
21746aa3 DB |
367 | active_ctx = REV_CTX; |
368 | reset_rev_ctx(atoi(val)); | |
a9a55613 | 369 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
90c0a3cf DB |
370 | break; |
371 | case sizeof("Node-path"): | |
d8d8708b | 372 | if (constcmp(t, "Node-")) |
90c0a3cf DB |
373 | continue; |
374 | if (!constcmp(t + strlen("Node-"), "path")) { | |
375 | if (active_ctx == NODE_CTX) | |
376 | handle_node(); | |
9ecfa8ae | 377 | if (active_ctx == REV_CTX) |
271fd1fc | 378 | begin_revision(local_ref); |
90c0a3cf DB |
379 | active_ctx = NODE_CTX; |
380 | reset_node_ctx(val); | |
a9a55613 | 381 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
90c0a3cf DB |
382 | break; |
383 | } | |
384 | if (constcmp(t + strlen("Node-"), "kind")) | |
385 | continue; | |
a9a55613 | 386 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
21746aa3 | 387 | if (!strcmp(val, "dir")) |
21c7c2d9 | 388 | node_ctx.type = S_IFDIR; |
21746aa3 | 389 | else if (!strcmp(val, "file")) |
21c7c2d9 | 390 | node_ctx.type = S_IFREG | 0644; |
21746aa3 DB |
391 | else |
392 | fprintf(stderr, "Unknown node-kind: %s\n", val); | |
90c0a3cf DB |
393 | break; |
394 | case sizeof("Node-action"): | |
395 | if (constcmp(t, "Node-action")) | |
396 | continue; | |
a9a55613 | 397 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
21746aa3 DB |
398 | if (!strcmp(val, "delete")) { |
399 | node_ctx.action = NODEACT_DELETE; | |
400 | } else if (!strcmp(val, "add")) { | |
401 | node_ctx.action = NODEACT_ADD; | |
402 | } else if (!strcmp(val, "change")) { | |
403 | node_ctx.action = NODEACT_CHANGE; | |
404 | } else if (!strcmp(val, "replace")) { | |
405 | node_ctx.action = NODEACT_REPLACE; | |
406 | } else { | |
407 | fprintf(stderr, "Unknown node-action: %s\n", val); | |
408 | node_ctx.action = NODEACT_UNKNOWN; | |
409 | } | |
90c0a3cf DB |
410 | break; |
411 | case sizeof("Node-copyfrom-path"): | |
412 | if (constcmp(t, "Node-copyfrom-path")) | |
413 | continue; | |
03087971 DB |
414 | strbuf_reset(&node_ctx.src); |
415 | strbuf_addstr(&node_ctx.src, val); | |
a9a55613 | 416 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
90c0a3cf DB |
417 | break; |
418 | case sizeof("Node-copyfrom-rev"): | |
419 | if (constcmp(t, "Node-copyfrom-rev")) | |
420 | continue; | |
21746aa3 | 421 | node_ctx.srcRev = atoi(val); |
a9a55613 | 422 | strbuf_addf(&rev_ctx.note, "%s\n", t); |
90c0a3cf DB |
423 | break; |
424 | case sizeof("Text-content-length"): | |
e32b79cb JN |
425 | if (constcmp(t, "Text") && constcmp(t, "Prop")) |
426 | continue; | |
427 | if (constcmp(t + 4, "-content-length")) | |
428 | continue; | |
429 | { | |
150f7546 | 430 | char *end; |
e32b79cb | 431 | uintmax_t len; |
150f7546 | 432 | |
e32b79cb | 433 | len = strtoumax(val, &end, 10); |
150f7546 JN |
434 | if (!isdigit(*val) || *end) |
435 | die("invalid dump: non-numeric length %s", val); | |
e32b79cb | 436 | if (len > maximum_signed_value_of_type(off_t)) |
150f7546 | 437 | die("unrepresentable length in dump: %s", val); |
e32b79cb JN |
438 | |
439 | if (*t == 'T') | |
440 | node_ctx.text_length = (off_t) len; | |
441 | else | |
442 | node_ctx.prop_length = (off_t) len; | |
90c0a3cf DB |
443 | break; |
444 | } | |
90c0a3cf DB |
445 | case sizeof("Text-delta"): |
446 | if (!constcmp(t, "Text-delta")) { | |
447 | node_ctx.text_delta = !strcmp(val, "true"); | |
448 | break; | |
449 | } | |
450 | if (constcmp(t, "Prop-delta")) | |
451 | continue; | |
1f05d07c | 452 | node_ctx.prop_delta = !strcmp(val, "true"); |
90c0a3cf DB |
453 | break; |
454 | case sizeof("Content-length"): | |
455 | if (constcmp(t, "Content-length")) | |
456 | continue; | |
21746aa3 | 457 | len = atoi(val); |
c9d1c8ba JN |
458 | t = buffer_read_line(&input); |
459 | if (!t) | |
460 | die_short_read(); | |
461 | if (*t) | |
462 | die("invalid dump: expected blank line after content length header"); | |
21746aa3 DB |
463 | if (active_ctx == REV_CTX) { |
464 | read_props(); | |
465 | } else if (active_ctx == NODE_CTX) { | |
466 | handle_node(); | |
7e11902c | 467 | active_ctx = INTERNODE_CTX; |
21746aa3 | 468 | } else { |
5418d96d | 469 | fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len); |
c9d1c8ba JN |
470 | if (buffer_skip_bytes(&input, len) != len) |
471 | die_short_read(); | |
21746aa3 DB |
472 | } |
473 | } | |
474 | } | |
c9d1c8ba JN |
475 | if (buffer_ferror(&input)) |
476 | die_short_read(); | |
21746aa3 DB |
477 | if (active_ctx == NODE_CTX) |
478 | handle_node(); | |
7e11902c | 479 | if (active_ctx == REV_CTX) |
271fd1fc | 480 | begin_revision(local_ref); |
21746aa3 | 481 | if (active_ctx != DUMP_CTX) |
8e43a1d0 | 482 | end_revision(notes_ref); |
21746aa3 DB |
483 | } |
484 | ||
fd871b94 | 485 | static void init(int report_fd) |
21746aa3 | 486 | { |
fd871b94 | 487 | fast_export_init(report_fd); |
7c5817d3 DB |
488 | strbuf_init(&dump_ctx.uuid, 4096); |
489 | strbuf_init(&dump_ctx.url, 4096); | |
dce33c9c | 490 | strbuf_init(&rev_ctx.log, 4096); |
7c5817d3 | 491 | strbuf_init(&rev_ctx.author, 4096); |
a9a55613 | 492 | strbuf_init(&rev_ctx.note, 4096); |
03087971 DB |
493 | strbuf_init(&node_ctx.src, 4096); |
494 | strbuf_init(&node_ctx.dst, 4096); | |
7c5817d3 | 495 | reset_dump_ctx(NULL); |
21746aa3 DB |
496 | reset_rev_ctx(0); |
497 | reset_node_ctx(NULL); | |
fd871b94 FA |
498 | return; |
499 | } | |
500 | ||
501 | int svndump_init(const char *filename) | |
502 | { | |
503 | if (buffer_init(&input, filename)) | |
1c8ead97 | 504 | return error_errno("cannot open %s", filename ? filename : "NULL"); |
fd871b94 FA |
505 | init(REPORT_FILENO); |
506 | return 0; | |
507 | } | |
508 | ||
509 | int svndump_init_fd(int in_fd, int back_fd) | |
510 | { | |
511 | if(buffer_fdinit(&input, xdup(in_fd))) | |
1c8ead97 | 512 | return error_errno("cannot open fd %d", in_fd); |
fd871b94 | 513 | init(xdup(back_fd)); |
5c28a8b0 | 514 | return 0; |
21746aa3 DB |
515 | } |
516 | ||
517 | void svndump_deinit(void) | |
518 | { | |
41529bbc | 519 | fast_export_deinit(); |
7c5817d3 | 520 | reset_dump_ctx(NULL); |
21746aa3 DB |
521 | reset_rev_ctx(0); |
522 | reset_node_ctx(NULL); | |
dce33c9c | 523 | strbuf_release(&rev_ctx.log); |
a9a55613 FA |
524 | strbuf_release(&rev_ctx.author); |
525 | strbuf_release(&rev_ctx.note); | |
03087971 DB |
526 | strbuf_release(&node_ctx.src); |
527 | strbuf_release(&node_ctx.dst); | |
e5e45ca1 | 528 | if (buffer_deinit(&input)) |
21746aa3 DB |
529 | fprintf(stderr, "Input error\n"); |
530 | if (ferror(stdout)) | |
531 | fprintf(stderr, "Output error\n"); | |
532 | } | |
533 | ||
534 | void svndump_reset(void) | |
535 | { | |
7c5817d3 DB |
536 | strbuf_release(&dump_ctx.uuid); |
537 | strbuf_release(&dump_ctx.url); | |
538 | strbuf_release(&rev_ctx.log); | |
539 | strbuf_release(&rev_ctx.author); | |
21746aa3 | 540 | } |