Search code examples
regexmercurialhgignore

Can't ignore all files except *.m in directories


I want Mercurial to automatically ignore all files not ending in '.m' at the repo root and in all subdirectories, and I can't make this work.

Here's a dummy repo (no files tracked):

./.hgignore
./foo/abcdef.m
./foo/abcdef.txt
./abcdef.m
./abcdef.txt

This is .hgignore:

syntax: regexp
re:.*[^m]$

And this is what happens:

~/src/dummy$ hg st -A
? abcdef.m
I .hgignore
I abcdef.txt
I foo/abcdef.m
I foo/abcdef.txt

That is, abcdef.txt and foo/abcdef.txt are ignored, but so is foo/abcdef.m, which shouldn't be.

If I change my regex to the opposite:

syntax: regexp
re:.*[m]$

I get the expected result:

~/src/dummy$ hg st -A
? .hgignore
? abcdef.txt
? foo/abcdef.txt
I abcdef.m
I foo/abcdef.m

The .m files are ignored, the .txt files are not.

What am I doing wrong? Why does an inclusive regex (ends in 'm') work but not an exclusive regex (doesn't end in 'm')?

Mercurial 2.8.2 on Ubuntu 14.04.


Solution

  • This is a specified limitation, you cannot exclude all but... You can read it here:

    Limitations

    There is no straightforward way to ignore all but a set of files. Attempting to use an inverted regex match will fail when combined with other patterns. This is an intentional limitation, as alternate formats were all considered far too likely to confuse users to be worth the additional flexibility.

    And @sth is right here, you are blocking foo sub-folder entirely in your first attempt.