vcs-svn: pass paths through to fast-import
authorDavid Barr <david.barr@cordelta.com>
Mon, 13 Dec 2010 05:41:12 +0000 (16:41 +1100)
committerJonathan Nieder <jrnieder@gmail.com>
Tue, 22 Mar 2011 23:32:58 +0000 (18:32 -0500)
Now that there is no internal representation of the repo, it is not
necessary to tokenise paths.  Use strbuf instead and bypass
string_pool.

This means svn-fe can handle arbitrarily long paths (as long as a
strbuf can fit them), with arbitrarily many path components.

While at it, since we now treat paths in their entirety, only quote
when necessary.

Signed-off-by: David Barr <david.barr@cordelta.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
vcs-svn/fast_export.c
vcs-svn/fast_export.h
vcs-svn/repo_tree.c
vcs-svn/repo_tree.h
vcs-svn/svndump.c

index a64a3c5633212fe5bd48f34d1ab568be6512df21..ec323e9b3917307abf96a111b7fe5aa40c2a56df 100644 (file)
@@ -4,10 +4,11 @@
  */
 
 #include "git-compat-util.h"
+#include "strbuf.h"
+#include "quote.h"
 #include "fast_export.h"
 #include "line_buffer.h"
 #include "repo_tree.h"
-#include "string_pool.h"
 #include "strbuf.h"
 
 #define MAX_GITSVN_LINE_LEN 4096
@@ -32,30 +33,30 @@ void fast_export_reset(void)
        buffer_reset(&report_buffer);
 }
 
-void fast_export_delete(uint32_t depth, const uint32_t *path)
+void fast_export_delete(const char *path)
 {
-       printf("D \"");
-       pool_print_seq_q(depth, path, '/', stdout);
-       printf("\"\n");
+       putchar('D');
+       putchar(' ');
+       quote_c_style(path, NULL, stdout, 0);
+       putchar('\n');
 }
 
-static void fast_export_truncate(uint32_t depth, const uint32_t *path, uint32_t mode)
+static void fast_export_truncate(const char *path, uint32_t mode)
 {
-       fast_export_modify(depth, path, mode, "inline");
+       fast_export_modify(path, mode, "inline");
        printf("data 0\n\n");
 }
 
-void fast_export_modify(uint32_t depth, const uint32_t *path, uint32_t mode,
-                       const char *dataref)
+void fast_export_modify(const char *path, uint32_t mode, const char *dataref)
 {
        /* Mode must be 100644, 100755, 120000, or 160000. */
        if (!dataref) {
-               fast_export_truncate(depth, path, mode);
+               fast_export_truncate(path, mode);
                return;
        }
-       printf("M %06"PRIo32" %s \"", mode, dataref);
-       pool_print_seq_q(depth, path, '/', stdout);
-       printf("\"\n");
+       printf("M %06"PRIo32" %s ", mode, dataref);
+       quote_c_style(path, NULL, stdout, 0);
+       putchar('\n');
 }
 
 static char gitsvnline[MAX_GITSVN_LINE_LEN];
@@ -93,20 +94,20 @@ void fast_export_end_commit(uint32_t revision)
        printf("progress Imported commit %"PRIu32".\n\n", revision);
 }
 
-static void ls_from_rev(uint32_t rev, uint32_t depth, const uint32_t *path)
+static void ls_from_rev(uint32_t rev, const char *path)
 {
        /* ls :5 path/to/old/file */
-       printf("ls :%"PRIu32" \"", rev);
-       pool_print_seq_q(depth, path, '/', stdout);
-       printf("\"\n");
+       printf("ls :%"PRIu32" ", rev);
+       quote_c_style(path, NULL, stdout, 0);
+       putchar('\n');
        fflush(stdout);
 }
 
-static void ls_from_active_commit(uint32_t depth, const uint32_t *path)
+static void ls_from_active_commit(const char *path)
 {
        /* ls "path/to/file" */
        printf("ls \"");
-       pool_print_seq_q(depth, path, '/', stdout);
+       quote_c_style(path, NULL, stdout, 1);
        printf("\"\n");
        fflush(stdout);
 }
@@ -183,16 +184,15 @@ static int parse_ls_response(const char *response, uint32_t *mode,
        return 0;
 }
 
