git/list[1] front-page[2] threads[3] people[4] search[5] about
 

BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Apr 25, 2017, 19:13 UTC
Message-ID
<CACBZZX5u5fF4fJBJ3CwH0DmLBw4D32jN5o=Om-iqwQdPG93DFg@mail.gmail.com>

Thought I'd just start another thread for this rather than tack it onto the pathalogical case thread.

In commit 4c251e5cb5 ("wildmatch: make /**/ match zero or more directories", 2012-10-15) Duy added support for ** in globs.

One test-case for this is:
    match 1 0 'foo/baz/bar' 'foo/**/**/bar'

I.e. foo/**/**/bar matches foo/baz/bar. However due to some pre-pruning we do in pathspec/ls-tree we can't ever match it, because the first thing we do is peel the first part of the path/pattern off, i.e. foo/, and then match baz/bar against **/**/bar.

The monkeypatch at the end of this mail makes this case work, but breaks some others, and more importantly now e.g. on git.git we have to call wildmatch() ~3K times for all the files we track, instead of just for stuff in my foo/ folder.

So I don't think this needs to be made to work, being able to prune patterns like this is very useful, but:

a) the wildmatch tests are lacking because they just call the low-level function without a helper, but that's not actually how it gets invoked by anything that matters

b) If we're going to be using wildmatch but implicitly not supporting some of its very expensive optimization-beating syntax we should probably make that an error explicitly.

diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index a6c70dbe9e..4285a09ccc 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -235,3 +235,3 @@ static void show_ce_entry(const char *tag, const
struct cache_entry *ce)
        struct strbuf name = STRBUF_INIT;
-       int len = max_prefix_len;
+       int len = 0;
        if (super_prefix)
@@ -640,2 +640,3 @@ int cmd_ls_files(int argc, const char **argv,
const char *cmd_prefix)
        max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
+       max_prefix_len = 0;

diff --git a/dir.c b/dir.c
index f451bfa48c..b4399f042c 100644
--- a/dir.c
+++ b/dir.c
@@ -86,3 +86,3 @@ int git_fnmatch(const struct pathspec_item *item,
                return wildmatch(pattern, string,
-                                item->magic & PATHSPEC_ICASE ? WM_CASEFOLD : 0,
+                                item->magic & PATHSPEC_ICASE ?
WM_CASEFOLD : WM_PATHNAME,
                                 NULL);
@@ -316,3 +316,3 @@ static int match_pathspec_item(const struct
pathspec_item *item, int prefix,
            !git_fnmatch(item, match, name,
-                        item->nowildcard_len - prefix))
+                        prefix))
                return MATCHED_FNMATCH;
Next: Duy Nguyen
Message 1 of 3 in “BUG: wildmatches like foo/**/**/bar don't match properly due to internal optimizations”
  1. Ævar Arnfjörð BjarmasonApr 25, 2017
  2. Duy NguyenApr 26, 2017
  3. Brandon WilliamsApr 26, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.