--- 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