{"thread":{"id":"35197","subject":"[BUG] \"git --literal-pathspecs blame\" broken in master","startedAt":"2013-10-25T03:49:47Z","lastAt":"2013-10-26T06:39:12Z","messageCount":8,"participants":["Jeff King","Duy Nguyen","Nguyễn Thái Ngọc Duy"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"229465","messageId":"20131025034947.GA4959@sigill.intra.peff.net","threadId":"35197","inReplyTo":null,"subject":"[BUG] \"git --literal-pathspecs blame\" broken in master","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-25T03:49:47Z","receivedAt":"2013-10-25T03:49:47Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"There seems to be a bad interaction with --literal-pathspecs and the\npathspec magic that is in master. Here's an example:\n\n  [setup]\n  $ git init\n  $ echo content >':(foo)bar'\n  $ git add . && git commit -m foo\n\n  [with git v1.8.4]\n  $ git blame ':(foo)bar'\n  ^6b07eb4 (Jeff King 2013-10-24 22:59:02 -0400 1) content\n  $ git --literal-pathspecs blame ':(foo)bar'\n  ^6b07eb4 (Jeff King 2013-10-24 22:59:02 -0400 1) content\n\nSo originally \"blame\" did not handle pathspec magic at all, and\n--literal-pathspecs did nothing. So the former is arguably buggy, but\nthe latter did the right thing (if only by accident :) ).\n\nThen along came 9a08727 (remove init_pathspec() in favor of\nparse_pathspec(), 2013-07-14), and we get:\n\n  $ git blame ':(foo)bar'\n  fatal: Invalid pathspec magic 'foo' in ':(foo)bar'\n  $ git --literal-pathspecs blame ':(foo)bar'\n  fatal: Invalid pathspec magic 'foo' in ':(foo)bar'\n\nThe first is an improvement, because we are now consistent with other\npathspec handling in git. But the latter is a regression; we are not\nrespecting the literal pathspec flag.\n\nWe get another change with a16bf9d (pathspec: make --literal-pathspecs\ndisable pathspec magic, 2013-07-14), which I would think would fix\nthings, but doesn't.\n\n  $ git blame ':(foo)bar'\n  fatal: Invalid pathspec magic 'foo' in ':(foo)bar'\n  $ git --literal-pathspecs blame ':(foo)bar'\n  fatal: :(foo)bar: pathspec magic not supported by this command: 'literal'\n\nThe first one remains good, but the second one is still broken. I\nhaven't dug further yet, but I thought it might be a bit more obvious to\nyou.\n\n-Peff\n"},{"id":"229466","messageId":"20131025040436.GA11810@sigill.intra.peff.net","threadId":"35197","inReplyTo":"20131025034947.GA4959@sigill.intra.peff.net","subject":"Re: [BUG] \"git --literal-pathspecs blame\" broken in master","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-25T04:04:36Z","receivedAt":"2013-10-25T04:04:36Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Oct 24, 2013 at 11:49:47PM -0400, Jeff King wrote:\n\n> We get another change with a16bf9d (pathspec: make --literal-pathspecs\n> disable pathspec magic, 2013-07-14), which I would think would fix\n> things, but doesn't.\n> \n>   $ git blame ':(foo)bar'\n>   fatal: Invalid pathspec magic 'foo' in ':(foo)bar'\n>   $ git --literal-pathspecs blame ':(foo)bar'\n>   fatal: :(foo)bar: pathspec magic not supported by this command: 'literal'\n> \n> The first one remains good, but the second one is still broken. I\n> haven't dug further yet, but I thought it might be a bit more obvious to\n> you.\n\nHmm. Is the fix as simple as:\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 56e3d6b..1c2b303 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -408,7 +408,7 @@ static struct origin *find_origin(struct scoreboard *sb,\n \tpaths[0] = origin->path;\n \tpaths[1] = NULL;\n \n-\tparse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", paths);\n+\tparse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL, 0, \"\", paths);\n \tdiff_setup_done(&diff_opts);\n \n \tif (is_null_sha1(origin->commit->object.sha1))\n\nAll of the GUARD_PATHSPEC calls indicate that everybody understands\nPATHSPEC_LITERAL. It is not technically true that git-blame understands\nthe literal pathspec magic:\n\n  $ git blame -- ':(literal)revision.c'\n  fatal: no such path ':(literal)revision.c' in HEAD\n\nbut that is a separate bug (that blame considers the argument as a path\nfirst before feeding it to the pathspec machinery). The patch above does\nnot fix that, but AFAICT it does not make anything worse.\n\n-Peff\n"},{"id":"229467","messageId":"CACsJy8AYS8VLuuZ_4rVvrG8SV_aq8dtNa0TqfcjEmow05RSP_A@mail.gmail.com","threadId":"35197","inReplyTo":"20131025034947.GA4959@sigill.intra.peff.net","subject":"Re: [BUG] \"git --literal-pathspecs blame\" broken in master","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-25T04:11:21Z","receivedAt":"2013-10-25T04:11:21Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Oct 25, 2013 at 10:49 AM, Jeff King <peff@peff.net> wrote:\n>   $ git --literal-pathspecs blame ':(foo)bar'\n>   fatal: :(foo)bar: pathspec magic not supported by this command: 'literal'\n>\n> The first one remains good, but the second one is still broken. I\n> haven't dug further yet, but I thought it might be a bit more obvious to\n> you.\n\nI checked it too strict. Something like this should fix it. I'll post\na patch with tests later\n\ndiff --git a/pathspec.c b/pathspec.c\nindex ad1a9f5..69e4fdb 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -405,7 +405,7 @@ void parse_pathspec(struct pathspec *pathspec,\n                item[i].magic = prefix_pathspec(item + i, &short_magic,\n                                                argv + i, flags,\n                                                prefix, prefixlen, entry);\n-               if (item[i].magic & magic_mask)\n+               if (item[i].magic & (magic_mask & ~PATHSPEC_LITERAL))\n                        unsupported_magic(entry,\n                                          item[i].magic & magic_mask,\n                                          short_magic);\n\n-- \nDuy\n"},{"id":"229468","messageId":"CACsJy8Aw9KyeWqgC5KQmqPrzD7J4Gga1ibDTvfNQFaVN303U9g@mail.gmail.com","threadId":"35197","inReplyTo":"20131025040436.GA11810@sigill.intra.peff.net","subject":"Re: [BUG] \"git --literal-pathspecs blame\" broken in master","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-25T04:16:08Z","receivedAt":"2013-10-25T04:16:08Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Fri, Oct 25, 2013 at 11:04 AM, Jeff King <peff@peff.net> wrote:\n> On Thu, Oct 24, 2013 at 11:49:47PM -0400, Jeff King wrote:\n>\n>> We get another change with a16bf9d (pathspec: make --literal-pathspecs\n>> disable pathspec magic, 2013-07-14), which I would think would fix\n>> things, but doesn't.\n>>\n>>   $ git blame ':(foo)bar'\n>>   fatal: Invalid pathspec magic 'foo' in ':(foo)bar'\n>>   $ git --literal-pathspecs blame ':(foo)bar'\n>>   fatal: :(foo)bar: pathspec magic not supported by this command: 'literal'\n>>\n>> The first one remains good, but the second one is still broken. I\n>> haven't dug further yet, but I thought it might be a bit more obvious to\n>> you.\n>\n> Hmm. Is the fix as simple as:\n>\n> diff --git a/builtin/blame.c b/builtin/blame.c\n> index 56e3d6b..1c2b303 100644\n> --- a/builtin/blame.c\n> +++ b/builtin/blame.c\n> @@ -408,7 +408,7 @@ static struct origin *find_origin(struct scoreboard *sb,\n>         paths[0] = origin->path;\n>         paths[1] = NULL;\n>\n> -       parse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", paths);\n> +       parse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL, 0, \"\", paths);\n>         diff_setup_done(&diff_opts);\n>\n>         if (is_null_sha1(origin->commit->object.sha1))\n>\n> All of the GUARD_PATHSPEC calls indicate that everybody understands\n> PATHSPEC_LITERAL. It is not technically true that git-blame understands\n> the literal pathspec magic:\n>\n>   $ git blame -- ':(literal)revision.c'\n>   fatal: no such path ':(literal)revision.c' in HEAD\n>\n> but that is a separate bug (that blame considers the argument as a path\n> first before feeding it to the pathspec machinery). The patch above does\n> not fix that, but AFAICT it does not make anything worse.\n\nI did consider this change but dropped it because there are more\nparse_pathspec() calls with PATHSPEC_ALL_MAGIC as mask. Thanks for\nbringing up \":(literal)\".  I guess we need to change prefix_pathspec()\nto set PATHSPEC_LITERAL only when :(literal) is present, not when\n--literal-pathspecs is used.\n-- \nDuy\n"},{"id":"229469","messageId":"20131025041837.GA17266@sigill.intra.peff.net","threadId":"35197","inReplyTo":"CACsJy8Aw9KyeWqgC5KQmqPrzD7J4Gga1ibDTvfNQFaVN303U9g@mail.gmail.com","subject":"Re: [BUG] \"git --literal-pathspecs blame\" broken in master","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-25T04:18:37Z","receivedAt":"2013-10-25T04:18:37Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Oct 25, 2013 at 11:16:08AM +0700, Nguyen Thai Ngoc Duy wrote:\n\n> > All of the GUARD_PATHSPEC calls indicate that everybody understands\n> > PATHSPEC_LITERAL. It is not technically true that git-blame understands\n> > the literal pathspec magic:\n> >\n> >   $ git blame -- ':(literal)revision.c'\n> >   fatal: no such path ':(literal)revision.c' in HEAD\n> >\n> > but that is a separate bug (that blame considers the argument as a path\n> > first before feeding it to the pathspec machinery). The patch above does\n> > not fix that, but AFAICT it does not make anything worse.\n> \n> I did consider this change but dropped it because there are more\n> parse_pathspec() calls with PATHSPEC_ALL_MAGIC as mask. Thanks for\n> bringing up \":(literal)\".  I guess we need to change prefix_pathspec()\n> to set PATHSPEC_LITERAL only when :(literal) is present, not when\n> --literal-pathspecs is used.\n\nI considered suggesting that, too, but it means that everywhere that\nchecks for PATHSPEC_LITERAL must _also_ check for literal_global (e.g.,\nif they were deciding to feed the result to fnmatch). Whereas if we\ncatch it at the parse_pathspec layer, then the consumers of the pathspec\njust need to check the one flag.\n\nI dunno. I haven't kept up very well with your work in this area, so you\nprobably have a better sense than I do of what would be the most\nelegant.\n\n-Peff\n"},{"id":"229541","messageId":"1382753360-32037-1-git-send-email-pclouds@gmail.com","threadId":"35197","inReplyTo":"20131025034947.GA4959@sigill.intra.peff.net","subject":"[PATCH] pathspec: stop --*-pathspecs impact on internal parse_pathspec() uses","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-26T02:09:20Z","receivedAt":"2013-10-26T02:09:20Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Normally parse_pathspec() is used on command line arguments where it\ncan do fancy thing like parsing magic on each argument or adding magic\nfor all pathspecs based on --*-pathspecs options.\n\nThere's another use of parse_pathspec(), where pathspec is needed, but\nthe input is known to be pure paths. In this case we usually don't\nwant --*-pathspecs to interfere. And we definitely do not want to\nparse magic in these paths, regardless of --literal-pathspecs.\n\nAdd new flag PATHSPEC_LITERAL_PATH for this purpose. When it's set,\n--*-pathspecs are ignored, no magic is parsed. And if the caller\nallows PATHSPEC_LITERAL (i.e. the next calls can take literal magic),\nthen PATHSPEC_LITERAL will be set.\n\nThis fixes cases where git chokes when GIT_*_PATHSPECS are set because\nparse_pathspec() indicates it won't take any magic. But\nGIT_*_PATHSPECS add them anyway. These are\n\n   export GIT_LITERAL_PATHSPECS=1\n   git blame -- something\n   git log --follow something\n   git log --merge\n\n\"git ls-files --with-tree=path\" (aka parse_pathspec() in\noverlay_tree_on_cache()) is safe because the input is empty, and\nproducing one pathspec due to PATHSPEC_PREFER_CWD does not take any\nmagic into account.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Jeff, how about this?\n \n It's similar to your last suggestion (i.e.  relaxing the magic mask\n about literal magic). In addition, it forces literal magic\n unconditionally in this case, which I think is the right thing to do.\n And it will fix other --*-pathspecs as well.\n\n builtin/blame.c            | 4 +++-\n pathspec.c                 | 9 ++++++++-\n pathspec.h                 | 7 +++++++\n revision.c                 | 3 ++-\n t/t6130-pathspec-noglob.sh | 7 +++++++\n tree-diff.c                | 4 +++-\n 6 files changed, 30 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 6da7233..1407ae7 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -409,7 +409,9 @@ static struct origin *find_origin(struct scoreboard *sb,\n \tpaths[0] = origin->path;\n \tpaths[1] = NULL;\n \n-\tparse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", paths);\n+\tparse_pathspec(&diff_opts.pathspec,\n+\t\t       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_LITERAL_PATH, \"\", paths);\n \tdiff_setup_done(&diff_opts);\n \n \tif (is_null_sha1(origin->commit->object.sha1))\ndiff --git a/pathspec.c b/pathspec.c\nindex ad1a9f5..4cf2bd3 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -128,7 +128,11 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\tdie(_(\"global 'literal' pathspec setting is incompatible \"\n \t\t      \"with all other global pathspec settings\"));\n \n-\tif (elt[0] != ':' || literal_global) {\n+\tif (flags & PATHSPEC_LITERAL_PATH)\n+\t\tglobal_magic = 0;\n+\n+\tif (elt[0] != ':' || literal_global ||\n+\t    (flags & PATHSPEC_LITERAL_PATH)) {\n \t\t; /* nothing to do */\n \t} else if (elt[1] == '(') {\n \t\t/* longhand */\n@@ -405,6 +409,9 @@ void parse_pathspec(struct pathspec *pathspec,\n \t\titem[i].magic = prefix_pathspec(item + i, &short_magic,\n \t\t\t\t\t\targv + i, flags,\n \t\t\t\t\t\tprefix, prefixlen, entry);\n+\t\tif ((flags & PATHSPEC_LITERAL_PATH) &&\n+\t\t    !(magic_mask & PATHSPEC_LITERAL))\n+\t\t\titem[i].magic |= PATHSPEC_LITERAL;\n \t\tif (item[i].magic & magic_mask)\n \t\t\tunsupported_magic(entry,\n \t\t\t\t\t  item[i].magic & magic_mask,\ndiff --git a/pathspec.h b/pathspec.h\nindex 944baeb..a75e924 100644\n--- a/pathspec.h\n+++ b/pathspec.h\n@@ -58,6 +58,13 @@ struct pathspec {\n #define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)\n #define PATHSPEC_PREFIX_ORIGIN (1<<6)\n #define PATHSPEC_KEEP_ORDER (1<<7)\n+/*\n+ * For the callers that just need pure paths from somewhere else, not\n+ * from command line. Global --*-pathspecs options are ignored. No\n+ * magic is parsed in each pathspec either. If PATHSPEC_LITERAL is\n+ * allowed, then it will automatically set for every pathspec.\n+ */\n+#define PATHSPEC_LITERAL_PATH (1<<8)\n \n extern void parse_pathspec(struct pathspec *pathspec,\n \t\t\t   unsigned magic_mask,\ndiff --git a/revision.c b/revision.c\nindex 0173e01..9b9e22e 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1372,7 +1372,8 @@ static void prepare_show_merge(struct rev_info *revs)\n \t\t\ti++;\n \t}\n \tfree_pathspec(&revs->prune_data);\n-\tparse_pathspec(&revs->prune_data, PATHSPEC_ALL_MAGIC, 0, \"\", prune);\n+\tparse_pathspec(&revs->prune_data, PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_LITERAL_PATH, \"\", prune);\n \trevs->limited = 1;\n }\n \ndiff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh\nindex ea00d71..6583532 100755\n--- a/t/t6130-pathspec-noglob.sh\n+++ b/t/t6130-pathspec-noglob.sh\n@@ -108,6 +108,13 @@ test_expect_success 'no-glob environment variable works' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'blame takes global pathspec flags' '\n+\tgit --literal-pathspecs blame -- foo &&\n+\tgit --icase-pathspecs   blame -- foo &&\n+\tgit --glob-pathspecs    blame -- foo &&\n+\tgit --noglob-pathspecs  blame -- foo\n+'\n+\n test_expect_success 'setup xxx/bar' '\n \tmkdir xxx &&\n \ttest_commit xxx xxx/bar\ndiff --git a/tree-diff.c b/tree-diff.c\nindex ccf9d7c..456660c 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -254,7 +254,9 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \t\t\tpath[0] = p->one->path;\n \t\t\tpath[1] = NULL;\n \t\t\tfree_pathspec(&opt->pathspec);\n-\t\t\tparse_pathspec(&opt->pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", path);\n+\t\t\tparse_pathspec(&opt->pathspec,\n+\t\t\t\t       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t\t\t       PATHSPEC_LITERAL_PATH, \"\", path);\n \n \t\t\t/*\n \t\t\t * The caller expects us to return a set of vanilla\n-- \n1.8.2.83.gc99314b\n"},{"id":"229542","messageId":"1382753379-32076-1-git-send-email-pclouds@gmail.com","threadId":"35197","inReplyTo":"20131025034947.GA4959@sigill.intra.peff.net","subject":"[PATCH] pathspec: stop --*-pathspecs impact on internal parse_pathspec() uses","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2013-10-26T02:09:39Z","receivedAt":"2013-10-26T02:09:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Normally parse_pathspec() is used on command line arguments where it\ncan do fancy thing like parsing magic on each argument or adding magic\nfor all pathspecs based on --*-pathspecs options.\n\nThere's another use of parse_pathspec(), where pathspec is needed, but\nthe input is known to be pure paths. In this case we usually don't\nwant --*-pathspecs to interfere. And we definitely do not want to\nparse magic in these paths, regardless of --literal-pathspecs.\n\nAdd new flag PATHSPEC_LITERAL_PATH for this purpose. When it's set,\n--*-pathspecs are ignored, no magic is parsed. And if the caller\nallows PATHSPEC_LITERAL (i.e. the next calls can take literal magic),\nthen PATHSPEC_LITERAL will be set.\n\nThis fixes cases where git chokes when GIT_*_PATHSPECS are set because\nparse_pathspec() indicates it won't take any magic. But\nGIT_*_PATHSPECS add them anyway. These are\n\n   export GIT_LITERAL_PATHSPECS=1\n   git blame -- something\n   git log --follow something\n   git log --merge\n\n\"git ls-files --with-tree=path\" (aka parse_pathspec() in\noverlay_tree_on_cache()) is safe because the input is empty, and\nproducing one pathspec due to PATHSPEC_PREFER_CWD does not take any\nmagic into account.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Jeff, how about this?\n \n It's similar to your last suggestion (i.e.  relaxing the magic mask\n about literal magic). In addition, it forces literal magic\n unconditionally in this case, which I think is the right thing to do.\n And it will fix other --*-pathspecs as well.\n\n builtin/blame.c            | 4 +++-\n pathspec.c                 | 9 ++++++++-\n pathspec.h                 | 7 +++++++\n revision.c                 | 3 ++-\n t/t6130-pathspec-noglob.sh | 7 +++++++\n tree-diff.c                | 4 +++-\n 6 files changed, 30 insertions(+), 4 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex 6da7233..1407ae7 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -409,7 +409,9 @@ static struct origin *find_origin(struct scoreboard *sb,\n \tpaths[0] = origin->path;\n \tpaths[1] = NULL;\n \n-\tparse_pathspec(&diff_opts.pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", paths);\n+\tparse_pathspec(&diff_opts.pathspec,\n+\t\t       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_LITERAL_PATH, \"\", paths);\n \tdiff_setup_done(&diff_opts);\n \n \tif (is_null_sha1(origin->commit->object.sha1))\ndiff --git a/pathspec.c b/pathspec.c\nindex ad1a9f5..4cf2bd3 100644\n--- a/pathspec.c\n+++ b/pathspec.c\n@@ -128,7 +128,11 @@ static unsigned prefix_pathspec(struct pathspec_item *item,\n \t\tdie(_(\"global 'literal' pathspec setting is incompatible \"\n \t\t      \"with all other global pathspec settings\"));\n \n-\tif (elt[0] != ':' || literal_global) {\n+\tif (flags & PATHSPEC_LITERAL_PATH)\n+\t\tglobal_magic = 0;\n+\n+\tif (elt[0] != ':' || literal_global ||\n+\t    (flags & PATHSPEC_LITERAL_PATH)) {\n \t\t; /* nothing to do */\n \t} else if (elt[1] == '(') {\n \t\t/* longhand */\n@@ -405,6 +409,9 @@ void parse_pathspec(struct pathspec *pathspec,\n \t\titem[i].magic = prefix_pathspec(item + i, &short_magic,\n \t\t\t\t\t\targv + i, flags,\n \t\t\t\t\t\tprefix, prefixlen, entry);\n+\t\tif ((flags & PATHSPEC_LITERAL_PATH) &&\n+\t\t    !(magic_mask & PATHSPEC_LITERAL))\n+\t\t\titem[i].magic |= PATHSPEC_LITERAL;\n \t\tif (item[i].magic & magic_mask)\n \t\t\tunsupported_magic(entry,\n \t\t\t\t\t  item[i].magic & magic_mask,\ndiff --git a/pathspec.h b/pathspec.h\nindex 944baeb..a75e924 100644\n--- a/pathspec.h\n+++ b/pathspec.h\n@@ -58,6 +58,13 @@ struct pathspec {\n #define PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE (1<<5)\n #define PATHSPEC_PREFIX_ORIGIN (1<<6)\n #define PATHSPEC_KEEP_ORDER (1<<7)\n+/*\n+ * For the callers that just need pure paths from somewhere else, not\n+ * from command line. Global --*-pathspecs options are ignored. No\n+ * magic is parsed in each pathspec either. If PATHSPEC_LITERAL is\n+ * allowed, then it will automatically set for every pathspec.\n+ */\n+#define PATHSPEC_LITERAL_PATH (1<<8)\n \n extern void parse_pathspec(struct pathspec *pathspec,\n \t\t\t   unsigned magic_mask,\ndiff --git a/revision.c b/revision.c\nindex 0173e01..9b9e22e 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1372,7 +1372,8 @@ static void prepare_show_merge(struct rev_info *revs)\n \t\t\ti++;\n \t}\n \tfree_pathspec(&revs->prune_data);\n-\tparse_pathspec(&revs->prune_data, PATHSPEC_ALL_MAGIC, 0, \"\", prune);\n+\tparse_pathspec(&revs->prune_data, PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t       PATHSPEC_LITERAL_PATH, \"\", prune);\n \trevs->limited = 1;\n }\n \ndiff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh\nindex ea00d71..6583532 100755\n--- a/t/t6130-pathspec-noglob.sh\n+++ b/t/t6130-pathspec-noglob.sh\n@@ -108,6 +108,13 @@ test_expect_success 'no-glob environment variable works' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success 'blame takes global pathspec flags' '\n+\tgit --literal-pathspecs blame -- foo &&\n+\tgit --icase-pathspecs   blame -- foo &&\n+\tgit --glob-pathspecs    blame -- foo &&\n+\tgit --noglob-pathspecs  blame -- foo\n+'\n+\n test_expect_success 'setup xxx/bar' '\n \tmkdir xxx &&\n \ttest_commit xxx xxx/bar\ndiff --git a/tree-diff.c b/tree-diff.c\nindex ccf9d7c..456660c 100644\n--- a/tree-diff.c\n+++ b/tree-diff.c\n@@ -254,7 +254,9 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co\n \t\t\tpath[0] = p->one->path;\n \t\t\tpath[1] = NULL;\n \t\t\tfree_pathspec(&opt->pathspec);\n-\t\t\tparse_pathspec(&opt->pathspec, PATHSPEC_ALL_MAGIC, 0, \"\", path);\n+\t\t\tparse_pathspec(&opt->pathspec,\n+\t\t\t\t       PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,\n+\t\t\t\t       PATHSPEC_LITERAL_PATH, \"\", path);\n \n \t\t\t/*\n \t\t\t * The caller expects us to return a set of vanilla\n-- \n1.8.2.83.gc99314b\n"},{"id":"229548","messageId":"20131026063912.GA24499@sigill.intra.peff.net","threadId":"35197","inReplyTo":"1382753360-32037-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH] pathspec: stop --*-pathspecs impact on internal parse_pathspec() uses","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2013-10-26T06:39:12Z","receivedAt":"2013-10-26T06:39:12Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Oct 26, 2013 at 09:09:20AM +0700, Nguyen Thai Ngoc Duy wrote:\n\n>  Jeff, how about this?\n>  \n>  It's similar to your last suggestion (i.e.  relaxing the magic mask\n>  about literal magic). In addition, it forces literal magic\n>  unconditionally in this case, which I think is the right thing to do.\n>  And it will fix other --*-pathspecs as well.\n\nYeah, I think I follow your reasoning. The problem I saw was just about\n--literal-pathspec, but the real issue is that \"blame\" does not want\nmagic pathspecs at all, and your new flag turns that off.\n\nSo it fixes both my problem, as well as \"git blame -- :(foo)bar\".\n\n-Peff\n"}]}