diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -680,8 +680,25 @@ def binarydecode(repo, stream): return books -def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()): - ui.debug(b"checking for updated bookmarks\n") +def mirroring_remote(ui, repo, remotemarks): + """computes the bookmark changes that set the local bookmarks to + remotemarks""" + changed = [] + localmarks = repo._bookmarks + for (b, id) in pycompat.iteritems(remotemarks): + if id != localmarks.get(b, None) and id in repo: + changed.append((b, id, ui.debug, _(b"updating bookmark %s\n") % b)) + for b in localmarks: + if b not in remotemarks: + changed.append( + (b, None, ui.debug, _(b"removing bookmark %s\n") % b) + ) + return changed + + +def merging_from_remote(ui, repo, remotemarks, path, explicit=()): + """computes the bookmark changes that merge remote bookmarks into the + local bookmarks, based on comparebookmarks""" localmarks = repo._bookmarks ( addsrc, @@ -752,6 +769,15 @@ def updatefromremote(ui, repo, remotemar _(b"remote bookmark %s points to locally missing %s\n") % (b, hex(scid)[:12]) ) + return changed + + +def updatefromremote(ui, repo, remotemarks, path, trfunc, explicit=()): + ui.debug(b"checking for updated bookmarks\n") + if ui.configbool(b'bookmarks', b'mirror'): + changed = mirroring_remote(ui, repo, remotemarks) + else: + changed = merging_from_remote(ui, repo, remotemarks, path, explicit) if changed: tr = trfunc() @@ -760,7 +786,7 @@ def updatefromremote(ui, repo, remotemar for b, node, writer, msg in sorted(changed, key=key): changes.append((b, node)) writer(msg) - localmarks.applychanges(repo, tr, changes) + repo._bookmarks.applychanges(repo, tr, changes) def incoming(ui, repo, peer): diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -207,6 +207,11 @@ coreconfigitem( b'pushing', default=list, ) +coreconfigitem( + b'bookmarks', + b'mirror', + default=False, +) # bundle.mainreporoot: internal hack for bundlerepo coreconfigitem( b'bundle', diff --git a/mercurial/helptext/config.txt b/mercurial/helptext/config.txt --- a/mercurial/helptext/config.txt +++ b/mercurial/helptext/config.txt @@ -418,6 +418,16 @@ Supported arguments: If no suitable authentication entry is found, the user is prompted for credentials as usual if required by the remote. +``bookmarks`` +------------- + +Controls some aspect of bookmarks. + +``mirror`` + When pulling, instead of merging local bookmarks and remote bookmarks, + replace local bookmarks by remote bookmarks. This is useful to replicate + a repository, or as an optimization. (default: False) + ``cmdserver`` ------------- 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 @@ -490,6 +490,30 @@ divergent bookmarks Y 0:4e3505fd9583 Z 1:0d2164f0ce0d +mirroring bookmarks + + $ hg book + @ 1:9b140be10808 + @foo 2:0d2164f0ce0d + X 1:9b140be10808 + X@foo 2:0d2164f0ce0d + Y 0:4e3505fd9583 + Z 2:0d2164f0ce0d + foo -1:000000000000 + * foobar 1:9b140be10808 + $ cp .hg/bookmarks .hg/bookmarks.bak + $ hg book -d X + $ hg pull ../a --config bookmarks.mirror=true + pulling from ../a + searching for changes + no changes found + $ hg book + @ 2:0d2164f0ce0d + X 2:0d2164f0ce0d + Y 0:4e3505fd9583 + Z 2:0d2164f0ce0d + $ mv .hg/bookmarks.bak .hg/bookmarks + explicit pull should overwrite the local version (issue4439) $ hg update -r X