-int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
+int fast_export_ls_rev(uint32_t rev, const char *path,
                                uint32_t *mode, struct strbuf *dataref)
 {
-       ls_from_rev(rev, depth, path);
+       ls_from_rev(rev, 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)
+int fast_export_ls(const char *path, uint32_t *mode, struct strbuf *dataref)
 {
-       ls_from_active_commit(depth, path);
+       ls_from_active_commit(path);
        return parse_ls_response(get_response_line(), mode, dataref);
 }
index fc142424201a94b5eb9da7efbf3cf52c2766cd49..12b0bbb41969ea2159a79c9fe90492fb1b2435d2 100644 (file)
@@ -8,9 +8,8 @@ void fast_export_init(int fd);
 void fast_export_deinit(void);
 void fast_export_reset(void);
 
-void fast_export_delete(uint32_t depth, const uint32_t *path);
-void fast_export_modify(uint32_t depth, const uint32_t *path,
-                       uint32_t mode, const char *dataref);
+void fast_export_delete(const char *path);
+void fast_export_modify(const char *path, uint32_t mode, const char *dataref);
 void fast_export_begin_commit(uint32_t revision, const char *author, char *log,
                        const char *uuid, const char *url,
                        unsigned long timestamp);
@@ -18,9 +17,9 @@ void fast_export_end_commit(uint32_t revision);
 void fast_export_data(uint32_t mode, uint32_t len, struct line_buffer *input);
 
 /* If there is no such file at that rev, returns -1, errno == ENOENT. */
-int fast_export_ls_rev(uint32_t rev, uint32_t depth, const uint32_t *path,
+int fast_export_ls_rev(uint32_t rev, const char *path,
                        uint32_t *mode_out, struct strbuf *dataref_out);
-int fast_export_ls(uint32_t depth, const uint32_t *path,
+int fast_export_ls(const char *path,
                        uint32_t *mode_out, struct strbuf *dataref_out);
 
 #endif
index e75f58087c23f75fbb6b61fdf1a795e06d4832df..f2466bc63412f2afc2b0ce07306ed2351d0fa749 100644 (file)
@@ -8,14 +8,14 @@
 #include "repo_tree.h"
 #include "fast_export.h"
 
-const char *repo_read_path(const uint32_t *path)
+const char *repo_read_path(const char *path)
 {
        int err;
        uint32_t dummy;
        static struct strbuf buf = STRBUF_INIT;
 
        strbuf_reset(&buf);
-       err = fast_export_ls(REPO_MAX_PATH_DEPTH, path, &dummy, &buf);
+       err = fast_export_ls(path, &dummy, &buf);
        if (err) {
                if (errno != ENOENT)
                        die_errno("BUG: unexpected fast_export_ls error");
@@ -24,14 +24,14 @@ const char *repo_read_path(const uint32_t *path)
        return buf.buf;
 }
 
-uint32_t repo_read_mode(const uint32_t *path)
+uint32_t repo_read_mode(const char *path)
 {
        int err;
        uint32_t result;
        static struct strbuf dummy = STRBUF_INIT;
 
        strbuf_reset(&dummy);
-       err = fast_export_ls(REPO_MAX_PATH_DEPTH, path, &result, &dummy);
+       err = fast_export_ls(path, &result, &dummy);
        if (err) {
                if (errno != ENOENT)
                        die_errno("BUG: unexpected fast_export_ls error");
@@ -41,24 +41,24 @@ uint32_t repo_read_mode(const uint32_t *path)
        return result;
 }
 
-void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst)
+void repo_copy(uint32_t revision, const char *src, const char *dst)
 {
        int err;
        uint32_t mode;
        static struct strbuf data = STRBUF_INIT;
 
        strbuf_reset(&data);
-       err = fast_export_ls_rev(revision, REPO_MAX_PATH_DEPTH, src, &mode, &data);
+       err = fast_export_ls_rev(revision, src, &mode, &data);
        if (err) {
                if (errno != ENOENT)
                        die_errno("BUG: unexpected fast_export_ls_rev error");
-               fast_export_delete(REPO_MAX_PATH_DEPTH, dst);
+               fast_export_delete(dst);
                return;
        }
-       fast_export_modify(REPO_MAX_PATH_DEPTH, dst, mode, data.buf);
+       fast_export_modify(dst, mode, data.buf);
 }
 
-void repo_delete(uint32_t *path)
+void repo_delete(const char *path)
 {
-       fast_export_delete(REPO_MAX_PATH_DEPTH, path);
+       fast_export_delete(path);
 }
index 29887f97656333688f2aeba90978f7f76388174c..44e6e8fabc4c26a8bc6369d9182ff03d2219228d 100644 (file)
@@ -8,15 +8,12 @@
 #define REPO_MODE_EXE 0100755
 #define REPO_MODE_LNK 0120000
 
-#define REPO_MAX_PATH_LEN 4096
-#define REPO_MAX_PATH_DEPTH 1000
-
 uint32_t next_blob_mark(void);
-void repo_copy(uint32_t revision, const uint32_t *src, const uint32_t *dst);
-void repo_add(uint32_t *path, uint32_t mode, uint32_t blob_mark);
-const char *repo_read_path(const uint32_t *path);
-uint32_t repo_read_mode(const uint32_t *path);
-void repo_delete(uint32_t *path);
+void repo_copy(uint32_t revision, const char *src, const char *dst);
+void repo_add(const char *path, uint32_t mode, uint32_t blob_mark);
+const char *repo_read_path(const char *path);
+uint32_t repo_read_mode(const char *path);
+void repo_delete(const char *path);
 void repo_commit(uint32_t revision, const char *author,
                char *log, const char *uuid, const char *url,
                long unsigned timestamp);
index f5de49cbeb35c5b146db1280de4322ce2fab4031..363503d4eafb9f157afbbfe0d593f1ceee8ed0c9 100644 (file)
@@ -11,7 +11,6 @@
 #include "repo_tree.h"
 #include "fast_export.h"
 #include "line_buffer.h"
-#include "string_pool.h"
 #include "strbuf.h"
 
 #define REPORT_FILENO 3
@@ -41,7 +40,7 @@ static struct line_buffer input = LINE_BUFFER_INIT;
 
 static struct {
        uint32_t action, propLength, textLength, srcRev, type;
-       uint32_t src[REPO_MAX_PATH_DEPTH], dst[REPO_MAX_PATH_DEPTH];
+       struct strbuf src, dst;
        uint32_t text_delta, prop_delta;
 } node_ctx;
 
@@ -62,9 +61,11 @@ static void reset_node_ctx(char *fname)
        node_ctx.action = NODEACT_UNKNOWN;
        node_ctx.propLength = LENGTH_UNKNOWN;
        node_ctx.textLength = LENGTH_UNKNOWN;
-       node_ctx.src[0] = ~0;
+       strbuf_reset(&node_ctx.src);
        node_ctx.srcRev = 0;
-       pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.dst, "/", fname);
+       strbuf_reset(&node_ctx.dst);
+       if (fname)
+               strbuf_addstr(&node_ctx.dst, fname);
        node_ctx.text_delta = 0;
        node_ctx.prop_delta = 0;
 }
@@ -228,14 +229,14 @@ static void handle_node(void)
                if (have_text || have_props || node_ctx.srcRev)
                        die("invalid dump: deletion node has "
                                "copyfrom info, text, or properties");
-               return repo_delete(node_ctx.dst);
+               return repo_delete(node_ctx.dst.buf);
        }
        if (node_ctx.action == NODEACT_REPLACE) {
-               repo_delete(node_ctx.dst);
+               repo_delete(node_ctx.dst.buf);
                node_ctx.action = NODEACT_ADD;
        }
        if (node_ctx.srcRev) {
-               repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
+               repo_copy(node_ctx.srcRev, node_ctx.src.buf, node_ctx.dst.buf);
                if (node_ctx.action == NODEACT_ADD)
                        node_ctx.action = NODEACT_CHANGE;
        }
@@ -245,14 +246,14 @@ static void handle_node(void)
        /*
         * Find old content (old_data) and decide on the new mode.
         */
-       if (node_ctx.action == NODEACT_CHANGE && !~*node_ctx.dst) {
+       if (node_ctx.action == NODEACT_CHANGE && !*node_ctx.dst.buf) {
                if (type != REPO_MODE_DIR)
                        die("invalid dump: root of tree is not a regular file");
                old_data = NULL;
        } else if (node_ctx.action == NODEACT_CHANGE) {
                uint32_t mode;
-               old_data = repo_read_path(node_ctx.dst);
-               mode = repo_read_mode(node_ctx.dst);
+               old_data = repo_read_path(node_ctx.dst.buf);
+               mode = repo_read_mode(node_ctx.dst.buf);
                if (mode == REPO_MODE_DIR && type != REPO_MODE_DIR)
                        die("invalid dump: cannot modify a directory into a file");
                if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
@@ -289,12 +290,10 @@ static void handle_node(void)
                /* For the fast_export_* functions, NULL means empty. */
                old_data = NULL;
        if (!have_text) {
-               fast_export_modify(REPO_MAX_PATH_DEPTH, node_ctx.dst,
-                                       node_ctx.type, old_data);
+               fast_export_modify(node_ctx.dst.buf, node_ctx.type, old_data);
                return;
        }
-       fast_export_modify(REPO_MAX_PATH_DEPTH, node_ctx.dst,
-                               node_ctx.type, "inline");
+       fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline");
        fast_export_data(node_ctx.type, node_ctx.textLength, &input);
 }
 
@@ -395,7 +394,8 @@ void svndump_read(const char *url)
                case sizeof("Node-copyfrom-path"):
                        if (constcmp(t, "Node-copyfrom-path"))
                                continue;
-                       pool_tok_seq(REPO_MAX_PATH_DEPTH, node_ctx.src, "/", val);
+                       strbuf_reset(&node_ctx.src);
+                       strbuf_addstr(&node_ctx.src, val);
                        break;
                case sizeof("Node-copyfrom-rev"):
                        if (constcmp(t, "Node-copyfrom-rev"))
@@ -460,6 +460,8 @@ int svndump_init(const char *filename)
        strbuf_init(&dump_ctx.url, 4096);
        strbuf_init(&rev_ctx.log, 4096);
        strbuf_init(&rev_ctx.author, 4096);
+       strbuf_init(&node_ctx.src, 4096);
+       strbuf_init(&node_ctx.dst, 4096);
        reset_dump_ctx(NULL);
        reset_rev_ctx(0);
        reset_node_ctx(NULL);
@@ -473,6 +475,8 @@ void svndump_deinit(void)
        reset_rev_ctx(0);
        reset_node_ctx(NULL);
        strbuf_release(&rev_ctx.log);
+       strbuf_release(&node_ctx.src);
+       strbuf_release(&node_ctx.dst);
        if (buffer_deinit(&input))
                fprintf(stderr, "Input error\n");
        if (ferror(stdout))