[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