{"thread":{"id":"20760","subject":"[PATCH v5a 0/6] add new feature and option command","startedAt":"2009-08-27T18:40:25Z","lastAt":"2009-08-27T19:37:48Z","messageCount":9,"participants":["Sverre Rabbelier","Teemu Likonen"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"121894","messageId":"1251398431-12461-1-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":null,"subject":"[PATCH v5a 0/6] add new feature and option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:25Z","receivedAt":"2009-08-27T18:40:25Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Apologies for the borked v5.\n\nThis is a reroll of sr/gfi-options to include suggestions from an\noff-list discussion about the fast-import format.\n\nReworked the series (compared to v4) to introduce a 'feature' command\nfirst, and use that in the new 'option' series.\n\nSverre Rabbelier (6):\n      fast-import: put option parsing code in seperate 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 |   39 ++++++\n fast-import.c                     |  255 ++++++++++++++++++++++++++-----------\n t/t9300-fast-import.sh            |   86 +++++++++++++\n 3 files changed, 303 insertions(+), 77 deletions(-)\n"},{"id":"121895","messageId":"1251398431-12461-2-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-1-git-send-email-srabbelier@gmail.com","subject":"[PATCH v5a 1/6] fast-import: put option parsing code in seperate functions","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:26Z","receivedAt":"2009-08-27T18:40:26Z","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\tUnchanged since v4/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.122.g6ffd7\n"},{"id":"121896","messageId":"1251398431-12461-3-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-2-git-send-email-srabbelier@gmail.com","subject":"[PATCH v5a 2/6] fast-import: put marks reading in it's own function","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:27Z","receivedAt":"2009-08-27T18:40:27Z","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\tUnchanged from v4/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.122.g6ffd7\n"},{"id":"121897","messageId":"1251398431-12461-4-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-3-git-send-email-srabbelier@gmail.com","subject":"[RFC PATCH v5a 3/6] fast-import: add feature command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:28Z","receivedAt":"2009-08-27T18:40:28Z","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\tNew in this series, currently RFC. This should make it easier\n\tfor frontends to specify their needs.\n\n\tAlso fixed from line.\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.122.g6ffd7\n"},{"id":"121898","messageId":"1251398431-12461-5-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-4-git-send-email-srabbelier@gmail.com","subject":"[RFC PATCH v5a 4/6] fast-import: test the new feature command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:29Z","receivedAt":"2009-08-27T18:40:29Z","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\n\tNew in this series, nothing special here\n\n\tAlso fixed from line.\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..a5b9b38 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 Q (feature)\n+###\n+\n+cat >input <<EOF\n+feature no-such-feature-exists\n+EOF\n+\n+test_expect_success 'Q: 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 'Q: supported feature is accepted' '\n+\tgit fast-import <input\n+'\n+\n test_done\n-- \n1.6.4.122.g6ffd7\n"},{"id":"121899","messageId":"1251398431-12461-6-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-5-git-send-email-srabbelier@gmail.com","subject":"[PATCH v5a 5/6] fast-import: add option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:30Z","receivedAt":"2009-08-27T18:40:30Z","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\tSimilar to v4, but now requires that the 'feature git-options'\n\tcommand is seen before any 'option' command.\n\n\tDifference from v5 is adding of prefixcmp feature.\n\n Documentation/git-fast-import.txt |   23 ++++++++++++\n fast-import.c                     |   68 ++++++++++++++++++++++++++++++------\n 2 files changed, 79 insertions(+), 12 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 1e293f2..4ba62f3 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,24 @@ 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, to give an\n+option command after any non-option 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..334dd4f 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,26 @@ 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 + 7;\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 int git_pack_config(const char *k, const char *v, void *cb)\n {\n \tif (!strcmp(k, \"pack.depth\")) {\n@@ -2485,6 +2512,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 +2550,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 +2576,16 @@ 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 \"))\n+\t\t\tparse_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.122.g6ffd7\n"},{"id":"121900","messageId":"1251398431-12461-7-git-send-email-srabbelier@gmail.com","threadId":"20760","inReplyTo":"1251398431-12461-6-git-send-email-srabbelier@gmail.com","subject":"[PATCH v5a 6/6] fast-import: test the new option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T18:40:31Z","receivedAt":"2009-08-27T18:40:31Z","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\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tOnly difference from v4 is that it is rebased and a new test to\n\tverify that 'feature git-options' is now accepted.\n\n t/t9300-fast-import.sh |   68 +++++++++++++++++++++++++++++++++++++++++++++++-\n 1 files changed, 67 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex a5b9b38..1fbfc5e 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 Q (feature)\n+### series Q (feature and option)\n ###\n \n cat >input <<EOF\n@@ -1108,4 +1108,70 @@ test_expect_success 'Q: supported feature is accepted' '\n \tgit fast-import <input\n '\n \n+cat >input << EOF\n+feature git-options\n+option quiet\n+blob\n+data 3\n+hi\n+\n+EOF\n+\n+touch empty\n+\n+test_expect_success 'Q: 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 export-marks=git.marks\n+blob\n+mark :1\n+data 3\n+hi\n+\n+EOF\n+\n+test_expect_success \\\n+    'Q: 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+    'Q: 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 import-marks=marks.out\n+option export-marks=marks.new\n+EOF\n+\n+test_expect_success \\\n+    'Q: 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 import-marks=nonexistant.marks\n+option export-marks=marks.new\n+EOF\n+\n+test_expect_success \\\n+    'Q: 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 'Q: feature option is accepted' '\n+\tgit fast-import <input\n+'\n+\n test_done\n-- \n1.6.4.122.g6ffd7\n"},{"id":"121903","messageId":"87y6p5xf5x.fsf@iki.fi","threadId":"20760","inReplyTo":"1251398431-12461-2-git-send-email-srabbelier@gmail.com","subject":"Re: [PATCH v5a 1/6] fast-import: put option parsing code in seperate functions","fromName":"Teemu Likonen","fromEmail":"tlikonen@iki.fi","sentAt":"2009-08-27T18:52:42Z","receivedAt":"2009-08-27T18:52:42Z","isPatch":true,"sender":{"key":"tlikonen@iki.fi","avatar":null},"body":"On 2009-08-27 11:40 (-0700), Sverre Rabbelier wrote:\n\n> Putting the options in their own functions increases readability of\n> the option parsing block and makes it easier to reuse the option\n> parsing code later on.\n>\n> Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n\nTypo in the title:\n\n    fast-import: put option parsing code in seperate functions\n                                               ^\n\n\"separate\"\n"},{"id":"121905","messageId":"fabb9a1e0908271237n3bb89193t971adbf35247ed4@mail.gmail.com","threadId":"20760","inReplyTo":"87y6p5xf5x.fsf@iki.fi","subject":"Re: [PATCH v5a 1/6] fast-import: put option parsing code in seperate functions","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-08-27T19:37:48Z","receivedAt":"2009-08-27T19:37:48Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Heya,\n\nOn Thu, Aug 27, 2009 at 11:52, Teemu Likonen<tlikonen@iki.fi> wrote:\n>    fast-import: put option parsing code in seperate functions\n\nThanks, fixed.\n\n-- \nCheers,\n\nSverre Rabbelier\n"}]}