views:

81

answers:

2

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?

+2  A: 

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

shambulator
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).
Chris R
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.
shambulator
A: 

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.

Ry4an
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?
shambulator
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.
Ry4an
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`.
shambulator
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.
Ry4an