Add branch --set-upstream
[gitweb.git] / fast-import.c
index ce0cd4e68a4a086f12d576f1fcb8fdf60f466acb..52d33bcba8c5ca834fc944bbb2d47ae14bf2f7b8 100644 (file)
@@ -19,8 +19,8 @@ Format of STDIN stream:
 
   new_commit ::= 'commit' sp ref_str lf
     mark?
-    ('author' sp name sp '<' email '>' sp when lf)?
-    'committer' sp name sp '<' email '>' sp when lf
+    ('author' (sp name)? sp '<' email '>' sp when lf)?
+    'committer' (sp name)? sp '<' email '>' sp when lf
     commit_msg
     ('from' sp committish lf)?
     ('merge' sp committish lf)*
@@ -47,7 +47,7 @@ Format of STDIN stream:
 
   new_tag ::= 'tag' sp tag_str lf
     'from' sp committish lf
-    ('tagger' sp name sp '<' email '>' sp when lf)?
+    ('tagger' (sp name)? sp '<' email '>' sp when lf)?
     tag_msg;
   tag_msg ::= data;
 
@@ -296,6 +296,8 @@ static unsigned long branch_load_count;
 static int failure;
 static FILE *pack_edges;
 static unsigned int show_stats = 1;
+static int global_argc;
+static const char **global_argv;
 
 /* Memory pools */
 static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -320,6 +322,8 @@ static struct object_entry *object_table[1 << 16];
 static struct mark_set *marks;
 static const char *export_marks_file;
 static const char *import_marks_file;
+static int import_marks_file_from_stream;
+static int relative_marks_paths;
 
 /* Our last blob */
 static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };
@@ -355,6 +359,8 @@ static uintmax_t next_mark;
 static struct strbuf new_data = STRBUF_INIT;
 static int seen_data_command;
 
+static void parse_argv(void);
+
 static void write_branch_report(FILE *rpt, struct branch *b)
 {
        fprintf(rpt, "%s:\n", b->name);
@@ -1706,8 +1712,9 @@ static int read_next_command(void)
                                return EOF;
 
                        if (!seen_data_command
-                               && prefixcmp(command_buf.buf, "feature ")) {
-                               seen_data_command = 1;
+                               && prefixcmp(command_buf.buf, "feature ")
+                               && prefixcmp(command_buf.buf, "option ")) {
+                               parse_argv();
                        }
 
                        rc = rc_free;
@@ -2464,9 +2471,29 @@ static void parse_progress(void)
        skip_optional_lf();
 }
 
-static void option_import_marks(const char *marks)
+static char* make_fast_import_path(const char *path)
+{
+       struct strbuf abs_path = STRBUF_INIT;
+
+       if (!relative_marks_paths || is_absolute_path(path))
+               return xstrdup(path);
+       strbuf_addf(&abs_path, "%s/info/fast-import/%s", get_git_dir(), path);
+       return strbuf_detach(&abs_path, NULL);
+}
+
+static void option_import_marks(const char *marks, int from_stream)
 {
-       import_marks_file = xstrdup(marks);
+       if (import_marks_file) {
+               if (from_stream)
+                       die("Only one import-marks command allowed per stream");
+
+               /* read previous mark file */
+               if(!import_marks_file_from_stream)
+                       read_marks();
+       }
+
+       import_marks_file = make_fast_import_path(marks);
+       import_marks_file_from_stream = from_stream;
 }
 
 static void option_date_format(const char *fmt)
@@ -2500,7 +2527,7 @@ static void option_active_branches(const char *branches)
 
 static void option_export_marks(const char *marks)
 {
-       export_marks_file = xstrdup(marks);
+       export_marks_file = make_fast_import_path(marks);
 }
 
 static void option_export_pack_edges(const char *edges)
@@ -2512,41 +2539,39 @@ static void option_export_pack_edges(const char *edges)
                die_errno("Cannot open '%s'", edges);
 }
 
