# HG changeset patch # User Valentin Gatien-Baron # Date 2020-02-14 03:51:17 # Node ID 8407031f195f77f8cacd0a6bd180a4a0045da423 # Parent 0275000564c453a85e89eddfab1a357e6aeae327 bookmarks: prevent pushes of divergent bookmarks (foo@remote) Before this change, such bookmarks are write-only: a client can push them but not pull/read them. And because these bookmark can't be read, even pushes are limited (for instance trying to delete such a bookmark fails with a vanilla client because the client thinks the bookmark is neither on the local nor the remote). This change makes the server refuses such bookmarks, and for earlier errors, makes the client refuse to send them. I think the change of behavior is acceptable because I think this is a bug in push/pull, and I don't think we change the behavior of `hg unbundle`, because it doesn't seem that `hg bundle` ever store bookmarks (and even if it did, it would seem weird anyway to try to send divergent bookmarks). Differential Revision: https://phab.mercurial-scm.org/D8117 diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -487,6 +487,8 @@ def listbookmarks(repo): def pushbookmark(repo, key, old, new): + if isdivergent(key): + return False if bookmarksinstore(repo): wlock = util.nullcontextmanager() else: diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -2368,6 +2368,11 @@ def handlebookmark(op, inpart): b'prepushkey', throw=True, **pycompat.strkwargs(hookargs) ) + for book, node in changes: + if bookmarks.isdivergent(book): + msg = _(b'cannot accept divergent bookmark %s!') % book + raise error.Abort(msg) + bookstore.applychanges(op.repo, op.gettransaction(), changes) if pushkeycompat: diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -856,7 +856,11 @@ def _processcompared(pushop, pushed, exp for b, scid, dcid in addsrc: if b in explicit: explicit.remove(b) - pushop.outbookmarks.append((b, b'', scid)) + if bookmod.isdivergent(b): + pushop.ui.warn(_(b'cannot push divergent bookmark %s!\n') % b) + pushop.bkresult = 2 + else: + pushop.outbookmarks.append((b, b'', scid)) # search for overwritten bookmark for b, scid, dcid in list(advdst) + list(diverge) + list(differ): if b in explicit: diff --git a/relnotes/next b/relnotes/next --- a/relnotes/next +++ b/relnotes/next @@ -24,6 +24,7 @@ * Use `hg copy --forget --at-rev REV` to unmark already committed copies. + * prevent pushes of divergent bookmarks (foo@remote) == Bug Fixes == 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 @@ -328,6 +328,17 @@ delete a remote bookmark #endif +Divergent bookmark cannot be exported + + $ hg book W@default + $ hg push -B W@default ../a + pushing to ../a + searching for changes + cannot push divergent bookmark W@default! + no changes found + [2] + $ hg book -d W@default + export the active bookmark $ hg bookmark V