wildmatch + fnmatch compatibility

From: Zachary Newman <hidden>
Date: 2017-10-05 14:07:23

Hi all,

I noticed a possible inconsistency in the documentation for
.gitignore; the pertinent bit is:

    If the pattern does not contain a slash /, Git treats it as a
shell glob pattern
    and checks for a match against the pathname relative to the location of the
    .gitignore file

    ...

    Otherwise, Git treats the pattern as a shell glob suitable for
    consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in
    the pattern will not match a / in the pathname.

However, notice:

    $ cd $(mktemp -d)
    $ git init
    $ touch '['
    $ echo -e '.gitignore\n[' > .gitignore
    $ git add --dry-run .
    add '['
    $ python -c "import fnmatch; print fnmatch.fnmatchcase('[', '[')"
    True

Specifically, git *does not* match the string '[' while fnmatch
*does*. "Git treats it
as a shell glob pattern" could mean that the globbing is different
from fnmatch,
but 'test/[' exhibits the same behavior.

I believe this is the result of an inconsistency in between wildmatch
and fnmatch[1]:

    printf("%d\n", fnmatch("[", "[", FNM_PATHNAME);  // prints 0,
indicating a match
    printf("%d\n", wildmatch("[", "[", WM_PATHNAME);  // prints -1,
indicating error

While the way wildmatch handles this makes sense (it *is* a malformed pattern),
it doesn't square with the documentation for .gitignore [2].

There are a few ways that I can think of to resolve this:

* update the documentation to reflect that the syntax is similar but
not identical to
  fnmatch.
* update the behavior of wildmatch to match fnmatch.
* leave the behavior of wildmatch, but fall back to fnmatch if there's an error.
* decide that anybody who comes to depend on this behavior is already in
  dangerous territory, and it's not worth addressing.
* decide that I'm wrong.

(As an aside: I trolled through the mailing list a bit but couldn't
find a rationale
for using wildmatch instead of fnmatch---it looks to be related to a desire to
support '**' patterns in .gitignore, maybe?)

Cheers,
Zack


[1] Specifically, I've tested on both a macOS (BSD) implementation and
Ubuntu (GNU) implementation of fnmatch. Additionally, if I'm reading the
specification right, it claims "If an open bracket introduces a
bracket expression
as in XBD RE Bracket Expression...it shall introduce a pattern bracket
expression....Otherwise, '[' shall match the character itself."
(<http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13_02>)

[2] There's one caveat: none of the older versions I tested with
ignore '[' either.
In particular, 1.8.2.3 just prints "ha!" (which seems like it
indicates an error) and
1.8.3.1 includes '['; both of these are before the 1.8.4 release, when
the cut over
to using wildmatch occurred.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help