#include "repo_tree.h"
 #include "fast_export.h"
 #include "line_buffer.h"
-#include "string_pool.h"
 #include "strbuf.h"
+#include "svndump.h"
 
 /*
  * Compare start of string to literal of equal length;
 #define NODE_CTX 2     /* node metadata */
 #define INTERNODE_CTX 3        /* between nodes */
 
-#define LENGTH_UNKNOWN (~0)
 #define DATE_RFC2822_LEN 31
 
 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];
+       uint32_t action, srcRev, type;
+       off_t prop_length, text_length;
+       struct strbuf src, dst;
        uint32_t text_delta, prop_delta;
 } node_ctx;
 
 {
        node_ctx.type = 0;
        node_ctx.action = NODEACT_UNKNOWN;
-       node_ctx.propLength = LENGTH_UNKNOWN;
-       node_ctx.textLength = LENGTH_UNKNOWN;
-       node_ctx.src[0] = ~0;
+       node_ctx.prop_length = -1;
+       node_ctx.text_length = -1;
+       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;
 }
                int ch;
 
                if (!type || t[1] != ' ')
-                       die("invalid property line: %s\n", t);
+                       die("invalid property line: %s", t);
                len = atoi(&t[2]);
                strbuf_reset(&val);
                buffer_read_binary(&input, &val, len);
                        strbuf_reset(&key);
                        continue;
                default:
-                       die("invalid property line: %s\n", t);
+                       die("invalid property line: %s", t);
                }
        }
 }
 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_props = node_ctx.prop_length != -1;
+       const int have_text = node_ctx.text_length != -1;
        /*
         * Old text for this node:
         *  NULL        - directory or bug
         */
        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)
                        die("invalid dump: deletion node has "
                                "copyfrom info, text, or properties");
-               repo_delete(node_ctx.dst);
+               repo_delete(node_ctx.dst.buf);
                return;
        }
        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;
        }
        /*
         * 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);
+               old_data = repo_read_path(node_ctx.dst.buf, &mode);
                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)
                        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;
        if (have_props) {
                if (!node_ctx.prop_delta)
                        node_ctx.type = type;
-               if (node_ctx.propLength)
+               if (node_ctx.prop_length)
                        read_props();
        }
 
                /* 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;
+       }
+       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(REPO_MAX_PATH_DEPTH, node_ctx.dst,
-                               node_ctx.type, "inline");
-       fast_export_data(node_ctx.type, node_ctx.textLength, &input);
+       fast_export_modify(node_ctx.dst.buf, node_ctx.type, "inline");
+       fast_export_blob_delta(node_ctx.type, old_mode, old_data,
+                               node_ctx.text_length, &input);
 }
 
 static void begin_revision(void)
                        reset_rev_ctx(atoi(val));
                        break;
                case sizeof("Node-path"):
-                       if (prefixcmp(t, "Node-"))
+                       if (constcmp(t, "Node-"))
                                continue;
                        if (!constcmp(t + strlen("Node-"), "path")) {
                                if (active_ctx == NODE_CTX)
                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"))
                        node_ctx.srcRev = atoi(val);
                        break;
                case sizeof("Text-content-length"):
-                       if (!constcmp(t, "Text-content-length")) {
-                               node_ctx.textLength = atoi(val);
+                       if (constcmp(t, "Text") && constcmp(t, "Prop"))
+                               continue;
+                       if (constcmp(t + 4, "-content-length"))
+                               continue;
+                       {
+                               char *end;
+                               uintmax_t len;
+
+                               len = strtoumax(val, &end, 10);
+                               if (!isdigit(*val) || *end)
+                                       die("invalid dump: non-numeric length %s", val);
+                               if (len > maximum_signed_value_of_type(off_t))
+                                       die("unrepresentable length in dump: %s", val);
+
+                               if (*t == 'T')
+                                       node_ctx.text_length = (off_t) len;
+                               else
+                                       node_ctx.prop_length = (off_t) len;
                                break;
                        }
-                       if (constcmp(t, "Prop-content-length"))
-                               continue;
-                       node_ctx.propLength = atoi(val);
-                       break;
                case sizeof("Text-delta"):
                        if (!constcmp(t, "Text-delta")) {
                                node_ctx.text_delta = !strcmp(val, "true");
        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);
        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))
 
 void svndump_reset(void)
 {
-       fast_export_reset();
-       buffer_reset(&input);
        strbuf_release(&dump_ctx.uuid);
        strbuf_release(&dump_ctx.url);
        strbuf_release(&rev_ctx.log);