{"thread":{"id":"20826","subject":"[PATCH v6 0/6] fast-import: add new feature and mark command","startedAt":"2009-09-02T17:56:57Z","lastAt":"2009-09-04T03:42:26Z","messageCount":10,"participants":["Sverre Rabbelier","Junio C Hamano","Ian Clatworthy"],"isPatch":true,"patchVersion":6,"patchTotal":6},"messages":[{"id":"122316","messageId":"1251914223-31435-1-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":null,"subject":"[PATCH v6 0/6] fast-import: add new feature and mark command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:56:57Z","receivedAt":"2009-09-02T17:56:57Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Incorperated comments and changed 'option foo' to 'option git foo'. I\nthink this is ready to be merged to next if there are no objections.\n\nSverre Rabbelier (6):\n      fast-import: put option parsing code in separate functions\n      fast-import: put marks reading in it's own function\n      fast-import: add feature command\n      fast-import: test the new feature command\n      fast-import: add option command\n      fast-import: test the new option command\n\n Documentation/git-fast-import.txt |   40 ++++++\n fast-import.c                     |  262 ++++++++++++++++++++++++++-----------\n t/t9300-fast-import.sh            |  102 ++++++++++++++\n 3 files changed, 327 insertions(+), 77 deletions(-)\n"},{"id":"122317","messageId":"1251914223-31435-2-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-1-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 1/6] fast-import: put option parsing code in separate functions","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:56:58Z","receivedAt":"2009-09-02T17:56:58Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Putting the options in their own functions increases readability of\nthe option parsing block and makes it easier to reuse the option\nparsing code later on.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n  No change since v5.\n\n fast-import.c |  115 +++++++++++++++++++++++++++++++++++++--------------------\n 1 files changed, 75 insertions(+), 40 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex 7ef9865..b904f20 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -291,6 +291,7 @@ static unsigned long branch_count;\n static unsigned long branch_load_count;\n static int failure;\n static FILE *pack_edges;\n+static unsigned int show_stats = 1;\n \n /* Memory pools */\n static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);\n@@ -2337,7 +2338,7 @@ static void parse_progress(void)\n \tskip_optional_lf();\n }\n \n-static void import_marks(const char *input_file)\n+static void option_import_marks(const char *input_file)\n {\n \tchar line[512];\n \tFILE *f = fopen(input_file, \"r\");\n@@ -2372,6 +2373,76 @@ static void import_marks(const char *input_file)\n \tfclose(f);\n }\n \n+static void option_date_format(const char *fmt)\n+{\n+\tif (!strcmp(fmt, \"raw\"))\n+\t\twhenspec = WHENSPEC_RAW;\n+\telse if (!strcmp(fmt, \"rfc2822\"))\n+\t\twhenspec = WHENSPEC_RFC2822;\n+\telse if (!strcmp(fmt, \"now\"))\n+\t\twhenspec = WHENSPEC_NOW;\n+\telse\n+\t\tdie(\"unknown --date-format argument %s\", fmt);\n+}\n+\n+static void option_max_pack_size(const char *packsize)\n+{\n+\tmax_packsize = strtoumax(packsize, NULL, 0) * 1024 * 1024;\n+}\n+\n+static void option_depth(const char *depth)\n+{\n+\tmax_depth = strtoul(depth, NULL, 0);\n+\tif (max_depth > MAX_DEPTH)\n+\t\tdie(\"--depth cannot exceed %u\", MAX_DEPTH);\n+}\n+\n+static void option_active_branches(const char *branches)\n+{\n+\tmax_active_branches = strtoul(branches, NULL, 0);\n+}\n+\n+static void option_export_marks(const char *marks)\n+{\n+\tmark_file = xstrdup(marks);\n+}\n+\n+static void option_export_pack_edges(const char *edges)\n+{\n+\tif (pack_edges)\n+\t\tfclose(pack_edges);\n+\tpack_edges = fopen(edges, \"a\");\n+\tif (!pack_edges)\n+\t\tdie_errno(\"Cannot open '%s'\", edges);\n+}\n+\n+static void parse_one_option(const char *option)\n+{\n+\tif (!prefixcmp(option, \"date-format=\")) {\n+\t\toption_date_format(option + 12);\n+\t} else if (!prefixcmp(option, \"max-pack-size=\")) {\n+\t\toption_max_pack_size(option + 14);\n+\t} else if (!prefixcmp(option, \"depth=\")) {\n+\t\toption_depth(option + 6);\n+\t} else if (!prefixcmp(option, \"active-branches=\")) {\n+\t\toption_active_branches(option + 16);\n+\t} else if (!prefixcmp(option, \"import-marks=\")) {\n+\t\toption_import_marks(option + 13);\n+\t} else if (!prefixcmp(option, \"export-marks=\")) {\n+\t\toption_export_marks(option + 13);\n+\t} else if (!prefixcmp(option, \"export-pack-edges=\")) {\n+\t\toption_export_pack_edges(option + 18);\n+\t} else if (!prefixcmp(option, \"force\")) {\n+\t\tforce_update = 1;\n+\t} else if (!prefixcmp(option, \"quiet\")) {\n+\t\tshow_stats = 0;\n+\t} else if (!prefixcmp(option, \"stats\")) {\n+\t\tshow_stats = 1;\n+\t} else {\n+\t\tdie(\"Unsupported option: %s\", option);\n+\t}\n+}\n+\n static int git_pack_config(const char *k, const char *v, void *cb)\n {\n \tif (!strcmp(k, \"pack.depth\")) {\n@@ -2398,7 +2469,7 @@ static const char fast_import_usage[] =\n \n int main(int argc, const char **argv)\n {\n-\tunsigned int i, show_stats = 1;\n+\tunsigned int i;\n \n \tgit_extract_argv0_path(argv[0]);\n \n@@ -2419,44 +2490,8 @@ int main(int argc, const char **argv)\n \n \t\tif (*a != '-' || !strcmp(a, \"--\"))\n \t\t\tbreak;\n-\t\telse if (!prefixcmp(a, \"--date-format=\")) {\n-\t\t\tconst char *fmt = a + 14;\n-\t\t\tif (!strcmp(fmt, \"raw\"))\n-\t\t\t\twhenspec = WHENSPEC_RAW;\n-\t\t\telse if (!strcmp(fmt, \"rfc2822\"))\n-\t\t\t\twhenspec = WHENSPEC_RFC2822;\n-\t\t\telse if (!strcmp(fmt, \"now\"))\n-\t\t\t\twhenspec = WHENSPEC_NOW;\n-\t\t\telse\n-\t\t\t\tdie(\"unknown --date-format argument %s\", fmt);\n-\t\t}\n-\t\telse if (!prefixcmp(a, \"--max-pack-size=\"))\n-\t\t\tmax_packsize = strtoumax(a + 16, NULL, 0) * 1024 * 1024;\n-\t\telse if (!prefixcmp(a, \"--depth=\")) {\n-\t\t\tmax_depth = strtoul(a + 8, NULL, 0);\n-\t\t\tif (max_depth > MAX_DEPTH)\n-\t\t\t\tdie(\"--depth cannot exceed %u\", MAX_DEPTH);\n-\t\t}\n-\t\telse if (!prefixcmp(a, \"--active-branches=\"))\n-\t\t\tmax_active_branches = strtoul(a + 18, NULL, 0);\n-\t\telse if (!prefixcmp(a, \"--import-marks=\"))\n-\t\t\timport_marks(a + 15);\n-\t\telse if (!prefixcmp(a, \"--export-marks=\"))\n-\t\t\tmark_file = a + 15;\n-\t\telse if (!prefixcmp(a, \"--export-pack-edges=\")) {\n-\t\t\tif (pack_edges)\n-\t\t\t\tfclose(pack_edges);\n-\t\t\tpack_edges = fopen(a + 20, \"a\");\n-\t\t\tif (!pack_edges)\n-\t\t\t\tdie_errno(\"Cannot open '%s'\", a + 20);\n-\t\t} else if (!strcmp(a, \"--force\"))\n-\t\t\tforce_update = 1;\n-\t\telse if (!strcmp(a, \"--quiet\"))\n-\t\t\tshow_stats = 0;\n-\t\telse if (!strcmp(a, \"--stats\"))\n-\t\t\tshow_stats = 1;\n-\t\telse\n-\t\t\tdie(\"unknown option %s\", a);\n+\n+\t\tparse_one_option(a + 2);\n \t}\n \tif (i != argc)\n \t\tusage(fast_import_usage);\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122321","messageId":"1251914223-31435-3-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-2-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 2/6] fast-import: put marks reading in it's own function","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:56:59Z","receivedAt":"2009-09-02T17:56:59Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"All options do nothing but set settings, with the exception of the\n--input-marks option. Delay the reading of the marks file till after\nall options have been parsed.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n  No change since v5.\n\n fast-import.c |   73 ++++++++++++++++++++++++++++++++-------------------------\n 1 files changed, 41 insertions(+), 32 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex b904f20..812fcf0 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -315,6 +315,7 @@ static struct object_entry_pool *blocks;\n static struct object_entry *object_table[1 << 16];\n static struct mark_set *marks;\n static const char *mark_file;\n+static const char *input_file;\n \n /* Our last blob */\n static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };\n@@ -1643,6 +1644,42 @@ static void dump_marks(void)\n \t}\n }\n \n+static void read_marks(void)\n+{\n+\tchar line[512];\n+\tFILE *f = fopen(input_file, \"r\");\n+\tif (!f)\n+\t\tdie_errno(\"cannot read '%s'\", input_file);\n+\twhile (fgets(line, sizeof(line), f)) {\n+\t\tuintmax_t mark;\n+\t\tchar *end;\n+\t\tunsigned char sha1[20];\n+\t\tstruct object_entry *e;\n+\n+\t\tend = strchr(line, '\\n');\n+\t\tif (line[0] != ':' || !end)\n+\t\t\tdie(\"corrupt mark line: %s\", line);\n+\t\t*end = 0;\n+\t\tmark = strtoumax(line + 1, &end, 10);\n+\t\tif (!mark || end == line + 1\n+\t\t\t|| *end != ' ' || get_sha1(end + 1, sha1))\n+\t\t\tdie(\"corrupt mark line: %s\", line);\n+\t\te = find_object(sha1);\n+\t\tif (!e) {\n+\t\t\tenum object_type type = sha1_object_info(sha1, NULL);\n+\t\t\tif (type < 0)\n+\t\t\t\tdie(\"object not found: %s\", sha1_to_hex(sha1));\n+\t\t\te = insert_object(sha1);\n+\t\t\te->type = type;\n+\t\t\te->pack_id = MAX_PACK_ID;\n+\t\t\te->offset = 1; /* just not zero! */\n+\t\t}\n+\t\tinsert_mark(mark, e);\n+\t}\n+\tfclose(f);\n+}\n+\n+\n static int read_next_command(void)\n {\n \tstatic int stdin_eof = 0;\n@@ -2338,39 +2375,9 @@ static void parse_progress(void)\n \tskip_optional_lf();\n }\n \n-static void option_import_marks(const char *input_file)\n+static void option_import_marks(const char *marks)\n {\n-\tchar line[512];\n-\tFILE *f = fopen(input_file, \"r\");\n-\tif (!f)\n-\t\tdie_errno(\"cannot read '%s'\", input_file);\n-\twhile (fgets(line, sizeof(line), f)) {\n-\t\tuintmax_t mark;\n-\t\tchar *end;\n-\t\tunsigned char sha1[20];\n-\t\tstruct object_entry *e;\n-\n-\t\tend = strchr(line, '\\n');\n-\t\tif (line[0] != ':' || !end)\n-\t\t\tdie(\"corrupt mark line: %s\", line);\n-\t\t*end = 0;\n-\t\tmark = strtoumax(line + 1, &end, 10);\n-\t\tif (!mark || end == line + 1\n-\t\t\t|| *end != ' ' || get_sha1(end + 1, sha1))\n-\t\t\tdie(\"corrupt mark line: %s\", line);\n-\t\te = find_object(sha1);\n-\t\tif (!e) {\n-\t\t\tenum object_type type = sha1_object_info(sha1, NULL);\n-\t\t\tif (type < 0)\n-\t\t\t\tdie(\"object not found: %s\", sha1_to_hex(sha1));\n-\t\t\te = insert_object(sha1);\n-\t\t\te->type = type;\n-\t\t\te->pack_id = MAX_PACK_ID;\n-\t\t\te->offset = 1; /* just not zero! */\n-\t\t}\n-\t\tinsert_mark(mark, e);\n-\t}\n-\tfclose(f);\n+\tinput_file = xstrdup(marks);\n }\n \n static void option_date_format(const char *fmt)\n@@ -2495,6 +2502,8 @@ int main(int argc, const char **argv)\n \t}\n \tif (i != argc)\n \t\tusage(fast_import_usage);\n+\tif (input_file)\n+\t\tread_marks();\n \n \trc_free = pool_alloc(cmd_save * sizeof(*rc_free));\n \tfor (i = 0; i < (cmd_save - 1); i++)\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122318","messageId":"1251914223-31435-4-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-3-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 3/6] fast-import: add feature command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:57:00Z","receivedAt":"2009-09-02T17:57:00Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"This allows the fronted to require a specific feature to be supported\nby the frontend, or abort.\n\nAlso add support for the first feature, date-format=.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n  No longer RFC.\n\n Documentation/git-fast-import.txt |   16 ++++++++++++++++\n fast-import.c                     |   13 +++++++++++++\n 2 files changed, 29 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex c2f483a..1e293f2 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -303,6 +303,10 @@ and control the current import process.  More detailed discussion\n \tstandard output.  This command is optional and is not needed\n \tto perform an import.\n \n+`feature`::\n+\tRequire that fast-import supports the specified feature, or\n+\tabort if it does not.\n+\n `commit`\n ~~~~~~~~\n Create or update a branch with a new commit, recording one logical\n@@ -813,6 +817,18 @@ Placing a `progress` command immediately after a `checkpoint` will\n inform the reader when the `checkpoint` has been completed and it\n can safely access the refs that fast-import updated.\n \n+`feature`\n+~~~~~~~~~\n+Require that fast-import supports the specified feature, or abort if\n+it does not.\n+\n+....\n+\t'feature' SP <feature> LF\n+....\n+\n+The <feature> part of the command may be any string matching\n+[a-zA-Z-] and should be understood by a version of fast-import.\n+\n Crash Reports\n -------------\n If fast-import is supplied invalid input it will terminate with a\ndiff --git a/fast-import.c b/fast-import.c\nindex 812fcf0..9bf06a4 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -2450,6 +2450,17 @@ static void parse_one_option(const char *option)\n \t}\n }\n \n+static void parse_feature(void)\n+{\n+\tchar *feature = command_buf.buf + 8;\n+\n+\tif (!prefixcmp(feature, \"date-format=\")) {\n+\t\toption_date_format(feature + 12);\n+\t} else {\n+\t\tdie(\"This version of fast-import does not support feature %s.\", feature);\n+\t}\n+}\n+\n static int git_pack_config(const char *k, const char *v, void *cb)\n {\n \tif (!strcmp(k, \"pack.depth\")) {\n@@ -2526,6 +2537,8 @@ int main(int argc, const char **argv)\n \t\t\tparse_checkpoint();\n \t\telse if (!prefixcmp(command_buf.buf, \"progress \"))\n \t\t\tparse_progress();\n+\t\telse if (!prefixcmp(command_buf.buf, \"feature \"))\n+\t\t\tparse_feature();\n \t\telse\n \t\t\tdie(\"Unsupported command: %s\", command_buf.buf);\n \t}\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122319","messageId":"1251914223-31435-5-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-4-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 4/6] fast-import: test the new feature command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:57:01Z","receivedAt":"2009-09-02T17:57:01Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Test that an unknown feature causes fast-import to abort, and that a\nknown feature is accepted.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n t/t9300-fast-import.sh |   20 ++++++++++++++++++++\n 1 files changed, 20 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex 821be7c..564ed6b 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1088,4 +1088,24 @@ INPUT_END\n test_expect_success 'P: fail on blob mark in gitlink' '\n     test_must_fail git fast-import <input'\n \n+###\n+### series R (feature)\n+###\n+\n+cat >input <<EOF\n+feature no-such-feature-exists\n+EOF\n+\n+test_expect_success 'R: abort on unsupported feature' '\n+\ttest_must_fail git fast-import <input\n+'\n+\n+cat >input <<EOF\n+feature date-format=now\n+EOF\n+\n+test_expect_success 'R: supported feature is accepted' '\n+\tgit fast-import <input\n+'\n+\n test_done\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122320","messageId":"1251914223-31435-6-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-5-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 5/6] fast-import: add option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:57:02Z","receivedAt":"2009-09-02T17:57:02Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"This allows the frontend to specify any of the supported options as\nlong as no non-option command has been given. This way the\nuser does not have to include any frontend-specific options, but\ninstead she can rely on the frontend to tell fast-import what it\nneeds.\n\nAlso factor out parsing of argv and have it execute when we reach the\nfirst non-option command, or after all commands have been read and\nno non-option command has been encountered.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n  Main difference with v5 is that the syntax is now 'option git ...'\n  as per a discussion with the other fast-import devs. Other options,\n  e.g. 'option hg' are ignored. Also fixed the docs to say that\n  feature commands are allowed before git option commands.\n\n Documentation/git-fast-import.txt |   24 ++++++++++++\n fast-import.c                     |   75 +++++++++++++++++++++++++++++++------\n 2 files changed, 87 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 1e293f2..f1c94b4 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -307,6 +307,11 @@ and control the current import process.  More detailed discussion\n \tRequire that fast-import supports the specified feature, or\n \tabort if it does not.\n \n+`option`::\n+    Specify any of the options listed under OPTIONS to change\n+    fast-import's behavior to suit the frontend's needs. This command\n+    is optional and is not needed to perform an import.\n+\n `commit`\n ~~~~~~~~\n Create or update a branch with a new commit, recording one logical\n@@ -829,6 +834,25 @@ it does not.\n The <feature> part of the command may be any string matching\n [a-zA-Z-] and should be understood by a version of fast-import.\n \n+`option`\n+~~~~~~~~\n+Processes the specified option so that git fast-import behaves in a\n+way that suits the frontend's needs.\n+Note that options specified by the frontend are overridden by any\n+options the user may specify to git fast-import itself.\n+\n+....\n+    'option' SP <option> LF\n+....\n+\n+The `<option>` part of the command may contain any of the options\n+listed in the OPTIONS section, without the leading '--' and is\n+treated in the same way.\n+\n+Option commands must be the first commands on the input (not counting\n+feature commands), to give an option command after any non-option\n+command is an error.\n+\n Crash Reports\n -------------\n If fast-import is supplied invalid input it will terminate with a\ndiff --git a/fast-import.c b/fast-import.c\nindex 9bf06a4..bad93dc 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -292,6 +292,8 @@ static unsigned long branch_load_count;\n static int failure;\n static FILE *pack_edges;\n static unsigned int show_stats = 1;\n+static int global_argc;\n+static const char **global_argv;\n \n /* Memory pools */\n static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);\n@@ -349,6 +351,10 @@ static struct recent_command *rc_free;\n static unsigned int cmd_save = 100;\n static uintmax_t next_mark;\n static struct strbuf new_data = STRBUF_INIT;\n+static int options_enabled;\n+static int seen_non_option_command;\n+\n+static void parse_argv(void);\n \n static void write_branch_report(FILE *rpt, struct branch *b)\n {\n@@ -1700,6 +1706,12 @@ static int read_next_command(void)\n \t\t\tif (stdin_eof)\n \t\t\t\treturn EOF;\n \n+\t\t\tif (!seen_non_option_command\n+\t\t\t\t&& prefixcmp(command_buf.buf, \"feature \")\n+\t\t\t\t&& prefixcmp(command_buf.buf, \"option \")) {\n+\t\t\t\tparse_argv();\n+\t\t\t}\n+\n \t\t\trc = rc_free;\n \t\t\tif (rc)\n \t\t\t\trc_free = rc->next;\n@@ -2456,11 +2468,31 @@ static void parse_feature(void)\n \n \tif (!prefixcmp(feature, \"date-format=\")) {\n \t\toption_date_format(feature + 12);\n+\t} else if (!strcmp(\"git-options\", feature)) {\n+\t\toptions_enabled = 1;\n \t} else {\n \t\tdie(\"This version of fast-import does not support feature %s.\", feature);\n \t}\n }\n \n+static void parse_option(void)\n+{\n+\tchar* option = command_buf.buf + 11;\n+\n+\tif (!options_enabled)\n+\t\tdie(\"Got option command '%s' before options feature'\", option);\n+\n+\tif (seen_non_option_command)\n+\t\tdie(\"Got option command '%s' after non-option command\", option);\n+\n+\tparse_one_option(option);\n+}\n+\n+static void parse_nongit_option(void)\n+{\n+  // do nothing\n+}\n+\n static int git_pack_config(const char *k, const char *v, void *cb)\n {\n \tif (!strcmp(k, \"pack.depth\")) {\n@@ -2485,6 +2517,26 @@ static int git_pack_config(const char *k, const char *v, void *cb)\n static const char fast_import_usage[] =\n \"git fast-import [--date-format=f] [--max-pack-size=n] [--depth=n] [--active-branches=n] [--export-marks=marks.file]\";\n \n+static void parse_argv(void)\n+{\n+\tunsigned int i;\n+\n+\tfor (i = 1; i < global_argc; i++) {\n+\t\tconst char *a = global_argv[i];\n+\n+\t\tif (*a != '-' || !strcmp(a, \"--\"))\n+\t\t\tbreak;\n+\n+\t\tparse_one_option(a + 2);\n+\t}\n+\tif (i != global_argc)\n+\t\tusage(fast_import_usage);\n+\n+\tseen_non_option_command = 1;\n+\tif (input_file)\n+\t\tread_marks();\n+}\n+\n int main(int argc, const char **argv)\n {\n \tunsigned int i;\n@@ -2503,18 +2555,8 @@ int main(int argc, const char **argv)\n \tavail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));\n \tmarks = pool_calloc(1, sizeof(struct mark_set));\n \n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *a = argv[i];\n-\n-\t\tif (*a != '-' || !strcmp(a, \"--\"))\n-\t\t\tbreak;\n-\n-\t\tparse_one_option(a + 2);\n-\t}\n-\tif (i != argc)\n-\t\tusage(fast_import_usage);\n-\tif (input_file)\n-\t\tread_marks();\n+\tglobal_argc = argc;\n+\tglobal_argv = argv;\n \n \trc_free = pool_alloc(cmd_save * sizeof(*rc_free));\n \tfor (i = 0; i < (cmd_save - 1); i++)\n@@ -2539,9 +2581,18 @@ int main(int argc, const char **argv)\n \t\t\tparse_progress();\n \t\telse if (!prefixcmp(command_buf.buf, \"feature \"))\n \t\t\tparse_feature();\n+\t\telse if (!prefixcmp(command_buf.buf, \"option git \"))\n+\t\t\tparse_option();\n+    else if (!prefixcmp(command_buf.buf, \"option \"))\n+      parse_nongit_option();\n \t\telse\n \t\t\tdie(\"Unsupported command: %s\", command_buf.buf);\n \t}\n+\n+\t// argv hasn't been parsed yet, do so\n+\tif (!seen_non_option_command)\n+\t\tparse_argv();\n+\n \tend_packfile();\n \n \tdump_branches();\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122322","messageId":"1251914223-31435-7-git-send-email-srabbelier@gmail.com","threadId":"20826","inReplyTo":"1251914223-31435-6-git-send-email-srabbelier@gmail.com","subject":"[PATCH v6 6/6] fast-import: test the new option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-02T17:57:03Z","receivedAt":"2009-09-02T17:57:03Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Test three options (quiet and import/export-marks) and verify that the\ncommandline options override these.\n\nAlso make sure that a option command without a preceeding feature\ngit-options command is rejected and that non-git options are ignored.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n  Tests updated to match the new 'option git' syntax. Also added a\n  test to ensure that an option command without a preceeding 'feature\n  git-options' is rejected and that non-git options are ignored.\n\n t/t9300-fast-import.sh |   84 +++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 83 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex 564ed6b..fb795bb 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1089,7 +1089,7 @@ test_expect_success 'P: fail on blob mark in gitlink' '\n     test_must_fail git fast-import <input'\n \n ###\n-### series R (feature)\n+### series R (feature and option)\n ###\n \n cat >input <<EOF\n@@ -1108,4 +1108,86 @@ test_expect_success 'R: supported feature is accepted' '\n \tgit fast-import <input\n '\n \n+cat >input << EOF\n+feature git-options\n+option git quiet\n+blob\n+data 3\n+hi\n+\n+EOF\n+\n+touch empty\n+\n+test_expect_success 'R: quiet option results in no stats being output' '\n+    cat input | git fast-import 2> output &&\n+    test_cmp empty output\n+'\n+\n+cat >input << EOF\n+feature git-options\n+option git export-marks=git.marks\n+blob\n+mark :1\n+data 3\n+hi\n+\n+EOF\n+\n+test_expect_success \\\n+    'R: export-marks option results in a marks file being created' \\\n+    'cat input | git fast-import &&\n+    grep :1 git.marks'\n+\n+test_expect_success \\\n+    'R: export-marks options can be overriden by commandline options' \\\n+    'cat input | git fast-import --export-marks=other.marks &&\n+    grep :1 other.marks'\n+\n+cat >input << EOF\n+feature git-options\n+option git import-marks=marks.out\n+option git export-marks=marks.new\n+EOF\n+\n+test_expect_success \\\n+    'R: import to output marks works without any content' \\\n+    'cat input | git fast-import &&\n+    test_cmp marks.out marks.new'\n+\n+cat >input <<EOF\n+feature git-options\n+option git import-marks=nonexistant.marks\n+option git export-marks=marks.new\n+EOF\n+\n+test_expect_success \\\n+    'R: import marks uses the commandline marks file when the stream specifies one' \\\n+    'cat input | git fast-import --import-marks=marks.out &&\n+    test_cmp marks.out marks.new'\n+\n+cat >input <<EOF\n+feature git-options\n+EOF\n+\n+test_expect_success 'R: feature option is accepted' '\n+\t  git fast-import <input\n+'\n+\n+cat >input <<EOF\n+option git quiet\n+EOF\n+\n+test_expect_success \\\n+    'R: option without preceeding feature command is rejected' \\\n+    'test_must_fail git fast-import <input'\n+\n+cat >input <<EOF\n+option non-existing-vcs non-existing-option\n+EOF\n+\n+test_expect_success 'R: ignore non-git options' '\n+    git fast-import <input\n+'\n+\n test_done\n-- \n1.6.4.16.g72c66.dirty\n"},{"id":"122340","messageId":"7vskf4px6j.fsf@alter.siamese.dyndns.org","threadId":"20826","inReplyTo":"1251914223-31435-6-git-send-email-srabbelier@gmail.com","subject":"Re: [PATCH v6 5/6] fast-import: add option command","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-09-03T02:41:08Z","receivedAt":"2009-09-03T02:41:08Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Sverre Rabbelier <srabbelier@gmail.com> writes:\n\n>   Main difference with v5 is that the syntax is now 'option git ...'\n>   as per a discussion with the other fast-import devs. Other options,\n>   e.g. 'option hg' are ignored. Also fixed the docs to say that\n>   feature commands are allowed before git option commands.\n\nPerhaps the other people have discussed and thought about this much deeper\nthan I have after seeing the above description, but what should the\nsemantics be when you see unknown options?\n\nIf \"option git something-unknown\" is given, it is clear that the tool that\ngenerated the stream assumed that such an option exists in the importer;\nit might appear prudent to abort the operation.\n\nBut what about \"option hg something\"?\n\nIt is an indication that the stream is meant to be used with the named\noption if fed to Hg, but it does not say anything about what should happen\nwhen used with other systems.  If older versions of Hg that do not grok\nthe given option is expected to abort because they won't be able to change\nthe behaviour to obey the optional semantics demanded by the \"option hg\nsomething\", what should the other VCS do?\n\nWorrying about the above would be unnecessary, if you declare that it is\n*entirely* optional to understand and obey \"option\", and ignoring them\ndoes not result in a corrupt import at all.  I think that is the intent\nbehind \"option\", as opposed to \"feature\", and is consistent with the fact\nthat the command line options can override the in-stream settings.  In\nother words, any in-stream instruction that changes the semantics of\nstream to render it dangerous to be processed by older version of tools\nwould be expressed with \"feature\", not with \"option\".\n\nIf that is the sensible thing to do, then we obviously should ignore\n\"option hg anything\", but at the same time we should ignore \"option git\nwe-do-not-know-what-it-does\".\n\nBut then, the call to die(\"Unsupported option: %s\", option) at the end of\nparse_one_option() is wrong, isn't it?\n\nI think at least the function should be made conditional to die() if it\nwas called from parse_argv() but simply ignore unknown if it was called\nfrom the input stream.\n\n> diff --git a/fast-import.c b/fast-import.c\n> index 9bf06a4..bad93dc 100644\n> --- a/fast-import.c\n> +++ b/fast-import.c\n> @@ -2456,11 +2468,31 @@ static void parse_feature(void)\n>  \n>  \tif (!prefixcmp(feature, \"date-format=\")) {\n>  \t\toption_date_format(feature + 12);\n> +\t} else if (!strcmp(\"git-options\", feature)) {\n> +\t\toptions_enabled = 1;\n>  \t} else {\n>  \t\tdie(\"This version of fast-import does not support feature %s.\", feature);\n>  \t}\n>  }\n>  \n> +static void parse_option(void)\n> +{\n> +\tchar* option = command_buf.buf + 11;\n\nERROR: \"foo* bar\" should be \"foo *bar\"\n\n> +\n> +\tif (!options_enabled)\n> +\t\tdie(\"Got option command '%s' before options feature'\", option);\n> +\n> +\tif (seen_non_option_command)\n> +\t\tdie(\"Got option command '%s' after non-option command\", option);\n> +\n> +\tparse_one_option(option);\n> +}\n> +\n> +static void parse_nongit_option(void)\n> +{\n> +  // do nothing\n\nERROR: do not use C99 // comments\n\n> @@ -2539,9 +2581,18 @@ int main(int argc, const char **argv)\n>  \t\t\tparse_progress();\n>  \t\telse if (!prefixcmp(command_buf.buf, \"feature \"))\n>  \t\t\tparse_feature();\n> +\t\telse if (!prefixcmp(command_buf.buf, \"option git \"))\n> +\t\t\tparse_option();\n> +    else if (!prefixcmp(command_buf.buf, \"option \"))\n> +      parse_nongit_option();\n>  \t\telse\n>  \t\t\tdie(\"Unsupported command: %s\", command_buf.buf);\n>  \t}\n> +\n> +\t// argv hasn't been parsed yet, do so\n\nERROR: do not use C99 // comments\n"},{"id":"122341","messageId":"fabb9a1e0909022155r254c41c6s9ed962313c241e9@mail.gmail.com","threadId":"20826","inReplyTo":"7vskf4px6j.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v6 5/6] fast-import: add option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-09-03T04:55:38Z","receivedAt":"2009-09-03T04:55:38Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Sep 3, 2009 at 04:41, Junio C Hamano<gitster@pobox.com> wrote:\n> If \"option git something-unknown\" is given, it is clear that the tool that\n> generated the stream assumed that such an option exists in the importer;\n> it might appear prudent to abort the operation.\n>\n> But what about \"option hg something\"?\n\nI think we should assume that if we see 'option not-us foo' without a\npreceeding 'feature not-us-option', the frontend does not require us\nto understand the option (perhaps because they also specify 'option\ngit foo'.\n\n> If that is the sensible thing to do, then we obviously should ignore\n> \"option hg anything\", but at the same time we should ignore \"option git\n> we-do-not-know-what-it-does\".\n\nPerhaps, frontends could then use 'feature git-quiet-option' if it\nwants to make sure it is supported.\n\n> I think at least the function should be made conditional to die() if it\n> was called from parse_argv() but simply ignore unknown if it was called\n> from the input stream.\n\nMakes sense, what do the fast-import devs think?\n\n>> +static void parse_option(void)\n>> +{\n>> +     char* option = command_buf.buf + 11;\n>\n> ERROR: \"foo* bar\" should be \"foo *bar\"\n\nAh, I thought I had fixed all of those, apologies.\n\n> ERROR: do not use C99 // comments\n> ERROR: do not use C99 // comments\n\nWill fix in the next version (after we decide on what to do with\nunknown git options).\n\n-- \nCheers,\n\nSverre Rabbelier\n"},{"id":"122386","messageId":"4AA08CA2.4060702@canonical.com","threadId":"20826","inReplyTo":"fabb9a1e0909022155r254c41c6s9ed962313c241e9@mail.gmail.com","subject":"Re: [PATCH v6 5/6] fast-import: add option command","fromName":"Ian Clatworthy","fromEmail":"ian.clatworthy@canonical.com","sentAt":"2009-09-04T03:42:26Z","receivedAt":"2009-09-04T03:42:26Z","isPatch":true,"sender":{"key":"ian.clatworthy@canonical.com","avatar":null},"body":"Sverre Rabbelier wrote:\n> Heya,\n> \n> On Thu, Sep 3, 2009 at 04:41, Junio C Hamano<gitster@pobox.com> wrote:\n\n>> I think at least the function should be made conditional to die() if it\n>> was called from parse_argv() but simply ignore unknown if it was called\n>> from the input stream.\n> \n> Makes sense, what do the fast-import devs think?\n\nSounds ok to me.\n\nIan C.\n"}]}