Mercurial .hgignore regular expression
Asked Answered
A

4

6

Using Mercurial, I need to ignore all files and directories except directories "tests" and "languages" and files in those directories. That all must be done with regex and .hgignoere

Files:

  • tests\junk.txt
  • cms\tests\some_file.txt
  • cms\languages\users\lang.txt
  • languages\lang2.txt
  • tests.txt
  • proba/tests.txt

I tried with this:

^(?!test|test/|test$|languages|languages/|languages$)

but this only matches the files that starts with test and language:

  • tests\junk.txt
  • languages\lang2.txt

What I want is to matches also

  • cms\tests\some_file.txt
  • cms\languages\users\lang.txt

Any advice would be appreciated.

Across answered 14/7, 2010 at 13:44 Comment(1)
I changed my answer, and now it will work.Stanley
B
1

Use globs, they're simpler:

C:> dir
tests  languages pr0n espionage more_pr0n

C:> type .hgignore
syntax: glob
pr0n/*
espionage/*
more_pr0n/*

added: If you are concerned that there will be new directories that won't be ignored then you should:

hg add .hgignore
hg commit 
echo "new_directory/*" >> .hgignore
hg commit

If you have too many directories and files popping up in your source directory for this method to work, make a source-only directory.

Bushtit answered 14/7, 2010 at 13:54 Comment(5)
I get the impression he's looking for a suggestion that works even when new top level directories.Soneson
I got that impression too, in which case the cure is added above.Bushtit
Thanks for fast answer. I tried to put this in my .hgignore: syntax: glob tests/* languages/* But this is opposite of that what I want to achieve. I don't want to ignore files in those folder. I want to ignore all files/folders that are not member of "tests" and "languages"Across
I understand what you want, I'm suggesting that what you want is bad practice which is partly why it is difficult.Bushtit
This answer does not describe why it is impossible to use .hgignore the way the OP desires.Warfare
S
2

It's not the answer you're looking for but almost no one uses the negative-width-look-ahead ?: syntax in their .hgignore files. In cases where they want just a small subset of all files to be unignored they usually just ignore everything and then hg add the exceptions -- remember that in mercurial (unlike in cvs/svn) adding a file overrides ignore.

So if your .hgignore you'd have:

.*

and then you'd hg add the files in your tests and languages directories explicitly with 'hg add'. You do then, of course have to remember to add any new files as you go as everything will be ignored, but if most files are supposed to be ignored it still the easier way to go.

Soneson answered 14/7, 2010 at 14:8 Comment(4)
It is often unclear to me whether the question should be answered according to the constraints of the question or if the root problem should be addressed. If the latter, this answer is Correct and Complete but not Good.Bushtit
Thanks Ray4an for the answer but this is to hard to do every time. My idea is to ignore all files that are not in the folders tests and languages. Do you know how can I do this?Across
Why don’t people use the (?!negative-lookahead) syntax? The docs say that the pattern is a Python regex. Is that Python feature not supported in Mercurial somehow?Warfare
Ah, negative lookahead does work in .hgignore. In my case I was just writing my expression wrong (I needed a $ in my negative lookahead).Warfare
B
1

Use globs, they're simpler:

C:> dir
tests  languages pr0n espionage more_pr0n

C:> type .hgignore
syntax: glob
pr0n/*
espionage/*
more_pr0n/*

added: If you are concerned that there will be new directories that won't be ignored then you should:

hg add .hgignore
hg commit 
echo "new_directory/*" >> .hgignore
hg commit

If you have too many directories and files popping up in your source directory for this method to work, make a source-only directory.

Bushtit answered 14/7, 2010 at 13:54 Comment(5)
I get the impression he's looking for a suggestion that works even when new top level directories.Soneson
I got that impression too, in which case the cure is added above.Bushtit
Thanks for fast answer. I tried to put this in my .hgignore: syntax: glob tests/* languages/* But this is opposite of that what I want to achieve. I don't want to ignore files in those folder. I want to ignore all files/folders that are not member of "tests" and "languages"Across
I understand what you want, I'm suggesting that what you want is bad practice which is partly why it is difficult.Bushtit
This answer does not describe why it is impossible to use .hgignore the way the OP desires.Warfare
W
1

Key to solving this is this section from the hgignore man page:

For example, say we have an untracked file, file.c, at a/b/file.c inside our repository. Mercurial will ignore file.c if any pattern in .hgignore matches a/b/file.c, a/b or a.

In order to ignore everything but a certain set of directories, we must carefully ignore everything at each level of the file hierarchy. Let's say you want to ignore everything except one/two/three/, one/two/four/, and foo/. First, ignore everything but one/ and foo/:

^(?!(one|foo)(/|$))

The ^ and (/|$) anchor one|foo in the path. Next, ignore everything inside one/ that isn't two/:

^one/(?!(two)(/|$))

The parentheses around two are there for consistency and aren't necessary. And finally ignore everything in two/ that isn't three/ or four/:

^one/two/(?!(three|four)(/|$))

This easily generalizes to any such set of directories.

Well answered 22/5, 2013 at 1:49 Comment(0)
C
0

It's not possible.

See the manpage.

For example, say we have an untracked file, file.c, at a/b/file.c inside our repository. Mercurial will ignore file.c if any pattern in .hgignore matches a/b/file.c, a/b or a.

So let's say you make a regex that will not match any path containing test and the file proba/tests.txt is in your working directory. That regex will first be applied to proba and will match which will result in the file being ignored.

Chintz answered 14/7, 2010 at 14:28 Comment(4)
It actually is possible. Part of the reason you're wrong is that it's possible to anchor regular expressions so they only match at the start of the path.Stanley
You're going to have to prove it by supplying one because, as far as I can figure, rooting or not shouldn't matter.Chintz
I'm sorry, I missed an important part of the question. You're right, it isn't possible.Stanley
It would be possible if Mercurial were changed to give a hint that the match is against a directory. However, it is too late for them to change this as it would break their API. What I mean for example is if Mercurial tried to match a/ and then a/b/ and then a/b/file.c, it would be possible to write the pattern. I think you correctly identify the key issue with Mercurial which makes this impossible. Probably could write an extension instead of using .hgignore?Warfare

© 2022 - 2024 — McMap. All rights reserved.