-static void parse_one_option(const char *option)
+static int parse_one_option(const char *option)
 {
-       if (!prefixcmp(option, "date-format=")) {
-               option_date_format(option + 12);
-       } else if (!prefixcmp(option, "max-pack-size=")) {
+       if (!prefixcmp(option, "max-pack-size=")) {
                option_max_pack_size(option + 14);
        } else if (!prefixcmp(option, "depth=")) {
                option_depth(option + 6);
        } else if (!prefixcmp(option, "active-branches=")) {
                option_active_branches(option + 16);
-       } else if (!prefixcmp(option, "import-marks=")) {
-               option_import_marks(option + 13);
-       } else if (!prefixcmp(option, "export-marks=")) {
-               option_export_marks(option + 13);
        } else if (!prefixcmp(option, "export-pack-edges=")) {
                option_export_pack_edges(option + 18);
-       } else if (!prefixcmp(option, "force")) {
-               force_update = 1;
        } else if (!prefixcmp(option, "quiet")) {
                show_stats = 0;
        } else if (!prefixcmp(option, "stats")) {
                show_stats = 1;
        } else {
-               die("Unsupported option: %s", option);
+               return 0;
        }
+
+       return 1;
 }
 
-static int parse_one_feature(const char *feature)
+static int parse_one_feature(const char *feature, int from_stream)
 {
        if (!prefixcmp(feature, "date-format=")) {
                option_date_format(feature + 12);
        } else if (!prefixcmp(feature, "import-marks=")) {
-               option_import_marks(feature + 13);
+               option_import_marks(feature + 13, from_stream);
        } else if (!prefixcmp(feature, "export-marks=")) {
                option_export_marks(feature + 13);
+       } else if (!prefixcmp(feature, "relative-marks")) {
+               relative_marks_paths = 1;
+       } else if (!prefixcmp(feature, "no-relative-marks")) {
+               relative_marks_paths = 0;
        } else if (!prefixcmp(feature, "force")) {
                force_update = 1;
        } else {
@@ -2563,12 +2588,25 @@ static void parse_feature(void)
        if (seen_data_command)
                die("Got feature command '%s' after data command", feature);
 
-       if (parse_one_feature(feature))
+       if (parse_one_feature(feature, 1))
                return;
 
        die("This version of fast-import does not support feature %s.", feature);
 }
 
+static void parse_option(void)
+{
+       char *option = command_buf.buf + 11;
+
+       if (seen_data_command)
+               die("Got option command '%s' after data command", option);
+
+       if (parse_one_option(option))
+               return;
+
+       die("This version of fast-import does not support option: %s", option);
+}
+
 static int git_pack_config(const char *k, const char *v, void *cb)
 {
        if (!strcmp(k, "pack.depth")) {
@@ -2593,6 +2631,32 @@ static int git_pack_config(const char *k, const char *v, void *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]";
 
+static void parse_argv(void)
+{
+       unsigned int i;
+
+       for (i = 1; i < global_argc; i++) {
+               const char *a = global_argv[i];
+
+               if (*a != '-' || !strcmp(a, "--"))
+                       break;
+
+               if (parse_one_option(a + 2))
+                       continue;
+
+               if (parse_one_feature(a + 2, 0))
+                       continue;
+
+               die("unknown option %s", a);
+       }
+       if (i != global_argc)
+               usage(fast_import_usage);
+
+       seen_data_command = 1;
+       if (import_marks_file)
+               read_marks();
+}
+
 int main(int argc, const char **argv)
 {
        unsigned int i;
@@ -2614,18 +2678,8 @@ int main(int argc, const char **argv)
        avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
        marks = pool_calloc(1, sizeof(struct mark_set));
 
-       for (i = 1; i < argc; i++) {
-               const char *a = argv[i];
-
-               if (*a != '-' || !strcmp(a, "--"))
-                       break;
-
-               parse_one_option(a + 2);
-       }
-       if (i != argc)
-               usage(fast_import_usage);
-       if (import_marks_file)
-               read_marks();
+       global_argc = argc;
+       global_argv = argv;
 
        rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
        for (i = 0; i < (cmd_save - 1); i++)
@@ -2650,9 +2704,18 @@ int main(int argc, const char **argv)
                        parse_progress();
                else if (!prefixcmp(command_buf.buf, "feature "))
                        parse_feature();
+               else if (!prefixcmp(command_buf.buf, "option git "))
+                       parse_option();
+               else if (!prefixcmp(command_buf.buf, "option "))
+                       /* ignore non-git options*/;
                else
                        die("Unsupported command: %s", command_buf.buf);
        }
+
+       /* argv hasn't been parsed yet, do so */
+       if (!seen_data_command)
+               parse_argv();
+
        end_packfile();
 
        dump_branches();