Added option to export the marks table when fast-import terminates.
[gitweb.git] / fast-import.c
index 3e527edf70d3788b76d1d467913240921426cd28..d61da3adecd3c2725a05d65728f09ce5eb5c8c4d 100644 (file)
@@ -14,11 +14,11 @@ Format of STDIN stream:
   file_content ::= data;
 
   new_commit ::= 'commit' sp ref_str lf
-    ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
     mark?
     ('author' sp name '<' email '>' ts tz lf)?
     'committer' sp name '<' email '>' ts tz lf
     commit_msg
+    ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?
     file_change*
     lf;
   commit_msg ::= data;
@@ -223,6 +223,7 @@ static unsigned int object_entry_alloc = 1000;
 static struct object_entry_pool *blocks;
 static struct object_entry *object_table[1 << 16];
 static struct mark_set *marks;
+static const char* mark_file;
 
 /* Our last blob */
 static struct last_object last_blob;
@@ -516,6 +517,7 @@ static struct tree_entry* new_tree_entry()
 
        if (!avail_tree_entry) {
                unsigned int n = tree_entry_alloc;
+               total_allocd += n * sizeof(struct tree_entry);
                avail_tree_entry = e = xmalloc(n * sizeof(struct tree_entry));
                while (n--) {
                        *((void**)e) = e + 1;
@@ -1121,6 +1123,36 @@ static void dump_tags()
        }
 }
 
+static void dump_marks_helper(FILE *f,
+       unsigned long base,
+       struct mark_set *m)
+{
+       int k;
+       if (m->shift) {
+               for (k = 0; k < 1024; k++) {
+                       if (m->data.sets[k])
+                               dump_marks_helper(f, (base + k) << m->shift,
+                                       m->data.sets[k]);
+               }
+       } else {
+               for (k = 0; k < 1024; k++) {
+                       if (m->data.marked[k])
+                               fprintf(f, "%lu,%s\n", base + k,
+                                       sha1_to_hex(m->data.marked[k]->sha1));
+               }
+       }
+}
+
+static void dump_marks()
+{
+       if (mark_file)
+       {
+               FILE *f = fopen(mark_file, "w");
+               dump_marks_helper(f, 0, marks);
+               fclose(f);
+       }
+}
+
 static void read_next_command()
 {
        read_line(&command_buf, stdin, '\n');
@@ -1385,7 +1417,6 @@ static void cmd_new_commit()
                free(str_uq);
 
        read_next_command();
-       cmd_from(b);
        cmd_mark();
        if (!strncmp("author ", command_buf.buf, 7)) {
                author = strdup(command_buf.buf);
@@ -1398,6 +1429,8 @@ static void cmd_new_commit()
        if (!committer)
                die("Expected committer but didn't get one");
        msg = cmd_data(&msglen);
+       read_next_command();
+       cmd_from(b);
 
        /* ensure the branch is active/loaded */
        if (!b->branch_tree.tree || !max_active_branches) {
@@ -1407,7 +1440,6 @@ static void cmd_new_commit()
 
        /* file_change* */
        for (;;) {
-               read_next_command();
                if (1 == command_buf.len)
                        break;
                else if (!strncmp("M ", command_buf.buf, 2))
@@ -1416,6 +1448,7 @@ static void cmd_new_commit()
                        file_change_d(b);
                else
                        die("Unsupported file_change: %s", command_buf.buf);
+               read_next_command();
        }
 
        /* build the tree and the commit */
@@ -1542,7 +1575,7 @@ static void cmd_new_tag()
 }
 
 static const char fast_import_usage[] =
-"git-fast-import [--objects=n] [--depth=n] [--active-branches=n] temp.pack";
+"git-fast-import [--objects=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file] temp.pack";
 
 int main(int argc, const char **argv)
 {
@@ -1567,6 +1600,8 @@ int main(int argc, const char **argv)
                        max_depth = strtoul(a + 8, NULL, 0);
                else if (!strncmp(a, "--active-branches=", 18))
                        max_active_branches = strtoul(a + 18, NULL, 0);
+               else if (!strncmp(a, "--export-marks=", 15))
+                       mark_file = a + 15;
                else
                        die("unknown option %s", a);
        }
@@ -1611,6 +1646,7 @@ int main(int argc, const char **argv)
        write_index(idx_name);
        dump_branches();
        dump_tags();
+       dump_marks();
 
        fprintf(stderr, "%s statistics:\n", argv[0]);
        fprintf(stderr, "---------------------------------------------------\n");