# HG changeset patch # User Patrick Mezard # Date 1345064620 -7200 # Node ID ff3c89cf1477e558424c555f3a40fa82953b1cb3 # Parent 5e276d1d504abfc012d2768f8482e5ba4921fd1c# Parent 1310489eb5d6e4b730638220591f3f8eb1eefe9c Merge with stable diff -r 5e276d1d504a -r ff3c89cf1477 mercurial/commands.py --- a/mercurial/commands.py Wed Aug 15 12:12:21 2012 +0200 +++ b/mercurial/commands.py Wed Aug 15 23:03:40 2012 +0200 @@ -1847,14 +1847,17 @@ localrevs = opts.get('local_head') doit(localrevs, remoterevs) -@command('debugfileset', [], ('REVSPEC')) -def debugfileset(ui, repo, expr): +@command('debugfileset', + [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))], + _('[-r REV] FILESPEC')) +def debugfileset(ui, repo, expr, **opts): '''parse and apply a fileset specification''' + ctx = scmutil.revsingle(repo, opts.get('rev'), None) if ui.verbose: tree = fileset.parse(expr)[0] ui.note(tree, "\n") - for f in fileset.getfileset(repo[None], expr): + for f in fileset.getfileset(ctx, expr): ui.write("%s\n" % f) @command('debugfsinfo', [], _('[PATH]')) diff -r 5e276d1d504a -r ff3c89cf1477 mercurial/fileset.py --- a/mercurial/fileset.py Wed Aug 15 12:12:21 2012 +0200 +++ b/mercurial/fileset.py Wed Aug 15 23:03:40 2012 +0200 @@ -107,6 +107,11 @@ s = set(getset(mctx, x)) return [r for r in mctx.subset if r not in s] +def minusset(mctx, x, y): + xl = getset(mctx, x) + yl = set(getset(mctx, y)) + return [f for f in xl if f not in yl] + def listset(mctx, a, b): raise error.ParseError(_("can't use a list in this context")) @@ -251,8 +256,11 @@ """``grep(regex)`` File contains the given regular expression. """ - pat = getstring(x, _("grep requires a pattern")) - r = re.compile(pat) + try: + # i18n: "grep" is a keyword + r = re.compile(getstring(x, _("grep requires a pattern"))) + except re.error, e: + raise error.ParseError(_('invalid match pattern: %s') % e) return [f for f in mctx.existing() if r.search(mctx.ctx[f].data())] _units = dict(k=2**10, K=2**10, kB=2**10, KB=2**10, @@ -406,6 +414,7 @@ 'symbol': stringset, 'and': andset, 'or': orset, + 'minus': minusset, 'list': listset, 'group': getset, 'not': notset, @@ -424,7 +433,14 @@ def filter(self, files): return [f for f in files if f in self.subset] def existing(self): - return (f for f in self.subset if f in self.ctx) + if self._status is not None: + removed = set(self._status[3]) + unknown = set(self._status[4] + self._status[5]) + else: + removed = set() + unknown = set() + return (f for f in self.subset + if (f in self.ctx and f not in removed) or f in unknown) def narrow(self, files): return matchctx(self.ctx, self.filter(files), self._status) @@ -438,14 +454,26 @@ return True return False +# filesets using matchctx.existing() +_existingcallers = [ + 'binary', + 'exec', + 'grep', + 'size', + 'symlink', +] + def getfileset(ctx, expr): tree, pos = parse(expr) if (pos != len(expr)): raise error.ParseError(_("invalid token"), pos) # do we need status info? - if _intree(['modified', 'added', 'removed', 'deleted', - 'unknown', 'ignored', 'clean'], tree): + if (_intree(['modified', 'added', 'removed', 'deleted', + 'unknown', 'ignored', 'clean'], tree) or + # Using matchctx.existing() on a workingctx requires us to check + # for deleted files. + (ctx.rev() is None and _intree(_existingcallers, tree))): unknown = _intree(['unknown'], tree) ignored = _intree(['ignored'], tree) @@ -457,7 +485,7 @@ subset.extend(c) else: status = None - subset = ctx.walk(ctx.match([])) + subset = list(ctx.walk(ctx.match([]))) return getset(matchctx(ctx, subset, status), tree) diff -r 5e276d1d504a -r ff3c89cf1477 tests/test-cat.t --- a/tests/test-cat.t Wed Aug 15 12:12:21 2012 +0200 +++ b/tests/test-cat.t Wed Aug 15 23:03:40 2012 +0200 @@ -21,3 +21,14 @@ [1] $ hg cat -r 1 b 1 + +Test fileset + + $ echo 3 > c + $ hg ci -Am addmore c + $ hg cat 'set:not(b) or a' + 3 + $ hg cat 'set:c or b' + 1 + 3 + diff -r 5e276d1d504a -r ff3c89cf1477 tests/test-debugcomplete.t --- a/tests/test-debugcomplete.t Wed Aug 15 12:12:21 2012 +0200 +++ b/tests/test-debugcomplete.t Wed Aug 15 23:03:40 2012 +0200 @@ -229,7 +229,7 @@ debugdata: changelog, manifest debugdate: extended debugdiscovery: old, nonheads, ssh, remotecmd, insecure - debugfileset: + debugfileset: rev debugfsinfo: debuggetbundle: head, common, type debugignore: diff -r 5e276d1d504a -r ff3c89cf1477 tests/test-fileset.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-fileset.t Wed Aug 15 23:03:40 2012 +0200 @@ -0,0 +1,228 @@ + $ fileset() { + > hg debugfileset "$@" + > } + + $ hg init repo + $ cd repo + $ echo a > a1 + $ echo a > a2 + $ echo b > b1 + $ echo b > b2 + $ hg ci -Am addfiles + adding a1 + adding a2 + adding b1 + adding b2 + +Test operators and basic patterns + + $ fileset a1 + a1 + $ fileset 'a*' + a1 + a2 + $ fileset '"re:a\d"' + a1 + a2 + $ fileset 'a1 or a2' + a1 + a2 + $ fileset 'a1 | a2' + a1 + a2 + $ fileset 'a* and "*1"' + a1 + $ fileset 'a* & "*1"' + a1 + $ fileset 'not (r"a*")' + b1 + b2 + $ fileset '! ("a*")' + b1 + b2 + $ fileset 'a* - a1' + a2 + +Test files status + + $ rm a1 + $ hg rm a2 + $ echo b >> b2 + $ hg cp b1 c1 + $ echo c > c2 + $ echo c > c3 + $ cat > .hgignore < \.hgignore + > 2$ + > EOF + $ fileset 'modified()' + b2 + $ fileset 'added()' + c1 + $ fileset 'removed()' + a2 + $ fileset 'deleted()' + a1 + $ fileset 'unknown()' + c3 + $ fileset 'ignored()' + .hgignore + c2 + $ fileset 'hgignore()' + a2 + b2 + $ fileset 'clean()' + b1 + $ fileset 'copied()' + c1 + +Test files properties + + >>> file('bin', 'wb').write('\0a') + $ fileset 'binary()' + $ fileset 'binary() and unknown()' + bin + $ echo '^bin$' >> .hgignore + $ fileset 'binary() and ignored()' + bin + $ hg add bin + $ fileset 'binary()' + bin + + $ fileset 'grep("b{1}")' + b2 + c1 + b1 + $ fileset 'grep("missingparens(")' + hg: parse error: invalid match pattern: unbalanced parenthesis + [255] + +#if execbit + $ chmod +x b2 + $ fileset 'exec()' + b2 +#endif + +#if symlink + $ ln -s b2 b2link + $ fileset 'symlink() and unknown()' + b2link + $ hg add b2link +#endif + + >>> file('1k', 'wb').write(' '*1024) + >>> file('2k', 'wb').write(' '*2048) + $ hg add 1k 2k + $ fileset 'size("bar")' + hg: parse error: couldn't parse size: bar + [255] + $ fileset 'size(1k)' + 1k + $ fileset '(1k or 2k) and size("< 2k")' + 1k + $ fileset '(1k or 2k) and size("<=2k")' + 1k + 2k + $ fileset '(1k or 2k) and size("> 1k")' + 2k + $ fileset '(1k or 2k) and size(">=1K")' + 1k + 2k + $ fileset '(1k or 2k) and size(".5KB - 1.5kB")' + 1k + +Test merge states + + $ hg ci -m manychanges + $ hg up -C 0 + * files updated, 0 files merged, * files removed, 0 files unresolved (glob) + $ echo c >> b2 + $ hg ci -m diverging b2 + created new head + $ fileset 'resolved()' + $ fileset 'unresolved()' + $ hg merge + merging b2 + warning: conflicts during merge. + merging b2 incomplete! (edit conflicts, then use 'hg resolve --mark') + * files updated, 0 files merged, * files removed, 1 files unresolved (glob) + use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon + [1] + $ fileset 'resolved()' + $ fileset 'unresolved()' + b2 + $ echo e > b2 + $ hg resolve -m b2 + $ fileset 'resolved()' + b2 + $ fileset 'unresolved()' + $ hg ci -m merge + +Test subrepo predicate + + $ hg init sub + $ echo a > sub/suba + $ hg -R sub add sub/suba + $ hg -R sub ci -m sub + $ echo 'sub = sub' > .hgsub + $ fileset 'subrepo()' + $ hg add .hgsub + $ fileset 'subrepo()' + sub + $ fileset 'subrepo("sub")' + sub + $ fileset 'subrepo("glob:*")' + sub + $ hg ci -m subrepo + +Test with a revision + + $ hg log -G --template '{rev} {desc}\n' + @ 4 subrepo + | + o 3 merge + |\ + | o 2 diverging + | | + o | 1 manychanges + |/ + o 0 addfiles + + $ echo unknown > unknown + $ fileset -r1 'modified()' + b2 + $ fileset -r1 'added() and c1' + c1 + $ fileset -r1 'removed()' + a2 + $ fileset -r1 'deleted()' + $ fileset -r1 'unknown()' + $ fileset -r1 'ignored()' + $ fileset -r1 'hgignore()' + b2 + bin + $ fileset -r1 'binary()' + bin + $ fileset -r1 'size(1k)' + 1k + $ fileset -r3 'resolved()' + $ fileset -r3 'unresolved()' + +#if execbit + $ fileset -r1 'exec()' + b2 +#endif + +#if symlink + $ fileset -r1 'symlink()' + b2link +#endif + + $ fileset -r4 'subrepo("re:su.*")' + sub + $ fileset -r4 'subrepo("sub")' + sub + $ fileset -r4 'b2 or c1' + b2 + c1 +