How can I ignore all directories except one using .hgignore?
Asked Answered
R

2

17

I'm managing $HOME using Mercurial, to keep my dotfiles nice and tracked, or at least the ones that matter to me.

However, there's a profusion of files and directories in ~ that do not need to be tracked, and that set is ever-changing and ever-growing.

Historically, I've dealt with this by having this .hgignore:

syntax: glob
*

This keeps my status clean, as far as it goes, making only previously tracked files visible. However, I have some directories (in my case, scripts, .emacs.d) that I would like to see untracked files in; I almost always want to track new additions to those directories.

I know that I can run hg st -u scripts to identify untracked files, but I want a means whereby I can achieve the same function using plain ole hg status.

Is there a way to do this?

Retaretable answered 3/9, 2010 at 15:58 Comment(0)
S
19

Try this in .hgignore instead:

syntax: regexp

^(?!(scripts|foo|bar)/)[^/]+/
  • ^ matches start of path
  • (?!(scripts|foo|bar) uses negative lookahead to ignore all files except those in directories scripts, foo or bar
  • /) ensures that directories which have a tracked directory as a prefix are ignored
  • [^/]+/ then actually matches any directory (excluding those ruled out by the lookahead), so that files in ~ aren't ignored

Credit for the central idea in this solution (the negative lookahead) goes to Michael La Voie's answer to this question

Seema answered 3/9, 2010 at 19:41 Comment(2)
This is most of a solution, but all of the files in ~ still get shown, which is at least as noisy. I don't track every dotfile (not least of which because so many packages insist on dropping them in my ~ directory).Retaretable
Unless you can use filename patterns to distinguish dotfiles (to be ignored) from directories (not to be ignored), I think you're out of luck. Mercurial docs say that if a path a/b/c fails to match a .hgignore pattern, the same pattern is tried against both a/b and, if that fails, a. So files and directories in the root can only be distinguished by how they're spelled. If only a few tracked directories start with a dot, then you could manually add those and .hgignore everything else starting with one.Seema
P
11

This question has been asked here on SO quite a few times, and you'll get a lot of convoluted answers using zero-width negative look ahead assertions, an oft abused regex trick, but the better solutions are to either (a) just make the repo in that directory alone or (b) just add the files in that directory. For option (b) you'd just put .* in your .hgignore file to ignore everything, and then manually hg add the files you want tracked. In mercurial, unlike svn and cvs, you can override an ignore with an add.

Postprandial answered 3/9, 2010 at 20:9 Comment(6)
Creating the repo in that directory doesn't track files in the root, or leave open the option of tracking other directories in the same repo. What's wrong with using lookahead?Seema
Nothing's wrong, it's just complicated and seldom done. Mostly folks just 'hg add' the exceptions and ignore everything if they wish .hgignore were a whitelist instead of the blacklist that it is.Postprandial
Fair enough - I won't deny it took a couple of tries to get the regex right, and that's assuming I haven't missed some corner case :) Each one you get right helps you with the next one, though! And this way, you get to just use hg status and hg addremove.Seema
Yeah, it's six one of half a dozen of the other. I'd be stuck with find scripts foo bar -type f | xargs hg add which would require a shell alias or a [alias] in mercurial. addremove would still catch deleted files since having added them overrides the .hgignore.Postprandial
I think you should put *.* in the .hgignore file - .* didn't work for me.Harve
.* is regex syntax for "everything". *.* is glob syntax for "everything with at least period in it", which if every file has an extension is approximately "everything". You control which syntax you're using on a per-line or per-block basis w/ the default being regexps.Postprandial

© 2022 - 2024 — McMap. All rights reserved.