printf("progress Imported commit %"PRIu32".\n\n", revision);
}
-void fast_export_blob(uint32_t mode, uint32_t mark, uint32_t len, struct line_buffer *input)
+static void ls_from_rev(uint32_t rev, uint32_t depth, const uint32_t *path)
+{
+ /* ls :5 path/to/old/file */
+ printf("ls :%"PRIu32" \"", rev);
+ pool_print_seq_q(depth, path, '/', stdout);
+ printf("\"\n");
+ fflush(stdout);
+}
+
+static void ls_from_active_commit(uint32_t depth, const uint32_t *path)
+{
+ /* ls "path/to/file" */
+ printf("ls \"");
+ pool_print_seq_q(depth, path, '/', stdout);
+ printf("\"\n");
+ fflush(stdout);
+}
+
+static const char *get_response_line(void)
+{
+ const char *line = buffer_read_line(&report_buffer);
+ if (line)
+ return line;
+ if (buffer_ferror(&report_buffer))
+ die_errno("error reading from fast-import");
+ die("unexpected end of fast-import feedback");
+}
+
+ static void die_short_read(struct line_buffer *input)
+ {
+ if (buffer_ferror(input))
+ die_errno("error reading dump file");
+ die("invalid dump: unexpected end of file");
+ }
+
+void fast_export_data(uint32_t mode, uint32_t len, struct line_buffer *input)
{
if (mode == REPO_MODE_LNK) {
/* svn symlink blobs start with "link " */
- buffer_skip_bytes(input, 5);
len -= 5;
+ if (buffer_skip_bytes(input, 5) != 5)
+ die_short_read(input);
}
- printf("blob\nmark :%"PRIu32"\ndata %"PRIu32"\n", mark, len);
+ printf("data %"PRIu32"\n", len);
- buffer_copy_bytes(input, len);
+ if (buffer_copy_bytes(input, len) != len)
+ die_short_read(input);
fputc('\n', stdout);
}
+
+static int parse_ls_response(const char *response, uint32_t *mode,
+ struct strbuf *dataref)
+{
+ const char *tab;
+ const char *response_end;
+
+ assert(response);
+ response_end = response + strlen(response);
+
+ if (*response == 'm') { /* Missing. */
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* Mode. */
+ if (response_end - response < strlen("100644") ||
+ response[strlen("100644")] != ' ')
+ die("invalid ls response: missing mode: %s", response);
+ *mode = 0;
+ for (; *response != ' '; response++) {
+ char ch = *response;
+ if (ch < '0' || ch > '7')
+ die("invalid ls response: mode is not octal: %s", response);
+ *mode *= 8;
+ *mode += ch - '0';
+ }
+
+ /* ' blob ' or ' tree ' */
+ if (response_end - response < strlen(" blob ") ||
+ (response[1] != 'b' && response[1] != 't'))
+ die("unexpected ls response: not a tree or blob: %s", response);
+ response += strlen(" blob ");
+
+ /* Dataref. */
+ tab = memchr(response, '\t', response_end - response);
+ if (!tab)
+ die("invalid ls response: missing tab: %s", response);
+ strbuf_add(dataref, response, tab - response);
+ return 0;
+}
+
+int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
+ uint32_t *mode, struct strbuf *dataref)
+{
+ ls_from_rev(rev, depth, path);
+ return parse_ls_response(get_response_line(), mode, dataref);
+}
+
+int fast_export_ls(uint32_t depth, const uint32_t *path,
+ uint32_t *mode, struct strbuf *dataref)
+{
+ ls_from_active_commit(depth, path);
+ return parse_ls_response(get_response_line(), mode, dataref);
+}
#include "obj_pool.h"
#include "string_pool.h"
+#define REPORT_FILENO 3
+
+ /*
+ * Compare start of string to literal of equal length;
+ * must be guarded by length test.
+ */
+ #define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
+
#define NODEACT_REPLACE 4
#define NODEACT_DELETE 3
#define NODEACT_ADD 2
if (dump_ctx.version > 3)
die("expected svn dump format version <= 3, found %"PRIu32,
dump_ctx.version);
- } else if (key == keys.uuid) {
+ break;
+ case sizeof("UUID"):
+ if (constcmp(t, "UUID"))
+ continue;
dump_ctx.uuid = pool_intern(val);
- } else if (key == keys.revision_number) {
+ break;
+ case sizeof("Revision-number"):
+ if (constcmp(t, "Revision-number"))
+ continue;
if (active_ctx == NODE_CTX)
handle_node();
+ if (active_ctx == REV_CTX)
+ begin_revision();
if (active_ctx != DUMP_CTX)
- handle_revision();
+ end_revision();
active_ctx = REV_CTX;
reset_rev_ctx(atoi(val));
- } else if (key == keys.node_path) {
- if (active_ctx == NODE_CTX)
- handle_node();
- if (active_ctx == REV_CTX)
- begin_revision();
- active_ctx = NODE_CTX;
- reset_node_ctx(val);
- } else if (key == keys.node_kind) {
+ break;
+ case sizeof("Node-path"):
+ if (prefixcmp(t, "Node-"))
+ continue;
+ if (!constcmp(t + strlen("Node-"), "path")) {
+ if (active_ctx == NODE_CTX)
+ handle_node();
++ if (active_ctx == REV_CTX)
++ begin_revision();
+ active_ctx = NODE_CTX;
+ reset_node_ctx(val);
+ break;
+ }
+ if (constcmp(t + strlen("Node-"), "kind"))
+ continue;
if (!strcmp(val, "dir"))
node_ctx.type = REPO_MODE_DIR;
else if (!strcmp(val, "file"))
read_props();
} else if (active_ctx == NODE_CTX) {
handle_node();
- active_ctx = REV_CTX;
+ active_ctx = INTERNODE_CTX;
} else {
fprintf(stderr, "Unexpected content length header: %"PRIu32"\n", len);
- buffer_skip_bytes(&input, len);
+ if (buffer_skip_bytes(&input, len) != len)
+ die_short_read();
}
}
}
+ if (buffer_ferror(&input))
+ die_short_read();
if (active_ctx == NODE_CTX)
handle_node();
+ if (active_ctx == REV_CTX)
+ begin_revision();
if (active_ctx != DUMP_CTX)
- handle_revision();
+ end_revision();
}
int svndump_init(const char *filename)