{"thread":{"id":"21861","subject":"[PATCH v8 0/7] fast-import: add new feature and option command","startedAt":"2009-12-04T17:06:53Z","lastAt":"2009-12-04T18:09:17Z","messageCount":9,"participants":["Sverre Rabbelier","Daniel Barkalow"],"isPatch":true,"patchVersion":8,"patchTotal":7},"messages":[{"id":"129206","messageId":"1259946420-8845-1-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":null,"subject":"[PATCH v8 0/7] fast-import: add new feature and option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:53Z","receivedAt":"2009-12-04T17:06:53Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"This reroll addressess comments from Shawn and the fast-import\nmailing list. It also adds a new feature, \"relative-marks\", which\nwill be very useful for remote helpers.\n\nApologies for taking so long with the reroll, hopefully this version\nis good for next and I can finish my git-remote-hg work :).\n\nSverre Rabbelier (7):\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: add option command\n      fast-import: test the new option command\n      fast-import: allow for multiple --import-marks= arguments\n      fast-import: add (non-)relative-marks feature\n\n Documentation/git-fast-import.txt |   79 +++++++++\n fast-import.c                     |  317 +++++++++++++++++++++++++++----------\n t/t9300-fast-import.sh            |  152 ++++++++++++++++++\n 3 files changed, 462 insertions(+), 86 deletions(-)\n"},{"id":"129212","messageId":"1259946420-8845-2-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-1-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 1/7] fast-import: put option parsing code in separate functions","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:54Z","receivedAt":"2009-12-04T17:06:54Z","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\tRebased against current master, no other changes.\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 dd3c99d..fcd9e1e 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -295,6 +295,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@@ -2420,7 +2421,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@@ -2455,6 +2456,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@@ -2481,7 +2552,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@@ -2505,44 +2576,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.5.3.164.g07b0c\n"},{"id":"129211","messageId":"1259946420-8845-3-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-2-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 2/7] fast-import: put marks reading in it's own function","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:55Z","receivedAt":"2009-12-04T17:06:55Z","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\nAlso, rename mark_file to export_marks_file as it is now ambiguous.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tRenamed mark_fiel to export_marks_file and added import_marks_file as\n\tper Shawn's comments.\n\n fast-import.c |   93 +++++++++++++++++++++++++++++++-------------------------\n 1 files changed, 51 insertions(+), 42 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex fcd9e1e..0458b03 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -318,7 +318,8 @@ static unsigned int object_entry_alloc = 5000;\n 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 *export_marks_file;\n+static const char *import_marks_file;\n \n /* Our last blob */\n static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };\n@@ -455,8 +456,8 @@ static void write_crash_report(const char *err)\n \tfputc('\\n', rpt);\n \tfputs(\"Marks\\n\", rpt);\n \tfputs(\"-----\\n\", rpt);\n-\tif (mark_file)\n-\t\tfprintf(rpt, \"  exported to %s\\n\", mark_file);\n+\tif (export_marks_file)\n+\t\tfprintf(rpt, \"  exported to %s\\n\", export_marks_file);\n \telse\n \t\tdump_marks_helper(rpt, 0, marks);\n \n@@ -1603,13 +1604,13 @@ static void dump_marks(void)\n \tint mark_fd;\n \tFILE *f;\n \n-\tif (!mark_file)\n+\tif (!export_marks_file)\n \t\treturn;\n \n-\tmark_fd = hold_lock_file_for_update(&mark_lock, mark_file, 0);\n+\tmark_fd = hold_lock_file_for_update(&mark_lock, export_marks_file, 0);\n \tif (mark_fd < 0) {\n \t\tfailure |= error(\"Unable to write marks file %s: %s\",\n-\t\t\tmark_file, strerror(errno));\n+\t\t\texport_marks_file, strerror(errno));\n \t\treturn;\n \t}\n \n@@ -1618,7 +1619,7 @@ static void dump_marks(void)\n \t\tint saved_errno = errno;\n \t\trollback_lock_file(&mark_lock);\n \t\tfailure |= error(\"Unable to write marks file %s: %s\",\n-\t\t\tmark_file, strerror(saved_errno));\n+\t\t\texport_marks_file, strerror(saved_errno));\n \t\treturn;\n \t}\n \n@@ -1634,7 +1635,7 @@ static void dump_marks(void)\n \t\tint saved_errno = errno;\n \t\trollback_lock_file(&mark_lock);\n \t\tfailure |= error(\"Unable to write marks file %s: %s\",\n-\t\t\tmark_file, strerror(saved_errno));\n+\t\t\texport_marks_file, strerror(saved_errno));\n \t\treturn;\n \t}\n \n@@ -1642,11 +1643,47 @@ static void dump_marks(void)\n \t\tint saved_errno = errno;\n \t\trollback_lock_file(&mark_lock);\n \t\tfailure |= error(\"Unable to commit marks file %s: %s\",\n-\t\t\tmark_file, strerror(saved_errno));\n+\t\t\texport_marks_file, strerror(saved_errno));\n \t\treturn;\n \t}\n }\n \n+static void read_marks(void)\n+{\n+\tchar line[512];\n+\tFILE *f = fopen(import_marks_file, \"r\");\n+\tif (!f)\n+\t\tdie_errno(\"cannot read '%s'\", import_marks_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@@ -2421,39 +2458,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+\timport_marks_file = xstrdup(marks);\n }\n \n static void option_date_format(const char *fmt)\n@@ -2487,7 +2494,7 @@ static void option_active_branches(const char *branches)\n \n static void option_export_marks(const char *marks)\n {\n-\tmark_file = xstrdup(marks);\n+\texport_marks_file = xstrdup(marks);\n }\n \n static void option_export_pack_edges(const char *edges)\n@@ -2581,6 +2588,8 @@ int main(int argc, const char **argv)\n \t}\n \tif (i != argc)\n \t\tusage(fast_import_usage);\n+\tif (import_marks_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.5.3.164.g07b0c\n"},{"id":"129209","messageId":"1259946420-8845-4-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-3-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 3/7] fast-import: add feature command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:56Z","receivedAt":"2009-12-04T17:06:56Z","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 four initial feature, date-format=, force=,\nimport-marks=, export-marks=.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tUpdated documentation, reject feature commands after a data command,\n\tas per Shawn's comments. Also factor out parse_one_feature from\n\tparse_feature so that we can re-use it in patch 4/7.\n\n\tThis also has the previous 4/6 squashed in (which added tests)\n\n Documentation/git-fast-import.txt |   25 +++++++++++++\n fast-import.c                     |   38 ++++++++++++++++++++\n t/t9300-fast-import.sh            |   70 +++++++++++++++++++++++++++++++++++++\n 3 files changed, 133 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 288032c..4357c21 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@@ -846,6 +850,27 @@ 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][a-zA-Z-]*$ and should be understood by fast-import.\n+\n+Feature work identical as their option counterparts.\n+\n+The following features are currently supported:\n+\n+* date-format\n+* import-marks\n+* export-marks\n+* force\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 0458b03..ce0cd4e 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -353,6 +353,7 @@ 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 seen_data_command;\n \n static void write_branch_report(FILE *rpt, struct branch *b)\n {\n@@ -1704,6 +1705,11 @@ static int read_next_command(void)\n \t\t\tif (stdin_eof)\n \t\t\t\treturn EOF;\n \n+\t\t\tif (!seen_data_command\n+\t\t\t\t&& prefixcmp(command_buf.buf, \"feature \")) {\n+\t\t\t\tseen_data_command = 1;\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@@ -2533,6 +2539,36 @@ static void parse_one_option(const char *option)\n \t}\n }\n \n+static int parse_one_feature(const char *feature)\n+{\n+\tif (!prefixcmp(feature, \"date-format=\")) {\n+\t\toption_date_format(feature + 12);\n+\t} else if (!prefixcmp(feature, \"import-marks=\")) {\n+\t\toption_import_marks(feature + 13);\n+\t} else if (!prefixcmp(feature, \"export-marks=\")) {\n+\t\toption_export_marks(feature + 13);\n+\t} else if (!prefixcmp(feature, \"force\")) {\n+\t\tforce_update = 1;\n+\t} else {\n+\t\treturn 0;\n+\t}\n+\n+\treturn 1;\n+}\n+\n+static void parse_feature(void)\n+{\n+\tchar *feature = command_buf.buf + 8;\n+\n+\tif (seen_data_command)\n+\t\tdie(\"Got feature command '%s' after data command\", feature);\n+\n+\tif (parse_one_feature(feature))\n+\t\treturn;\n+\n+\tdie(\"This version of fast-import does not support feature %s.\", feature);\n+}\n+\n static int git_pack_config(const char *k, const char *v, void *cb)\n {\n \tif (!strcmp(k, \"pack.depth\")) {\n@@ -2612,6 +2648,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}\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex b49815d..b2c521f 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1254,4 +1254,74 @@ test_expect_success \\\n \t'Q: verify note for third commit' \\\n \t'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'\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+cat >input << EOF\n+blob\n+data 3\n+hi\n+feature date-format=now\n+EOF\n+\n+test_expect_success 'R: abort on receiving feature after data command' '\n+\ttest_must_fail git fast-import <input\n+'\n+\n+cat >input << EOF\n+feature 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 feature 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 import-marks=marks.out\n+feature 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 import-marks=nonexistant.marks\n+feature export-marks=marks.new\n+EOF\n+\n+test_expect_success \\\n+    'R: import marks prefers commandline marks file over the stream' \\\n+    'cat input | git fast-import --import-marks=marks.out &&\n+    test_cmp marks.out marks.new'\n+\n test_done\n-- \n1.6.5.3.164.g07b0c\n"},{"id":"129210","messageId":"1259946420-8845-5-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-4-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 4/7] fast-import: add option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:57Z","receivedAt":"2009-12-04T17:06:57Z","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\nNon-git options are ignored, unrecognised options result in an error.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tReject unknown options, update documentation, and some style fixes.\n\n Documentation/git-fast-import.txt |   32 +++++++++++++\n fast-import.c                     |   87 ++++++++++++++++++++++++++-----------\n 2 files changed, 94 insertions(+), 25 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 4357c21..2d5f533 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+\tSpecify any of the options listed under OPTIONS that do not\n+\tchange stream semantic to suit the frontend's needs. This\n+\tcommand 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@@ -871,6 +876,33 @@ The following features are currently supported:\n * export-marks\n * force\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 that do not change import semantics,\n+without the leading '--' and is 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+The following commandline options change import semantics and may therefore\n+not be passed as option:\n+\n+* date-format\n+* import-marks\n+* export-marks\n+* force\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 ce0cd4e..ab099b6 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -296,6 +296,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@@ -355,6 +357,8 @@ static uintmax_t next_mark;\n static struct strbuf new_data = STRBUF_INIT;\n static int seen_data_command;\n \n+static void parse_argv(void);\n+\n static void write_branch_report(FILE *rpt, struct branch *b)\n {\n \tfprintf(rpt, \"%s:\\n\", b->name);\n@@ -1706,8 +1710,9 @@ static int read_next_command(void)\n \t\t\t\treturn EOF;\n \n \t\t\tif (!seen_data_command\n-\t\t\t\t&& prefixcmp(command_buf.buf, \"feature \")) {\n-\t\t\t\tseen_data_command = 1;\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@@ -2512,31 +2517,25 @@ static void option_export_pack_edges(const char *edges)\n \t\tdie_errno(\"Cannot open '%s'\", edges);\n }\n \n-static void parse_one_option(const char *option)\n+static int 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+\tif (!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\treturn 0;\n \t}\n+\n+\treturn 1;\n }\n \n static int parse_one_feature(const char *feature)\n@@ -2569,6 +2568,19 @@ static void parse_feature(void)\n \tdie(\"This version of fast-import does not support feature %s.\", feature);\n }\n \n+static void parse_option(void)\n+{\n+\tchar *option = command_buf.buf + 11;\n+\n+\tif (seen_data_command)\n+\t\tdie(\"Got option command '%s' after data command\", option);\n+\n+\tif (parse_one_option(option))\n+\t\treturn;\n+\n+\tdie(\"This version of fast-import does not support option: %s\", 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@@ -2593,6 +2605,32 @@ 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\tif (parse_one_option(a + 2))\n+\t\t\tcontinue;\n+\n+\t\tif (parse_one_feature(a + 2))\n+\t\t\tcontinue;\n+\n+\t\tdie(\"unknown option %s\", a);\n+\t}\n+\tif (i != global_argc)\n+\t\tusage(fast_import_usage);\n+\n+\tseen_data_command = 1;\n+\tif (import_marks_file)\n+\t\tread_marks();\n+}\n+\n int main(int argc, const char **argv)\n {\n \tunsigned int i;\n@@ -2614,18 +2652,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 (import_marks_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@@ -2650,9 +2678,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+\t\telse if (!prefixcmp(command_buf.buf, \"option \"))\n+\t\t\t/* ignore non-git options*/;\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_data_command)\n+\t\tparse_argv();\n+\n \tend_packfile();\n \n \tdump_branches();\n-- \n1.6.5.3.164.g07b0c\n"},{"id":"129208","messageId":"1259946420-8845-6-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-5-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 5/7] fast-import: test the new option command","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:58Z","receivedAt":"2009-12-04T17:06:58Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"Test the quiet option and verify that the commandline options\noverride it.\n\nAlso make sure that an unknown option command is rejected and that\nnon-git options are ignored.\n\nLastly, show that unknown options are rejected when parsed on the\ncommandline.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tTests updated to match the new behavior.\n\n t/t9300-fast-import.sh |   37 ++++++++++++++++++++++++++++++++++++-\n 1 files changed, 36 insertions(+), 1 deletions(-)\n\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex b2c521f..74dff11 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1255,7 +1255,7 @@ test_expect_success \\\n \t'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'\n \n ###\n-### series R (feature)\n+### series R (feature and option)\n ###\n \n cat >input <<EOF\n@@ -1324,4 +1324,39 @@ test_expect_success \\\n     'cat input | git fast-import --import-marks=marks.out &&\n     test_cmp marks.out marks.new'\n \n+cat >input << EOF\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+option git non-existing-option\n+EOF\n+\n+test_expect_success 'R: die on unknown option' '\n+    test_must_fail git fast-import <input\n+'\n+\n+test_expect_success 'R: unknown commandline options are rejected' '\\\n+    test_must_fail git fast-import --non-existing-option < /dev/null\n+'\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.5.3.164.g07b0c\n"},{"id":"129213","messageId":"1259946420-8845-7-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-6-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 6/7] fast-import: allow for multiple --import-marks= arguments","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:06:59Z","receivedAt":"2009-12-04T17:06:59Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"The --import-marks= option may be specified multiple times on the\ncommandline and should result in all marks being read in. Only one\nimport-marks feature may be specified in the stream, which is\noverriden by any --import-marks= commandline options.\n\nIf one wishes to specify import-marks files in addition to the one\nspecified in the stream, it is easy to repeat the stream option as a\n--import-marks= commandline option.\n\nAlso verify this behavior with tests.\n\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tNew in this series. Without this it is no longer possible to specify\n\tmultiple --import-marks= options on the commandline.\n\n Documentation/git-fast-import.txt |    8 +++++++-\n fast-import.c                     |   21 ++++++++++++++++-----\n t/t9300-fast-import.sh            |   22 ++++++++++++++++++++++\n 3 files changed, 45 insertions(+), 6 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 2d5f533..752f85c 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -867,7 +867,8 @@ it does not.\n The <feature> part of the command may be any string matching\n ^[a-zA-Z][a-zA-Z-]*$ and should be understood by fast-import.\n \n-Feature work identical as their option counterparts.\n+Feature work identical as their option counterparts with the\n+exception of the import-marks feature, see below.\n \n The following features are currently supported:\n \n@@ -876,6 +877,11 @@ The following features are currently supported:\n * export-marks\n * force\n \n+The import-marks behaves differently from when it is specified as\n+commandline option in that only one \"feature import-marks\" is allowed\n+per stream. Also, any --import-marks= specified on the commandline\n+will override those from the stream (if any).\n+\n `option`\n ~~~~~~~~\n Processes the specified option so that git fast-import behaves in a\ndiff --git a/fast-import.c b/fast-import.c\nindex ab099b6..4c3406e 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -322,6 +322,7 @@ static struct object_entry *object_table[1 << 16];\n static struct mark_set *marks;\n static const char *export_marks_file;\n static const char *import_marks_file;\n+static int import_marks_file_from_stream;\n \n /* Our last blob */\n static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };\n@@ -2469,9 +2470,19 @@ static void parse_progress(void)\n \tskip_optional_lf();\n }\n \n-static void option_import_marks(const char *marks)\n+static void option_import_marks(const char *marks, int from_stream)\n {\n+\tif (import_marks_file) {\n+\t\tif (from_stream)\n+\t\t\tdie(\"Only one import-marks command allowed per stream\");\n+\n+\t\t/* read previous mark file */\n+\t\tif(!import_marks_file_from_stream)\n+\t\t\tread_marks();\n+\t}\n+\n \timport_marks_file = xstrdup(marks);\n+\timport_marks_file_from_stream = from_stream;\n }\n \n static void option_date_format(const char *fmt)\n@@ -2538,12 +2549,12 @@ static int parse_one_option(const char *option)\n \treturn 1;\n }\n \n-static int parse_one_feature(const char *feature)\n+static int parse_one_feature(const char *feature, int from_stream)\n {\n \tif (!prefixcmp(feature, \"date-format=\")) {\n \t\toption_date_format(feature + 12);\n \t} else if (!prefixcmp(feature, \"import-marks=\")) {\n-\t\toption_import_marks(feature + 13);\n+\t\toption_import_marks(feature + 13, from_stream);\n \t} else if (!prefixcmp(feature, \"export-marks=\")) {\n \t\toption_export_marks(feature + 13);\n \t} else if (!prefixcmp(feature, \"force\")) {\n@@ -2562,7 +2573,7 @@ static void parse_feature(void)\n \tif (seen_data_command)\n \t\tdie(\"Got feature command '%s' after data command\", feature);\n \n-\tif (parse_one_feature(feature))\n+\tif (parse_one_feature(feature, 1))\n \t\treturn;\n \n \tdie(\"This version of fast-import does not support feature %s.\", feature);\n@@ -2618,7 +2629,7 @@ static void parse_argv(void)\n \t\tif (parse_one_option(a + 2))\n \t\t\tcontinue;\n \n-\t\tif (parse_one_feature(a + 2))\n+\t\tif (parse_one_feature(a + 2, 0))\n \t\t\tcontinue;\n \n \t\tdie(\"unknown option %s\", a);\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex 74dff11..ba92775 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1286,6 +1286,15 @@ test_expect_success 'R: abort on receiving feature after data command' '\n '\n \n cat >input << EOF\n+feature import-marks=git.marks\n+feature import-marks=git2.marks\n+EOF\n+\n+test_expect_success 'R: only one import-marks feature allowed per stream' '\n+\ttest_must_fail git fast-import <input\n+'\n+\n+cat >input << EOF\n feature export-marks=git.marks\n blob\n mark :1\n@@ -1324,6 +1333,19 @@ test_expect_success \\\n     'cat input | git fast-import --import-marks=marks.out &&\n     test_cmp marks.out marks.new'\n \n+\n+cat >input <<EOF\n+feature import-marks=nonexistant.marks\n+feature export-marks=combined.marks\n+EOF\n+\n+test_expect_success 'R: multiple --import-marks= should be honoured' '\n+    head -n2 marks.out > one.marks &&\n+    tail -n +3 marks.out > two.marks &&\n+    git fast-import --import-marks=one.marks --import-marks=two.marks <input &&\n+    test_cmp marks.out combined.marks\n+'\n+\n cat >input << EOF\n option git quiet\n blob\n-- \n1.6.5.3.164.g07b0c\n"},{"id":"129207","messageId":"1259946420-8845-8-git-send-email-srabbelier@gmail.com","threadId":"21861","inReplyTo":"1259946420-8845-7-git-send-email-srabbelier@gmail.com","subject":"[PATCH v8 7/7] fast-import: add (non-)relative-marks feature","fromName":"Sverre Rabbelier","fromEmail":"srabbelier@gmail.com","sentAt":"2009-12-04T17:07:00Z","receivedAt":"2009-12-04T17:07:00Z","isPatch":true,"sender":{"key":"srabbelier@gmail.com","avatar":"https://avatars.githubusercontent.com/u/3098?v=4"},"body":"After specifying 'feature relative-marks' the paths specified with\n'feature import-marks' and 'feature export-marks' are relative to an\ninternal directory in the current repository.\n\nIn git-fast-import this means that the paths are relative to the\n'.git/info/fast-import' directory. However, other importers may use a\ndifferent location.\n\nAdd 'feature non-relative-marks' to disable this behavior, this way\nit is possible to, for example, specify the import-marks location as\nrelative, and the export-marks location as non-relative.\n\nAlso add tests to verify this behavior.\n\nCc: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n---\n\n\tAs requested by Daniel, it is now possible to have the marks be\n\trelative to a constant directory. We might want to consider making\n\tthis the default at some point.\n\n\tThis patch opens the way for remote-helpers to use the marks feature\n\twithout poluting the work tree, which I think is very important.\n\n Documentation/git-fast-import.txt |   16 ++++++++++++++++\n fast-import.c                     |   19 +++++++++++++++++--\n t/t9300-fast-import.sh            |   25 +++++++++++++++++++++++++\n 3 files changed, 58 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 752f85c..1a63835 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -75,6 +75,20 @@ OPTIONS\n \tset of marks.  If a mark is defined to different values,\n \tthe last file wins.\n \n+--relative-marks::\n+\tAfter specifying --relative-marks= the paths specified\n+\twith --import-marks= and --export-marks= are relative\n+\tto an internal directory in the current repository.\n+\tIn git-fast-import this means that the paths are relative\n+\tto the .git/info/fast-import directory. However, other\n+\timporters may use a different location.\n+\n+--no-relative-marks::\n+\tNegates a previous --relative-marks. Allows for combining\n+\trelative and non-relative marks by interweaving\n+\t--(no-)-relative-marks= with the --(import|export)-marks=\n+\toptions.\n+\n --export-pack-edges=<file>::\n \tAfter creating a packfile, print a line of data to\n \t<file> listing the filename of the packfile and the last\n@@ -875,6 +889,8 @@ The following features are currently supported:\n * date-format\n * import-marks\n * export-marks\n+* relative-marks\n+* no-relative-marks\n * force\n \n The import-marks behaves differently from when it is specified as\ndiff --git a/fast-import.c b/fast-import.c\nindex 4c3406e..8d50a1e 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -323,6 +323,7 @@ static struct mark_set *marks;\n static const char *export_marks_file;\n static const char *import_marks_file;\n static int import_marks_file_from_stream;\n+static int relative_marks_paths;\n \n /* Our last blob */\n static struct last_object last_blob = { STRBUF_INIT, 0, 0, 0 };\n@@ -2470,6 +2471,16 @@ static void parse_progress(void)\n \tskip_optional_lf();\n }\n \n+static char* make_fast_import_path(const char *path)\n+{\n+\tif (!relative_marks_paths || is_absolute_path(path))\n+\t\treturn xstrdup(path);\n+\n+\tstruct strbuf abs_path = STRBUF_INIT;\n+\tstrbuf_addf(&abs_path, \"%s/info/fast-import/%s\", get_git_dir(), path);\n+\treturn strbuf_detach(&abs_path, NULL);\n+}\n+\n static void option_import_marks(const char *marks, int from_stream)\n {\n \tif (import_marks_file) {\n@@ -2481,7 +2492,7 @@ static void option_import_marks(const char *marks, int from_stream)\n \t\t\tread_marks();\n \t}\n \n-\timport_marks_file = xstrdup(marks);\n+\timport_marks_file = make_fast_import_path(marks);\n \timport_marks_file_from_stream = from_stream;\n }\n \n@@ -2516,7 +2527,7 @@ static void option_active_branches(const char *branches)\n \n static void option_export_marks(const char *marks)\n {\n-\texport_marks_file = xstrdup(marks);\n+\texport_marks_file = make_fast_import_path(marks);\n }\n \n static void option_export_pack_edges(const char *edges)\n@@ -2557,6 +2568,10 @@ static int parse_one_feature(const char *feature, int from_stream)\n \t\toption_import_marks(feature + 13, from_stream);\n \t} else if (!prefixcmp(feature, \"export-marks=\")) {\n \t\toption_export_marks(feature + 13);\n+\t} else if (!prefixcmp(feature, \"relative-marks\")) {\n+\t\trelative_marks_paths = 1;\n+\t} else if (!prefixcmp(feature, \"no-relative-marks\")) {\n+\t\trelative_marks_paths = 0;\n \t} else if (!prefixcmp(feature, \"force\")) {\n \t\tforce_update = 1;\n \t} else {\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex ba92775..a1b8c2b 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1346,6 +1346,31 @@ test_expect_success 'R: multiple --import-marks= should be honoured' '\n     test_cmp marks.out combined.marks\n '\n \n+cat >input <<EOF\n+feature relative-marks\n+feature import-marks=relative.in\n+feature export-marks=relative.out\n+EOF\n+\n+test_expect_success 'R: feature relative-marks should be honoured' '\n+    mkdir -p .git/info/fast-import/ &&\n+    cp marks.new .git/info/fast-import/relative.in &&\n+    git fast-import <input &&\n+    test_cmp marks.new .git/info/fast-import/relative.out\n+'\n+\n+cat >input <<EOF\n+feature relative-marks\n+feature import-marks=relative.in\n+feature no-relative-marks\n+feature export-marks=non-relative.out\n+EOF\n+\n+test_expect_success 'R: feature no-relative-marks should be honoured' '\n+    git fast-import <input &&\n+    test_cmp marks.new non-relative.out\n+'\n+\n cat >input << EOF\n option git quiet\n blob\n-- \n1.6.5.3.164.g07b0c\n"},{"id":"129226","messageId":"alpine.LNX.2.00.0912041258280.14365@iabervon.org","threadId":"21861","inReplyTo":"1259946420-8845-8-git-send-email-srabbelier@gmail.com","subject":"Re: [PATCH v8 7/7] fast-import: add (non-)relative-marks feature","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-12-04T18:09:17Z","receivedAt":"2009-12-04T18:09:17Z","isPatch":true,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Fri, 4 Dec 2009, Sverre Rabbelier wrote:\n\n> After specifying 'feature relative-marks' the paths specified with\n> 'feature import-marks' and 'feature export-marks' are relative to an\n> internal directory in the current repository.\n> \n> In git-fast-import this means that the paths are relative to the\n> '.git/info/fast-import' directory. However, other importers may use a\n> different location.\n> \n> Add 'feature non-relative-marks' to disable this behavior, this way\n> it is possible to, for example, specify the import-marks location as\n> relative, and the export-marks location as non-relative.\n> \n> Also add tests to verify this behavior.\n> \n> Cc: Daniel Barkalow <barkalow@iabervon.org>\n> Signed-off-by: Sverre Rabbelier <srabbelier@gmail.com>\n> ---\n> \n> \tAs requested by Daniel, it is now possible to have the marks be\n> \trelative to a constant directory. We might want to consider making\n> \tthis the default at some point.\n> \n> \tThis patch opens the way for remote-helpers to use the marks feature\n> \twithout poluting the work tree, which I think is very important.\n\nI think it would be better to make relative paths be the only available \nmethod, in part because we don't want to polute the work tree, but more \nbecause otherwise scripts aren't transferrable. That is, if you have an \nabsolute path, you can't send the same script to two different importers \n(because they'd have to write their marks to the same location). And \nthere's no way for the program constructing a script to determine a good \nabsolute location if the script may be run on a different host than it's \ngenerated on (think of getting a Linux user getting a script attached to a \nbug report from a native Windows user; there are no absolute paths that \nare valid on both of these).\n\n(However, it probably does make sense to permit absolute paths in the \ncommand line, since whoever's writing the command line is presumably aware \nof any local conventions)\n\n\t-Daniel\n*This .sig left intentionally blank*\n"}]}