Separate line buffering into its own module.
[svn-fe.git] / svndump.c
blob3490b878cd4692681500880275cd589247f55c14
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>.
8 * All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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
16 * copyright notices.
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
20 * distribution.
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
42 #include <stdint.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <time.h>
48 #include "repo_tree.h"
49 #include "line_buffer.h"
51 /**
52 * node was replaced
54 #define NODEACT_REPLACE 3
56 /**
57 * node was deleted
59 #define NODEACT_DELETE 2
61 /**
62 * node was added or copied from other location
64 #define NODEACT_ADD 1
66 /**
67 * node was modified
69 #define NODEACT_CHANGE 0
71 /**
72 * unknown action
74 #define NODEACT_UNKNOWN -1
76 static uint32_t next_blob_mark(void)
78 static int32_t mark = 1000000000;
79 return mark++;
82 /**
83 * read a modified file (node) within a revision
85 static void svnnode_read(char *fname)
87 int type = 0;
88 int action = NODEACT_UNKNOWN;
89 int propLength = -1;
90 int textLength = -1;
91 char *src = NULL;
92 int srcRev = 0;
93 uint32_t srcMode;
94 char *dst = strdup(fname);
95 char *t;
96 int len;
97 char *key;
98 char *val;
99 uint32_t mark = 0;
101 fprintf(stderr, "Node path: %s\n", fname);
103 for (t = buffer_read_line();
104 t && *t;
105 t = buffer_read_line()) {
106 if (!strncmp(t, "Node-kind:", 10)) {
107 val = &t[11];
108 if (!strncasecmp(val, "dir", 3)) {
109 type = REPO_MODE_DIR;
110 } else if (!strncasecmp(val, "file", 4)) {
111 type = REPO_MODE_BLB;
112 } else {
113 fprintf(stderr, "Unknown node-kind: %s\n", val);
115 } else if (!strncmp(t, "Node-action", 11)) {
116 val = &t[13];
117 if (!strncasecmp(val, "delete", 6))
118 action = NODEACT_DELETE;
120 else if (!strncasecmp(val, "add", 3))
121 action = NODEACT_ADD;
123 else if (!strncasecmp(val, "change", 6))
124 action = NODEACT_CHANGE;
126 else if (!strncasecmp(val, "replace", 6))
127 action = NODEACT_REPLACE;
129 else
130 action = NODEACT_UNKNOWN;
131 } else if (!strncmp(t, "Node-copyfrom-path", 18)) {
132 src = strdup(&t[20]);
133 fprintf(stderr, "Node copy path: %s\n", src);
134 } else if (!strncmp(t, "Node-copyfrom-rev", 17)) {
135 val = &t[19];
136 srcRev = atoi(val);
137 fprintf(stderr, "Node copy revision: %d\n", srcRev);
138 } else if (!strncmp(t, "Text-content-length:", 20)) {
139 val = &t[21];
140 textLength = atoi(val);
141 fprintf(stderr, "Text content length: %d\n", textLength);
142 } else if (!strncmp(t, "Prop-content-length:", 20)) {
143 val = &t[21];
144 propLength = atoi(val);
145 fprintf(stderr, "Prop content length: %d\n", propLength);
149 if (propLength > 0) {
150 for (t = buffer_read_line();
151 t && strncasecmp(t, "PROPS-END", 9);
152 t = buffer_read_line()) {
153 if (!strncmp(t, "K ", 2)) {
154 len = atoi(&t[2]);
155 key = buffer_read_string(len);
156 buffer_read_line();
157 } else if (!strncmp(t, "V ", 2)) {
158 len = atoi(&t[2]);
159 val = buffer_read_string(len);
160 if (!strcmp(key, "svn:executable")) {
161 if (type == REPO_MODE_BLB) {
162 type = REPO_MODE_EXE;
164 fprintf(stderr, "Executable: %s\n", val);
165 } else if (!strcmp(key, "svn:special")) {
166 if (type == REPO_MODE_BLB) {
167 type = REPO_MODE_LNK;
169 fprintf(stderr, "Special: %s\n", val);
171 key = "";
172 buffer_read_line();
177 if (src && srcRev) {
178 srcMode = repo_copy(srcRev, src, dst);
181 if (textLength >= 0 && type != REPO_MODE_DIR) {
182 mark = next_blob_mark();
185 if (action == NODEACT_DELETE) {
186 repo_delete(dst);
187 } else if (action == NODEACT_CHANGE ||
188 action == NODEACT_REPLACE) {
189 if (propLength >= 0 && textLength >= 0) {
190 repo_modify(dst, type, mark);
191 } else if (textLength >= 0) {
192 srcMode = repo_replace(dst, mark);
194 } else if (action == NODEACT_ADD) {
195 if (src && srcRev && propLength < 0 && textLength >= 0) {
196 srcMode = repo_replace(dst, mark);
197 } else if(type == REPO_MODE_DIR || textLength >= 0){
198 repo_add(dst, type, mark);
202 if (propLength < 0 && srcMode) {
203 type = srcMode;
206 if(textLength == -1) textLength = 0;
208 if (mark) {
209 if (type == REPO_MODE_LNK) {
210 /* svn symlink blobs start with "link " */
211 buffer_skip_bytes(5);
212 textLength -= 5;
214 printf("blob\nmark :%d\ndata %d\n", mark, textLength);
215 buffer_copy_bytes(textLength);
216 fputc('\n', stdout);
217 } else {
218 buffer_skip_bytes(textLength);
222 static char *uuid = NULL;
223 static char *url = NULL;
227 * create revision reading from stdin
228 * param number revision number
230 static void svnrev_read(uint32_t number)
232 struct tm tm;
233 time_t timestamp = 0;
234 char *descr = "";
235 char *author = "nobody";
236 char *date = "now";
237 char *t;
238 int len;
239 char *key = "";
240 char *val = "";
242 fprintf(stderr, "Revision: %d\n", number);
244 for (t = buffer_read_line();
245 t && strncasecmp(t, "PROPS-END", 9);
246 t = buffer_read_line()) {
247 if (!strncmp(t, "K ", 2)) {
248 len = atoi(&t[2]);
249 key = buffer_read_string(len);
250 buffer_read_line();
251 } else if (!strncmp(t, "V ", 2)) {
252 len = atoi(&t[2]);
253 val = buffer_read_string(len);
254 if (!strcmp(key, "svn:log")) {
255 descr = val;
256 fprintf(stderr, "Log: %s\n", descr);
257 } else if (!strcmp(key, "svn:author")) {
258 author = val;
259 fprintf(stderr, "Author: %s\n", author);
260 } else if (!strcmp(key, "svn:date")) {
261 date = val;
262 fprintf(stderr, "Date: %s\n", date);
263 strptime(date, "%FT%T", &tm);
264 timezone = 0;
265 tm.tm_isdst = 0;
266 timestamp = mktime(&tm);
268 key = "";
269 buffer_read_line();
273 for ( ;
274 t && strncmp(t, "Revision-number:", 16);
275 t = buffer_read_line()) {
276 if (!strncmp(t, "Node-path:", 10)) {
277 svnnode_read(&t[11]);
280 if (t)
281 buffer_push_line();
283 repo_commit(number, author, descr, uuid, url, timestamp);
287 * create dump representation by importing dump file
289 static void svndump_read(void)
291 char *t;
292 int revision;
293 for (t = buffer_read_line(); t; t = buffer_read_line()) {
294 if (!strncmp(t, "Revision-number:", 16)) {
295 revision = atoi(&t[17]);
296 svnrev_read(revision);
297 } else if(!strncmp(t, "UUID:", 5)) {
298 uuid = strdup(&t[6]);
303 int main(int argc, char **argv)
305 if (argc > 1) url = argv[1];
306 svndump_read();
307 return 0;