diff-tree -r -t: include added/removed directories in the output
[gitweb.git] / fast-import.c
index 73e5439d97481a0e4dcaa17d025b27ec3fdcf41b..5bc9ce2cc944d12914df0802fb4e010b056ed634 100644 (file)
@@ -43,7 +43,7 @@ Format of STDIN stream:
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf
-    'tagger' sp name '<' email '>' when lf
+    ('tagger' sp name '<' email '>' when lf)?
     tag_msg;
   tag_msg ::= data;
 
@@ -816,7 +816,7 @@ static void start_packfile(void)
        int pack_fd;
 
        snprintf(tmpfile, sizeof(tmpfile),
-               "%s/tmp_pack_XXXXXX", get_object_directory());
+               "%s/pack/tmp_pack_XXXXXX", get_object_directory());
        pack_fd = xmkstemp(tmpfile);
        p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
        strcpy(p->pack_name, tmpfile);
@@ -878,7 +878,7 @@ static char *create_index(void)
        }
 
        snprintf(tmpfile, sizeof(tmpfile),
-               "%s/tmp_idx_XXXXXX", get_object_directory());
+               "%s/pack/tmp_idx_XXXXXX", get_object_directory());
        idx_fd = xmkstemp(tmpfile);
        f = sha1fd(idx_fd, tmpfile);
        sha1write(f, array, 256 * sizeof(int));
@@ -890,7 +890,7 @@ static char *create_index(void)
                SHA1_Update(&ctx, (*c)->sha1, 20);
        }
        sha1write(f, pack_data->sha1, sizeof(pack_data->sha1));
-       sha1close(f, NULL, 1);
+       sha1close(f, NULL, CSUM_FSYNC);
        free(idx);
        SHA1_Final(pack_data->sha1, &ctx);
        return tmpfile;
@@ -943,6 +943,7 @@ static void end_packfile(void)
 {
        struct packed_git *old_p = pack_data, *new_p;
 
+       clear_delta_base_cache();
        if (object_count) {
                char *idx_name;
                int i;
@@ -951,7 +952,8 @@ static void end_packfile(void)
 
                close_pack_windows(pack_data);
                fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1,
-                                   pack_data->pack_name, object_count);
+                                   pack_data->pack_name, object_count,
+                                   NULL, 0);
                close(pack_data->pack_fd);
                idx_name = keep_pack(create_index());
 
@@ -981,8 +983,10 @@ static void end_packfile(void)
 
                pack_id++;
        }
-       else
+       else {
+               close(old_p->pack_fd);
                unlink(old_p->pack_name);
+       }
        free(old_p);
 
        /* We can't carry a delta across packfiles. */
@@ -1690,7 +1694,7 @@ static void skip_optional_lf(void)
                ungetc(term_char, stdin);
 }
 
-static void cmd_mark(void)
+static void parse_mark(void)
 {
        if (!prefixcmp(command_buf.buf, "mark :")) {
                next_mark = strtoumax(command_buf.buf + 6, NULL, 10);
@@ -1700,7 +1704,7 @@ static void cmd_mark(void)
                next_mark = 0;
 }
 
-static void cmd_data(struct strbuf *sb)
+static void parse_data(struct strbuf *sb)
 {
        strbuf_reset(sb);
 
@@ -1798,13 +1802,13 @@ static char *parse_ident(const char *buf)
        return ident;
 }
 
-static void cmd_new_blob(void)
+static void parse_new_blob(void)
 {
        static struct strbuf buf = STRBUF_INIT;
 
        read_next_command();
-       cmd_mark();
-       cmd_data(&buf);
+       parse_mark();
+       parse_data(&buf);
        store_object(OBJ_BLOB, &buf, &last_blob, NULL, next_mark);
 }
 
@@ -1865,11 +1869,13 @@ static void file_change_m(struct branch *b)
        if (!p)
                die("Corrupt mode: %s", command_buf.buf);
        switch (mode) {
+       case 0644:
+       case 0755:
+               mode |= S_IFREG;
        case S_IFREG | 0644:
        case S_IFREG | 0755:
        case S_IFLNK:
-       case 0644:
-       case 0755:
+       case S_IFGITLINK:
                /* ok */
                break;
        default:
@@ -1900,7 +1906,20 @@ static void file_change_m(struct branch *b)
                p = uq.buf;
        }
 
-       if (inline_data) {
+       if (S_ISGITLINK(mode)) {
+               if (inline_data)
+                       die("Git links cannot be specified 'inline': %s",
+                               command_buf.buf);
+               else if (oe) {
+                       if (oe->type != OBJ_COMMIT)
+                               die("Not a commit (actually a %s): %s",
+                                       typename(oe->type), command_buf.buf);
+               }
+               /*
+                * Accept the sha1 without checking; it expected to be in
+                * another repository.
+                */
+       } else if (inline_data) {
                static struct strbuf buf = STRBUF_INIT;
 
                if (p != uq.buf) {
@@ -1908,7 +1927,7 @@ static void file_change_m(struct branch *b)
                        p = uq.buf;
                }
                read_next_command();
-               cmd_data(&buf);
+               parse_data(&buf);
                store_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);
        } else if (oe) {
                if (oe->type != OBJ_BLOB)
@@ -1923,7 +1942,7 @@ static void file_change_m(struct branch *b)
                            typename(type), command_buf.buf);
        }
 
