mercurial/revset.py
changeset 17186 a3da6f298592
parent 17185 2c7c4824969e
child 17244 483aa765f6c4
--- a/mercurial/revset.py	Sat Jul 07 00:47:30 2012 -0400
+++ b/mercurial/revset.py	Sat Jul 07 00:47:55 2012 -0400
@@ -561,6 +561,50 @@
     # Like ``descendants(set)`` but follows only the first parents.
     return _descendants(repo, subset, x, followfirst=True)
 
+def destination(repo, subset, x):
+    """``destination([set])``
+    Changesets that were created by a graft, transplant or rebase operation,
+    with the given revisions specified as the source.  Omitting the optional set
+    is the same as passing all().
+    """
+    if x is not None:
+        args = set(getset(repo, range(len(repo)), x))
+    else:
+        args = set(getall(repo, range(len(repo)), x))
+
+    dests = set()
+
+    # subset contains all of the possible destinations that can be returned, so
+    # iterate over them and see if their source(s) were provided in the args.
+    # Even if the immediate src of r is not in the args, src's source (or
+    # further back) may be.  Scanning back further than the immediate src allows
+    # transitive transplants and rebases to yield the same results as transitive
+    # grafts.
+    for r in subset:
+        src = _getrevsource(repo, r)
+        lineage = None
+
+        while src is not None:
+            if lineage is None:
+                lineage = list()
+
+            lineage.append(r)
+
+            # The visited lineage is a match if the current source is in the arg
+            # set.  Since every candidate dest is visited by way of iterating
+            # subset, any dests futher back in the lineage will be tested by a
+            # different iteration over subset.  Likewise, if the src was already
+            # selected, the current lineage can be selected without going back
+            # further.
+            if src in args or src in dests:
+                dests.update(lineage)
+                break
+
+            r = src
+            src = _getrevsource(repo, r)
+
+    return [r for r in subset if r in dests]
+
 def draft(repo, subset, x):
     """``draft()``
     Changeset in draft phase."""
@@ -1399,6 +1443,7 @@
     "desc": desc,
     "descendants": descendants,
     "_firstdescendants": _firstdescendants,
+    "destination": destination,
     "draft": draft,
     "extinct": extinct,
     "extra": extra,