[PATCH 6 of 6] bookmark: take successors into account when updating (issue 3561)

pierre-yves.david at logilab.fr pierre-yves.david at logilab.fr
Fri Aug 24 10:15:00 CDT 2012


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at logilab.fr>
# Date 1343843300 -7200
# Node ID db9ca5b3a1e09c43e71e70b82ce615cde29e24b5
# Parent  bb4f46cc1c046702a735ae9ab352302d48614f03
bookmark: take successors into account when updating (issue 3561)

When we rewrite a bookmarked changeset, we want to update the bookmark on it's
successors. But the successors is not a descendant of it's precursor (kind of by
definition). This changeset alter the bookmarks logic to update bookmark
location is the newer location is a successors of the old one[1].

note: that valid destination are in fact any kind of successors of any kind
      of descendants (recursively.)

This changeset required the enabling of the obsolete feature in some bookmark
test.

diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py
--- a/mercurial/bookmarks.py
+++ b/mercurial/bookmarks.py
@@ -5,11 +5,11 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
 from mercurial.i18n import _
 from mercurial.node import hex
-from mercurial import encoding, error, util
+from mercurial import encoding, error, util, obsolete
 import errno, os
 
 def valid(mark):
     for c in (':', '\0', '\n', '\r'):
         if c in mark:
@@ -253,6 +253,21 @@ def diff(ui, repo, remote):
         return 1
     return 0
 
 def validdest(repo, old, new):
     """Is the new bookmark destination a valid update from the old one"""
-    return new in old.descendants()
+    if repo.obsstore and old and old.phase(): # don't apply for public old
+        # XXX will probably deserve and 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:
+                succs.update(obsolete.anysuccessors(repo.obsstore, c.node()))
+            validdests = set(repo.set('%ln::', succs))
+        if old:  # not nullrev
+            validdests.remove(old)
+    else:
+        validdests = old.descendants()
+    return new in validdests
diff --git a/tests/test-bookmarks-pushpull.t b/tests/test-bookmarks-pushpull.t
--- a/tests/test-bookmarks-pushpull.t
+++ b/tests/test-bookmarks-pushpull.t
@@ -1,7 +1,18 @@
   $ "$TESTDIR/hghave" serve || exit 80
 
+  $ cat << EOF >> $HGRCPATH
+  > [phases]
+  > publish=False
+  > [extensions]
+  > EOF
+  $ cat > obs.py << EOF
+  > import mercurial.obsolete
+  > mercurial.obsolete._enabled = True
+  > EOF
+  $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
+
 initialize
 
   $ hg init a
   $ cd a
   $ echo 'test' > test
@@ -38,10 +49,11 @@ import bookmark by name
      Z                         0:4e3505fd9583
   $ hg debugpushkey ../a namespaces
   bookmarks	
   phases	
   namespaces	
+  obsolete	
   $ hg debugpushkey ../a bookmarks
   Y	4e3505fd95835d721066b76e75dbb8cc554d7f77
   X	4e3505fd95835d721066b76e75dbb8cc554d7f77
   Z	4e3505fd95835d721066b76e75dbb8cc554d7f77
   $ hg pull -B X ../a
@@ -196,10 +208,45 @@ diverging a remote bookmark fails
   $ hg -R ../a book
    * X                         1:0d2164f0ce0d
      Y                         3:f6fc62dde3c0
      Z                         1:0d2164f0ce0d
 
+
+Unrelated marker does not alter the decision
+
+  $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+  $ hg push http://localhost:$HGPORT2/
+  pushing to http://localhost:$HGPORT2/
+  searching for changes
+  abort: push creates new remote head 4efff6d98829!
+  (did you forget to merge? use push -f to force)
+  [255]
+  $ hg -R ../a book
+   * X                         1:0d2164f0ce0d
+     Y                         3:f6fc62dde3c0
+     Z                         1:0d2164f0ce0d
+
+Update to a successors works
+
+  $ hg id --debug -r 3
+  f6fc62dde3c0771e29704af56ba4d8af77abcc2f
+  $ hg id --debug -r 4
+  4efff6d98829d9c824c621afd6e3f01865f5439f tip Y
+  $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f 4efff6d98829d9c824c621afd6e3f01865f5439f
+  $ hg push http://localhost:$HGPORT2/
+  pushing to http://localhost:$HGPORT2/
+  searching for changes
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 1 changes to 1 files (+1 heads)
+  updating bookmark Y
+  $ hg -R ../a book
+   * X                         1:0d2164f0ce0d
+     Y                         4:4efff6d98829
+     Z                         1:0d2164f0ce0d
+
 hgweb
 
   $ cat <<EOF > .hg/hgrc
   > [web]
   > push_ssl = false
@@ -212,10 +259,11 @@ hgweb
 
   $ hg debugpushkey http://localhost:$HGPORT/ namespaces
   bookmarks	
   phases	
   namespaces	
+  obsolete	
   $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
   Y	4efff6d98829d9c824c621afd6e3f01865f5439f
   foobar	9b140be1080824d768c5a4691a564088eede71f9
   Z	0d2164f0ce0d8f1d6f94351eba04b794909be66c
   foo	0000000000000000000000000000000000000000
@@ -249,16 +297,16 @@ hgweb
   $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
   requesting all changes
   adding changesets
   adding manifests
   adding file changes
-  added 5 changesets with 5 changes to 3 files (+3 heads)
+  added 4 changesets with 4 changes to 3 files (+2 heads)
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -R cloned-bookmarks bookmarks
      X                         1:9b140be10808
-     Y                         4:4efff6d98829
+     Y                         3:4efff6d98829
      Z                         2:0d2164f0ce0d
      foo                       -1:000000000000
      foobar                    1:9b140be10808
 
   $ cd ..
@@ -268,11 +316,11 @@ bookmark, not all outgoing changes:
   $ hg clone http://localhost:$HGPORT/ addmarks
   requesting all changes
   adding changesets
   adding manifests
   adding file changes
-  added 5 changesets with 5 changes to 3 files (+3 heads)
+  added 4 changesets with 4 changes to 3 files (+2 heads)
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd addmarks
   $ echo foo > foo
   $ hg add foo


More information about the Mercurial-devel mailing list