mercurial/bookmarks.py
changeset 17551 a7b3fdaf768d
parent 17550 fc530080013b
child 17625 b83c18204c36
--- a/mercurial/bookmarks.py	Sun Aug 26 00:28:56 2012 +0200
+++ b/mercurial/bookmarks.py	Sun Aug 26 01:28:22 2012 +0200
@@ -7,7 +7,7 @@
 
 from mercurial.i18n import _
 from mercurial.node import hex
-from mercurial import encoding, error, util
+from mercurial import encoding, error, util, obsolete, phases
 import errno, os
 
 def valid(mark):
@@ -255,4 +255,30 @@
 
 def validdest(repo, old, new):
     """Is the new bookmark destination a valid update from the old one"""
-    return new in old.descendants()
+    if old == new:
+        # Old == new -> nothing to update.
+        validdests = ()
+    elif not old:
+        # old is nullrev, anything is valid.
+        # (new != nullrev has been excluded by the previous check)
+        validdests = (new,)
+    elif repo.obsstore:
+        # We only need this complicated logic if there is obsolescence
+        # XXX will probably deserve an optimised rset.
+
+        validdests = set([old])
+        plen = -1
+        # compute the whole set of successors or descendants
+        while len(validdests) != plen:
+            plen = len(validdests)
+            succs = set(c.node() for c in validdests)
+            for c in validdests:
+                if c.phase() > phases.public:
+                    # obsolescence marker does not apply to public changeset
+                    succs.update(obsolete.anysuccessors(repo.obsstore,
+                                                        c.node()))
+            validdests = set(repo.set('%ln::', succs))
+        validdests.remove(old)
+    else:
+        validdests = old.descendants()
+    return new in validdests