1 /******************************************************************************
3 * Copyright (C) 2005 Stefan Hegny, hydrografix Consulting GmbH,
4 * Frankfurt/Main, Germany
5 * and others, see http://svn2cc.sarovar.org
7 * Copyright (C) 2010 David Barr <david.barr@cordelta.com>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice(s), this list of conditions and the following disclaimer
15 * unmodified other than the allowable addition of one or more
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice(s), this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
23 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 ******************************************************************************/
37 * Parse and rearrange a svnadmin dump.
38 * Create the dump with:
39 * svnadmin dump --incremental -r<startrev>:<endrev> <repository> >outfile
47 #include "repo_tree.h"
50 * node was moved to somwhere else
51 * (this is not contained in the dump)
52 * (only used in the FileChangeSet)
54 #define NODEACT_REMOVE 5
57 * node was moved from somwhere else
58 * (this is not contained in the dump)
59 * (only used in the FileChangeSet)
61 #define NODEACT_MOVE 4
64 * not clear if moved (if deleted afterwards) or
65 * added as copy (which can not be modeled straight in ccase).
66 * Will be used on create of SvnNodeEntry iff
67 * action is add and source is given.
68 * Will be modified after importing all files
69 * of a revision to NODEACT_ADD (copy which can
70 * not be modeled in ccase) or NODEACT_MOVE
72 #define NODEACT_COPY_OR_MOVE 3
77 #define NODEACT_DELETE 2
80 * Node was added or copied from other location
87 #define NODEACT_CHANGE 0
92 #define NODEACT_UNKNOWN -1
97 #define NODEKIND_DIR 1
102 #define NODEKIND_FILE 0
105 * unknown type of node
107 #define NODEKIND_UNKNOWN -1
109 static char line_buffer
[10000];
110 static int line_buffer_len
= 0;
111 static int line_len
= 0;
114 * read string up to newline from input stream
115 * return all characters except the newline
117 static char *svndump_read_line(void)
124 memmove(line_buffer
, &line_buffer
[line_len
],
125 line_buffer_len
- line_len
);
126 line_buffer_len
-= line_len
;
130 end
= memchr(line_buffer
, '\n', line_buffer_len
);
131 while (line_buffer_len
< 9999 && !feof(stdin
) && NULL
== end
) {
133 fread(&line_buffer
[line_buffer_len
], 1, 9999 - line_buffer_len
,
135 end
= memchr(&line_buffer
[line_buffer_len
], '\n', n_read
);
136 line_buffer_len
+= n_read
;
143 line_len
= end
- line_buffer
;
144 line_buffer
[line_len
++] = '\0';
146 line_len
= line_buffer_len
;
147 line_buffer
[line_buffer_len
] = '\0';
157 * so a line can be pushed-back after read
159 static void svndump_pushBackInputLine()
162 if (line_buffer
[line_len
- 1] == '\0')
163 line_buffer
[line_len
- 1] = '\n';
164 line_buffer
[line_buffer_len
] = '\0';
169 static char *svndump_read_string(int len
)
171 char *s
= malloc(len
+ 1);
173 if (line_buffer_len
> line_len
) {
174 offset
= line_buffer_len
- line_len
;
177 memcpy(s
, &line_buffer
[line_len
], offset
);
180 while (offset
< len
&& !feof(stdin
)) {
181 offset
+= fread(&s
[offset
], 1, len
- offset
, stdin
);
187 char byte_buffer
[4096];
188 static void copy_bytes(int len
)
191 if (line_buffer_len
> line_len
) {
192 in
= line_buffer_len
- line_len
;
196 while (out
< in
&& !ferror(stdout
)) {
198 fwrite(&line_buffer
[line_len
+ out
], 1, in
- out
, stdout
);
203 while (len
> 0 && !feof(stdin
)) {
204 in
= len
< 4096 ? len
: 4096;
205 in
= fread(byte_buffer
, 1, in
, stdin
);
208 while (out
< in
&& !ferror(stdout
)) {
209 out
+= fwrite(&byte_buffer
[out
], 1, in
- out
, stdout
);
214 static void skip_bytes(int len
)
217 if (line_buffer_len
> line_len
) {
218 in
= line_buffer_len
- line_len
;
224 while (len
> 0 && !feof(stdin
)) {
225 in
= len
< 4096 ? len
: 4096;
226 in
= fread(byte_buffer
, 1, in
, stdin
);
231 static int strendswith(char *s
, char *end
)
233 int end_len
= strlen(end
);
234 int s_len
= strlen(s
);
235 return s_len
>= end_len
&& !strcmp(&s
[s_len
- end_len
], end
);
238 static uint32_t next_blob_mark(void)
240 static int32_t mark
= 1000000000;
245 * read a modified file (node) within a revision
247 static void svnnode_read(char *fname
)
249 int type
= NODEKIND_UNKNOWN
;
250 int action
= NODEACT_UNKNOWN
;
255 char *dst
= strdup(fname
);
260 fprintf(stderr
, "Node path: %s\n", fname
);
262 for (t
= svndump_read_line();
264 t
= svndump_read_line()) {
265 if (!strncmp(t
, "Node-kind:", 10)) {
267 if (!strncasecmp(val
, "dir", 3))
270 else if (!strncasecmp(val
, "file", 4))
271 type
= NODEKIND_FILE
;
274 type
= NODEKIND_UNKNOWN
;
275 } else if (!strncmp(t
, "Node-action", 11)) {
277 if (!strncasecmp(val
, "delete", 6))
278 action
= NODEACT_DELETE
;
280 else if (!strncasecmp(val
, "add", 3))
281 action
= NODEACT_ADD
;
283 else if (!strncasecmp(val
, "change", 6))
284 action
= NODEACT_CHANGE
;
287 action
= NODEACT_UNKNOWN
;
288 } else if (!strncmp(t
, "Node-copyfrom-path", 18)) {
289 src
= strdup(&t
[20]);
290 fprintf(stderr
, "Node copy path: %s\n", src
);
291 } else if (!strncmp(t
, "Node-copyfrom-rev", 17)) {
294 fprintf(stderr
, "Node copy revision: %d\n", srcRev
);
295 } else if (!strncmp(t
, "Text-content-length:", 20)) {
297 textLength
= atoi(val
);
298 fprintf(stderr
, "Text content length: %d\n", textLength
);
299 } else if (!strncmp(t
, "Prop-content-length:", 20)) {
301 propLength
= atoi(val
);
302 fprintf(stderr
, "Prop content length: %d\n", propLength
);
307 skip_bytes(propLength
);
310 mark
= next_blob_mark();
311 printf("blob\nmark :%d\ndata %d\n", mark
, textLength
);
312 copy_bytes(textLength
);
316 if (action
== NODEACT_DELETE
) {
318 } else if (action
== NODEACT_CHANGE
) {
320 repo_modify(dst
, mark
);
321 } else if (src
&& srcRev
) {
322 repo_copy(srcRev
, src
, dst
);
324 } else if (action
== NODEACT_ADD
) {
327 type
== NODEKIND_DIR
? REPO_MODE_DIR
: REPO_MODE_BLB
,
330 repo_copy(srcRev
, src
, dst
);
336 * create revision reading from stdin
337 * param number revision number
339 static void svnrev_read(uint32_t number
)
344 char *author
= "nobody";
351 fprintf(stderr
, "Revision: %d\n", number
);
353 for (t
= svndump_read_line();
354 t
&& strncasecmp(t
, "PROPS-END", 9);
355 t
= svndump_read_line()) {
356 if (!strncmp(t
, "K ", 2)) {
358 key
= svndump_read_string(len
);
360 } else if (!strncmp(t
, "V ", 2)) {
362 val
= svndump_read_string(len
);
363 if (strendswith(key
, ":log")) {
365 fprintf(stderr
, "Log: %s\n", descr
);
366 } else if (strendswith(key
, ":author")) {
368 fprintf(stderr
, "Author: %s\n", author
);
369 } else if (strendswith(key
, ":date")) {
371 fprintf(stderr
, "Date: %s\n", date
);
372 strptime(date
, "%FT%T", &tm
);
373 timestamp
= mktime(&tm
);
381 t
&& strncmp(t
, "Revision-number:", 16);
382 t
= svndump_read_line()) {
383 if (!strncmp(t
, "Node-path:", 10)) {
384 svnnode_read(&t
[11]);
388 svndump_pushBackInputLine();
395 printf("commit refs/heads/master\nmark :%d\n", number
);
396 printf("committer %s <%s@local> %d +0000\n",
397 author
, author
, time(×tamp
));
398 printf("data %d\n%s\n", strlen(descr
), descr
);
399 repo_diff(number
- 1, number
);
402 printf("progress Imported commit %d.\n\n", number
);
406 * create dump representation by importing dump file
408 static void svndump_read(void)
411 for (t
= svndump_read_line(); t
; t
= svndump_read_line()) {
412 if (!strncmp(t
, "Revision-number:", 16)) {
413 svnrev_read(atoi(&t
[17]));
418 int main(int argc
, char **argv
)