{"thread":{"id":"45799","subject":"BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations","startedAt":"2017-04-25T19:13:54Z","lastAt":"2017-04-26T17:38:24Z","messageCount":3,"participants":["Ævar Arnfjörð Bjarmason","Duy Nguyen","Brandon Williams"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"317831","messageId":"CACBZZX5u5fF4fJBJ3CwH0DmLBw4D32jN5o=Om-iqwQdPG93DFg@mail.gmail.com","threadId":"45799","inReplyTo":null,"subject":"BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-25T19:13:27Z","receivedAt":"2017-04-25T19:13:54Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"Thought I'd just start another thread for this rather than tack it\nonto the pathalogical case thread.\n\nIn commit 4c251e5cb5 (\"wildmatch: make /**/ match zero or more\ndirectories\", 2012-10-15) Duy added support for ** in globs.\n\nOne test-case for this is:\n\n    match 1 0 'foo/baz/bar' 'foo/**/**/bar'\n\nI.e. foo/**/**/bar matches foo/baz/bar. However due to some\npre-pruning we do in pathspec/ls-tree we can't ever match it, because\nthe first thing we do is peel the first part of the path/pattern off,\ni.e. foo/, and then match baz/bar against **/**/bar.\n\nThe monkeypatch at the end of this mail makes this case work, but\nbreaks some others, and more importantly now e.g. on git.git we have\nto call wildmatch() ~3K times for all the files we track, instead of\njust for stuff in my foo/ folder.\n\nSo I don't think this needs to be made to work, being able to prune\npatterns like this is very useful, but:\n\na) the wildmatch tests are lacking because they just call the\nlow-level function without a helper, but that's not actually how it\ngets invoked by anything that matters\n\nb) If we're going to be using wildmatch but implicitly not supporting\nsome of its very expensive optimization-beating syntax we should\nprobably make that an error explicitly.\n\ndiff --git a/builtin/ls-files.c b/builtin/ls-files.c\nindex a6c70dbe9e..4285a09ccc 100644\n--- a/builtin/ls-files.c\n+++ b/builtin/ls-files.c\n@@ -235,3 +235,3 @@ static void show_ce_entry(const char *tag, const\nstruct cache_entry *ce)\n        struct strbuf name = STRBUF_INIT;\n-       int len = max_prefix_len;\n+       int len = 0;\n        if (super_prefix)\n@@ -640,2 +640,3 @@ int cmd_ls_files(int argc, const char **argv,\nconst char *cmd_prefix)\n        max_prefix_len = max_prefix ? strlen(max_prefix) : 0;\n+       max_prefix_len = 0;\n\ndiff --git a/dir.c b/dir.c\nindex f451bfa48c..b4399f042c 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -86,3 +86,3 @@ int git_fnmatch(const struct pathspec_item *item,\n                return wildmatch(pattern, string,\n-                                item->magic & PATHSPEC_ICASE ? WM_CASEFOLD : 0,\n+                                item->magic & PATHSPEC_ICASE ?\nWM_CASEFOLD : WM_PATHNAME,\n                                 NULL);\n@@ -316,3 +316,3 @@ static int match_pathspec_item(const struct\npathspec_item *item, int prefix,\n            !git_fnmatch(item, match, name,\n-                        item->nowildcard_len - prefix))\n+                        prefix))\n                return MATCHED_FNMATCH;\n"},{"id":"317908","messageId":"CACsJy8Ct4VU0XAgJruFECEVxb98MS4P+9Z6D8ag35ySL6OY-0g@mail.gmail.com","threadId":"45799","inReplyTo":"CACBZZX5u5fF4fJBJ3CwH0DmLBw4D32jN5o=Om-iqwQdPG93DFg@mail.gmail.com","subject":"Re: BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2017-04-26T08:56:22Z","receivedAt":"2017-04-26T08:57:01Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Apr 26, 2017 at 2:13 AM, Ævar Arnfjörð Bjarmason\n<avarab@gmail.com> wrote:\n> Thought I'd just start another thread for this rather than tack it\n> onto the pathalogical case thread.\n>\n> In commit 4c251e5cb5 (\"wildmatch: make /**/ match zero or more\n> directories\", 2012-10-15) Duy added support for ** in globs.\n>\n> One test-case for this is:\n>\n>     match 1 0 'foo/baz/bar' 'foo/**/**/bar'\n>\n> I.e. foo/**/**/bar matches foo/baz/bar. However due to some\n> pre-pruning we do in pathspec/ls-tree we can't ever match it, because\n> the first thing we do is peel the first part of the path/pattern off,\n> i.e. foo/, and then match baz/bar against **/**/bar.\n\nYeah. I think the prefix compare trick predated wildmatch. When I\nintroduced positional wildcards \"**/\" I failed to spot this. Good\ncatch.\n\nIdeally this sort of optimization should be contained within wildmatch\n(or whatever matching engine we'll be using). It also opens up more\nopportunity (like precompile pattern mentioned elsewhere in this\nthread).\n\nYou need to be careful though, when we do case-insensitive matching,\nsometimes we want to match the prefix case _sensitively_ instead. So\nwe need to pass the \"prefix\" info in some cases to the matching\nengine.\n\nI guess time is now ripe (i.e. somebody volunteers to work on this ;-)\nto improve wildmatch. \"improve\" can also be \"rewriting to pcre\" if we\nreally want that route, which I have no opinion because I don't know\npcre availability on other (some obscure) platforms.\n-- \nDuy\n"},{"id":"317944","messageId":"20170426173816.GA80265@google.com","threadId":"45799","inReplyTo":"CACsJy8Ct4VU0XAgJruFECEVxb98MS4P+9Z6D8ag35ySL6OY-0g@mail.gmail.com","subject":"Re: BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations","fromName":"Brandon Williams","fromEmail":"bmwill@google.com","sentAt":"2017-04-26T17:38:16Z","receivedAt":"2017-04-26T17:38:24Z","isPatch":false,"sender":{"key":"bwilliams.eng@gmail.com","avatar":null},"body":"On 04/26, Duy Nguyen wrote:\n> On Wed, Apr 26, 2017 at 2:13 AM, Ævar Arnfjörð Bjarmason\n> <avarab@gmail.com> wrote:\n> > Thought I'd just start another thread for this rather than tack it\n> > onto the pathalogical case thread.\n> >\n> > In commit 4c251e5cb5 (\"wildmatch: make /**/ match zero or more\n> > directories\", 2012-10-15) Duy added support for ** in globs.\n> >\n> > One test-case for this is:\n> >\n> >     match 1 0 'foo/baz/bar' 'foo/**/**/bar'\n> >\n> > I.e. foo/**/**/bar matches foo/baz/bar. However due to some\n> > pre-pruning we do in pathspec/ls-tree we can't ever match it, because\n> > the first thing we do is peel the first part of the path/pattern off,\n> > i.e. foo/, and then match baz/bar against **/**/bar.\n> \n> Yeah. I think the prefix compare trick predated wildmatch. When I\n> introduced positional wildcards \"**/\" I failed to spot this. Good\n> catch.\n> \n> Ideally this sort of optimization should be contained within wildmatch\n> (or whatever matching engine we'll be using). It also opens up more\n> opportunity (like precompile pattern mentioned elsewhere in this\n> thread).\n> \n> You need to be careful though, when we do case-insensitive matching,\n> sometimes we want to match the prefix case _sensitively_ instead. So\n> we need to pass the \"prefix\" info in some cases to the matching\n> engine.\n> \n> I guess time is now ripe (i.e. somebody volunteers to work on this ;-)\n> to improve wildmatch. \"improve\" can also be \"rewriting to pcre\" if we\n> really want that route, which I have no opinion because I don't know\n> pcre availability on other (some obscure) platforms.\n\nIf we do end up improving wildmatch, we may also want the functionality\nto (with a flag) have a pattern match a leading directory.  This would\nbe useful in the submodule case where a user gives a pathspec which\ncould go into a submodule but we don't want to launch a child process to\noperate on the submodule unless the first part of the pattern matches\nthe submodule.  Right now with recursive grep, if wildcards are used\nthen the code just punts and says \"yeah this pattern may match something\nin the submodule but we won't know for sure till we actually try\".\n\n-- \nBrandon Williams\n"}]}