vcs-svn: More dump format sanity checks
[gitweb.git] / vcs-svn / svndump.c
index 45f0e477d7f2c3ac1d60fe2ef691cc3d8f75ba63..ab4ccfc55fbd88750a5787d64e918c866c478aae 100644 (file)
@@ -150,50 +150,65 @@ static void read_props(void)
 
 static void handle_node(void)
 {
-       uint32_t old_mode = 0, mark = 0;
+       uint32_t mark = 0;
+       const uint32_t type = node_ctx.type;
        const int have_props = node_ctx.propLength != LENGTH_UNKNOWN;
 
        if (node_ctx.text_delta || node_ctx.prop_delta)
                die("text and property deltas not supported");
 
-       if (have_props && node_ctx.propLength)
-               read_props();
-
-       if (node_ctx.srcRev)
-               old_mode = repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
-
-       if (node_ctx.textLength != LENGTH_UNKNOWN &&
-           node_ctx.type != REPO_MODE_DIR)
+       if (node_ctx.textLength != LENGTH_UNKNOWN)
                mark = next_blob_mark();
 
        if (node_ctx.action == NODEACT_DELETE) {
+               if (mark || have_props || node_ctx.srcRev)
+                       die("invalid dump: deletion node has "
+                               "copyfrom info, text, or properties");
+               return repo_delete(node_ctx.dst);
+       }
+
+       if (node_ctx.action == NODEACT_REPLACE) {
                repo_delete(node_ctx.dst);
-       } else if (node_ctx.action == NODEACT_CHANGE ||
-                          node_ctx.action == NODEACT_REPLACE) {
-               if (node_ctx.action == NODEACT_REPLACE &&
-                   node_ctx.type == REPO_MODE_DIR)
-                       repo_replace(node_ctx.dst, mark);
-               else if (have_props)
-                       repo_modify(node_ctx.dst, node_ctx.type, mark);
-               else if (node_ctx.textLength != LENGTH_UNKNOWN)
-                       old_mode = repo_replace(node_ctx.dst, mark);
+               node_ctx.action = NODEACT_ADD;
+       }
+
+       if (node_ctx.srcRev) {
+               repo_copy(node_ctx.srcRev, node_ctx.src, node_ctx.dst);
+               if (node_ctx.action == NODEACT_ADD)
+                       node_ctx.action = NODEACT_CHANGE;
+       }
+
+       if (mark && type == REPO_MODE_DIR)
+               die("invalid dump: directories cannot have text attached");
+
+       if (node_ctx.action == NODEACT_CHANGE) {
+               uint32_t mode = repo_modify_path(node_ctx.dst, 0, mark);
+               if (!mode)
+                       die("invalid dump: path to be modified is missing");
+               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;
        } else if (node_ctx.action == NODEACT_ADD) {
-               if (node_ctx.srcRev && have_props)
-                       repo_modify(node_ctx.dst, node_ctx.type, mark);
-               else if (node_ctx.srcRev && node_ctx.textLength != LENGTH_UNKNOWN)
-                       old_mode = repo_replace(node_ctx.dst, mark);
-               else if ((node_ctx.type == REPO_MODE_DIR && !node_ctx.srcRev) ||
-                        node_ctx.textLength != LENGTH_UNKNOWN)
-                       repo_add(node_ctx.dst, node_ctx.type, mark);
+               if (!mark && type != REPO_MODE_DIR)
+                       die("invalid dump: adds node without text");
+               repo_add(node_ctx.dst, type, mark);
+       } else {
+               die("invalid dump: Node-path block lacks Node-action");
        }
 
-       if (!have_props && old_mode)
-               node_ctx.type = old_mode;
+       if (have_props) {
+               const uint32_t old_mode = node_ctx.type;
+               node_ctx.type = type;
+               if (node_ctx.propLength)
+                       read_props();
+               if (node_ctx.type != old_mode)
+                       repo_modify_path(node_ctx.dst, node_ctx.type, mark);
+       }
 
        if (mark)
                fast_export_blob(node_ctx.type, mark, node_ctx.textLength);
-       else if (node_ctx.textLength != LENGTH_UNKNOWN)
-               buffer_skip_bytes(node_ctx.textLength);
 }
 
 static void handle_revision(void)