push.default doc: explain simple after upstream
[gitweb.git] / vcs-svn / svndump.c
index 11c59f18bfccadbd56c7313b0eafea457f5c9f0b..644fdc71ba8c665f5dfadd552c3da63f4d8498e9 100644 (file)
@@ -12,6 +12,7 @@
 #include "fast_export.h"
 #include "line_buffer.h"
 #include "strbuf.h"
+#include "svndump.h"
 
 /*
  * Compare start of string to literal of equal length;
@@ -39,7 +40,8 @@
 static struct line_buffer input = LINE_BUFFER_INIT;
 
 static struct {
-       uint32_t action, propLength, textLength, srcRev, type;
+       uint32_t action, propLength, srcRev, type;
+       off_t text_length;
        struct strbuf src, dst;
        uint32_t text_delta, prop_delta;
 } node_ctx;
@@ -60,7 +62,7 @@ static void reset_node_ctx(char *fname)
        node_ctx.type = 0;
        node_ctx.action = NODEACT_UNKNOWN;
        node_ctx.propLength = LENGTH_UNKNOWN;
-       node_ctx.textLength = LENGTH_UNKNOWN;
+       node_ctx.text_length = -1;
        strbuf_reset(&node_ctx.src);
        node_ctx.srcRev = 0;
        strbuf_reset(&node_ctx.dst);
@@ -208,7 +210,7 @@ static void handle_node(void)
 {
        const uint32_t type = node_ctx.type;
        const int have_props = node_ctx.propLength != LENGTH_UNKNOWN;
-       const int have_text = node_ctx.textLength != LENGTH_UNKNOWN;
+       const int have_text = node_ctx.text_length != -1;
        /*
         * Old text for this node:
         *  NULL        - directory or bug
@@ -217,9 +219,7 @@ static void handle_node(void)
         */
        static const char *const empty_blob = "::empty::";
        const char *old_data = NULL;
-
-       if (node_ctx.text_delta)
-               die("text deltas not supported");
+       uint32_t old_mode = REPO_MODE_BLB;
 
        if (node_ctx.action == NODEACT_DELETE) {
                if (have_text || have_props || node_ctx.srcRev)
@@ -255,6 +255,7 @@ static void handle_node(void)
                if (mode != REPO_MODE_DIR && type == REPO_MODE_DIR)
                        die("invalid dump: cannot modify a file into a directory");
                node_ctx.type = mode;
+               old_mode = mode;
        } else if (node_ctx.action == NODEACT_ADD) {
                if (type == REPO_MODE_DIR)
                        old_data = NULL;
@@ -289,8 +290,14 @@ static void handle_node(void)
                fast_export_modify(node_ctx.dst.buf, node_ctx.type, old_data);
                return;
        }
+       if (!node_ctx.text_delta) {
+               fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline");
+               fast_export_data(node_ctx.type, node_ctx.text_length, &input);
+               return;
+       }
        fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline");
-       fast_export_data(node_ctx.type, node_ctx.textLength, &input);
+       fast_export_blob_delta(node_ctx.type, old_mode, old_data,
+                               node_ctx.text_length, &input);
 }
 
 static void begin_revision(void)
@@ -403,7 +410,15 @@ void svndump_read(const char *url)
                        break;
                case sizeof("Text-content-length"):
                        if (!constcmp(t, "Text-content-length")) {
-                               node_ctx.textLength = atoi(val);
+                               char *end;
+                               uintmax_t textlen;
+
+                               textlen = strtoumax(val, &end, 10);
+                               if (!isdigit(*val) || *end)
+                                       die("invalid dump: non-numeric length %s", val);
+                               if (textlen > maximum_signed_value_of_type(off_t))
+                                       die("unrepresentable length in dump: %s", val);
+                               node_ctx.text_length = (off_t) textlen;
                                break;
                        }
                        if (constcmp(t, "Prop-content-length"))