-       tree_content_set(&b->branch_tree, p, sha1, S_IFREG | mode, NULL);
+       tree_content_set(&b->branch_tree, p, sha1, mode, NULL);
 }
 
 static void file_change_d(struct branch *b)
@@ -1995,7 +2014,7 @@ static void file_change_deleteall(struct branch *b)
        load_tree(&b->branch_tree);
 }
 
-static void cmd_from_commit(struct branch *b, char *buf, unsigned long size)
+static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
 {
        if (!buf || size < 46)
                die("Not a valid commit: %s", sha1_to_hex(b->sha1));
@@ -2006,7 +2025,7 @@ static void cmd_from_commit(struct branch *b, char *buf, unsigned long size)
                b->branch_tree.versions[1].sha1);
 }
 
-static void cmd_from_existing(struct branch *b)
+static void parse_from_existing(struct branch *b)
 {
        if (is_null_sha1(b->sha1)) {
                hashclr(b->branch_tree.versions[0].sha1);
@@ -2017,12 +2036,12 @@ static void cmd_from_existing(struct branch *b)
 
                buf = read_object_with_reference(b->sha1,
                        commit_type, &size, b->sha1);
-               cmd_from_commit(b, buf, size);
+               parse_from_commit(b, buf, size);
                free(buf);
        }
 }
 
-static int cmd_from(struct branch *b)
+static int parse_from(struct branch *b)
 {
        const char *from;
        struct branch *s;
@@ -2053,12 +2072,12 @@ static int cmd_from(struct branch *b)
                if (oe->pack_id != MAX_PACK_ID) {
                        unsigned long size;
                        char *buf = gfi_unpack_entry(oe, &size);
-                       cmd_from_commit(b, buf, size);
+                       parse_from_commit(b, buf, size);
                        free(buf);
                } else
-                       cmd_from_existing(b);
+                       parse_from_existing(b);
        } else if (!get_sha1(from, b->sha1))
-               cmd_from_existing(b);
+               parse_from_existing(b);
        else
                die("Invalid ref name or SHA1 expression: %s", from);
 
@@ -2066,7 +2085,7 @@ static int cmd_from(struct branch *b)
        return 1;
 }
 
-static struct hash_list *cmd_merge(unsigned int *count)
+static struct hash_list *parse_merge(unsigned int *count)
 {
        struct hash_list *list = NULL, *n, *e = e;
        const char *from;
@@ -2107,7 +2126,7 @@ static struct hash_list *cmd_merge(unsigned int *count)
        return list;
 }
 
