mercurial/revset.py
changeset 24446 582cfcc843c7
parent 24419 0e41f110e69e
child 24457 c5022f3579b9
--- 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,