diff -r c71edbafe603 -r 582cfcc843c7 mercurial/revset.py --- a/mercurial/revset.py Tue Mar 24 20:28:39 2015 -0700 +++ b/mercurial/revset.py Wed Mar 25 14:56:54 2015 -0400 @@ -1755,6 +1755,49 @@ l.sort() return baseset([e[-1] for e in l]) +def subrepo(repo, subset, x): + """``subrepo([pattern])`` + Changesets that add, modify or remove the given subrepo. If no subrepo + pattern is named, any subrepo changes are returned. + """ + # i18n: "subrepo" is a keyword + args = getargs(x, 0, 1, _('subrepo takes at most one argument')) + if len(args) != 0: + pat = getstring(args[0], _("subrepo requires a pattern")) + + m = matchmod.exact(repo.root, repo.root, ['.hgsubstate']) + + def submatches(names): + k, p, m = _stringmatcher(pat) + for name in names: + if m(name): + yield name + + def matches(x): + c = repo[x] + s = repo.status(c.p1().node(), c.node(), match=m) + + if len(args) == 0: + return s.added or s.modified or s.removed + + if s.added: + return util.any(submatches(c.substate.keys())) + + if s.modified: + subs = set(c.p1().substate.keys()) + subs.update(c.substate.keys()) + + for path in submatches(subs): + if c.p1().substate.get(path) != c.substate.get(path): + return True + + if s.removed: + return util.any(submatches(c.p1().substate.keys())) + + return False + + return subset.filter(matches) + def _stringmatcher(pattern): """ accepts a string, possibly starting with 're:' or 'literal:' prefix. @@ -1952,6 +1995,7 @@ "roots": roots, "sort": sort, "secret": secret, + "subrepo": subrepo, "matching": matching, "tag": tag, "tagged": tagged,