Add branch --set-upstream
[gitweb.git] / fast-import.c
index 0458b03a2a45d7c16335d83b93dba1c33a6766b7..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 };
@@ -353,6 +357,9 @@ static struct recent_command *rc_free;
 static unsigned int cmd_save = 100;
 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)
 {
@@ -1704,6 +1711,12 @@ static int read_next_command(void)
                        if (stdin_eof)
                                return EOF;
 
+                       if (!seen_data_command
+                               && prefixcmp(command_buf.buf, "feature ")
+                               && prefixcmp(command_buf.buf, "option ")) {
+                               parse_argv();
+                       }
+
                        rc = rc_free;
                        if (rc)
                                rc_free = rc->next;
@@ -2458,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)
 {
-       import_marks_file = xstrdup(marks);
+       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)
+{
+       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)
@@ -2494,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)
@@ -2506,31 +2539,72 @@ 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, int from_stream)
+{
+       if (!prefixcmp(feature, "date-format=")) {
+               option_date_format(feature + 12);
+       } else if (!prefixcmp(feature, "import-marks=")) {
+               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 {
+               return 0;
+       }
+
+       return 1;
+}
+
+static void parse_feature(void)
+{
+       char *feature = command_buf.buf + 8;
+
+       if (seen_data_command)
+               die("Got feature command '%s' after data command", 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)
@@ -2557,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;
@@ -2578,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++)
@@ -2612,9 +2702,20 @@ int main(int argc, const char **argv)
                        parse_checkpoint();
                else if (!prefixcmp(command_buf.buf, "progress "))
                        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();