-static void cmd_new_commit(void)
+static void parse_new_commit(void)
 {
        static struct strbuf msg = STRBUF_INIT;
        struct branch *b;
@@ -2124,7 +2143,7 @@ static void cmd_new_commit(void)
                b = new_branch(sp);
 
        read_next_command();
-       cmd_mark();
+       parse_mark();
        if (!prefixcmp(command_buf.buf, "author ")) {
                author = parse_ident(command_buf.buf + 7);
                read_next_command();
@@ -2135,10 +2154,10 @@ static void cmd_new_commit(void)
        }
        if (!committer)
                die("Expected committer but didn't get one");
-       cmd_data(&msg);
+       parse_data(&msg);
        read_next_command();
-       cmd_from(b);
-       merge_list = cmd_merge(&merge_count);
+       parse_from(b);
+       merge_list = parse_merge(&merge_count);
 
        /* ensure the branch is active/loaded */
        if (!b->branch_tree.tree || !max_active_branches) {
@@ -2196,7 +2215,7 @@ static void cmd_new_commit(void)
        b->last_commit = object_count_by_type[OBJ_COMMIT];
 }
 
-static void cmd_new_tag(void)
+static void parse_new_tag(void)
 {
        static struct strbuf msg = STRBUF_INIT;
        char *sp;
@@ -2247,23 +2266,27 @@ static void cmd_new_tag(void)
        read_next_command();
 
        /* tagger ... */
-       if (prefixcmp(command_buf.buf, "tagger "))
-               die("Expected tagger command, got %s", command_buf.buf);
-       tagger = parse_ident(command_buf.buf + 7);
+       if (!prefixcmp(command_buf.buf, "tagger ")) {
+               tagger = parse_ident(command_buf.buf + 7);
+               read_next_command();
+       } else
+               tagger = NULL;
 
        /* tag payload/message */
-       read_next_command();
-       cmd_data(&msg);
+       parse_data(&msg);
 
        /* build the tag object */
        strbuf_reset(&new_data);
+
        strbuf_addf(&new_data,
-               "object %s\n"
-               "type %s\n"
-               "tag %s\n"
-               "tagger %s\n"
-               "\n",
-               sha1_to_hex(sha1), commit_type, t->name, tagger);
+                   "object %s\n"
+                   "type %s\n"
+                   "tag %s\n",
+                   sha1_to_hex(sha1), commit_type, t->name);
+       if (tagger)
+               strbuf_addf(&new_data,
+                           "tagger %s\n", tagger);
+       strbuf_addch(&new_data, '\n');
        strbuf_addbuf(&new_data, &msg);
        free(tagger);
 
@@ -2273,7 +2296,7 @@ static void cmd_new_tag(void)
                t->pack_id = pack_id;
 }
 
-static void cmd_reset_branch(void)
+static void parse_reset_branch(void)
 {
        struct branch *b;
        char *sp;
@@ -2293,12 +2316,12 @@ static void cmd_reset_branch(void)
        else
                b = new_branch(sp);
        read_next_command();
-       cmd_from(b);
+       parse_from(b);
        if (command_buf.len > 0)
                unread_command_buf = 1;
 }
 
-static void cmd_checkpoint(void)
+static void parse_checkpoint(void)
 {
        if (object_count) {
                cycle_packfile();
@@ -2309,7 +2332,7 @@ static void cmd_checkpoint(void)
        skip_optional_lf();
 }
 
-static void cmd_progress(void)
+static void parse_progress(void)
 {
        fwrite(command_buf.buf, 1, command_buf.len, stdout);
        fputc('\n', stdout);
@@ -2352,7 +2375,7 @@ static void import_marks(const char *input_file)
        fclose(f);
 }
 
-static int git_pack_config(const char *k, const char *v)
+static int git_pack_config(const char *k, const char *v, void *cb)
 {
        if (!strcmp(k, "pack.depth")) {
                max_depth = git_config_int(k, v);
@@ -2370,18 +2393,18 @@ static int git_pack_config(const char *k, const char *v)
                pack_compression_seen = 1;
                return 0;
        }
-       return git_default_config(k, v);
+       return git_default_config(k, v, cb);
 }
 
 static const char fast_import_usage[] =
-"git-fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
+"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]";
 
 int main(int argc, const char **argv)
 {
        unsigned int i, show_stats = 1;
 
        setup_git_directory();
-       git_config(git_pack_config);
+       git_config(git_pack_config, NULL);
        if (!pack_compression_seen && core_compression_seen)
                pack_compression_level = core_compression_level;
 
@@ -2449,17 +2472,17 @@ int main(int argc, const char **argv)
        set_die_routine(die_nicely);
        while (read_next_command() != EOF) {
                if (!strcmp("blob", command_buf.buf))
-                       cmd_new_blob();
+                       parse_new_blob();
                else if (!prefixcmp(command_buf.buf, "commit "))
-                       cmd_new_commit();
+                       parse_new_commit();
                else if (!prefixcmp(command_buf.buf, "tag "))
-                       cmd_new_tag();
+                       parse_new_tag();
                else if (!prefixcmp(command_buf.buf, "reset "))
-                       cmd_reset_branch();
+                       parse_reset_branch();
                else if (!strcmp("checkpoint", command_buf.buf))
-                       cmd_checkpoint();
+                       parse_checkpoint();
                else if (!prefixcmp(command_buf.buf, "progress "))
-                       cmd_progress();
+                       parse_progress();
                else
                        die("Unsupported command: %s", command_buf.buf);
        }