idlsoft created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers.
REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D6776 AFFECTED FILES mercurial/bundle2.py mercurial/exchange.py mercurial/localrepo.py tests/test-bookmarksconflict.t CHANGE DETAILS diff --git a/tests/test-bookmarksconflict.t b/tests/test-bookmarksconflict.t new file mode 100644 --- /dev/null +++ b/tests/test-bookmarksconflict.t @@ -0,0 +1,84 @@ +initialize + $ make_changes() { + > d=`pwd` + > [ ! -z $1 ] && cd $1 + > echo "test `basename \`pwd\``" >> test + > hg commit -Am"${2:-test}" + > r=$? + > cd $d + > return $r + > } + $ ls -1a + . + .. + $ hg init a + $ cd a + $ echo 'test' > test; hg commit -Am'test' + adding test + $ hg book @ + +clone to b + + $ mkdir ../b + $ cd ../b + $ hg clone ../a . + updating to bookmark @ + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_changes + $ hg book bk_b + +clone to c + $ mkdir ../c + $ cd ../c + $ hg clone ../a . + updating to bookmark @ + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ make_changes + $ hg book bk_c + +push from b + $ cd ../b + $ hg push -B . + pushing to $TESTTMP/a + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + updating bookmark @ + exporting bookmark bk_b + $ hg -R ../a id -r @ + e11a942451be tip @/bk_b + +push from c + $ cd ../c + $ hg push -B . + pushing to $TESTTMP/a + searching for changes + remote has heads on branch 'default' that are not known locally: e11a942451be + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + exporting bookmark bk_c + $ hg push -B @ + pushing to $TESTTMP/a + searching for changes + no changes found + abort: push rejected: bookmark "@" has changed + (run 'hg pull', resolve conflicts, and push again) + [255] + $ hg -R ../a book + * @ 1:e11a942451be + bk_b 1:e11a942451be + bk_c 2:110743c8a16c + $ hg push -B @ --force + pushing to $TESTTMP/a + searching for changes + no changes found + updating bookmark @ + [1] + $ hg -R ../a book + * @ 2:110743c8a16c + bk_b 1:e11a942451be + bk_c 2:110743c8a16c diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -307,14 +307,14 @@ raise error.Abort(_('cannot perform stream clone against local ' 'peer')) - def unbundle(self, bundle, heads, url): + def unbundle(self, bundle, heads, url, force=None): """apply a bundle on a repo This function handles the repo locking itself.""" try: try: bundle = exchange.readbundle(self.ui, bundle, None) - ret = exchange.unbundle(self._repo, bundle, heads, 'push', url) + ret = exchange.unbundle(self._repo, bundle, heads, 'push', url, force=force) if util.safehasattr(ret, 'getchunks'): # This is a bundle20 object, turn it into an unbundler. # This little dance should be dropped eventually when the diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -1149,6 +1149,7 @@ 'bundle': stream, 'heads': ['force'], 'url': pushop.remote.url(), + 'force': pushop.force, }).result() except error.BundleValueError as exc: raise error.Abort(_('missing support for %s') % exc) @@ -2362,7 +2363,7 @@ raise error.PushRaced('repository changed while %s - ' 'please try again' % context) -def unbundle(repo, cg, heads, source, url): +def unbundle(repo, cg, heads, source, url, force=None): """Apply a bundle to a repo. this function makes sure the repo is locked during the application and have @@ -2410,7 +2411,8 @@ op = bundle2.bundleoperation(repo, gettransaction, captureoutput=captureoutput, - source='push') + source='push', + force=force) try: op = bundle2.processbundle(repo, cg, op=op) finally: diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py --- a/mercurial/bundle2.py +++ b/mercurial/bundle2.py @@ -299,7 +299,7 @@ * a way to construct a bundle response when applicable. """ - def __init__(self, repo, transactiongetter, captureoutput=True, source=''): + def __init__(self, repo, transactiongetter, captureoutput=True, source='', force=False): self.repo = repo self.ui = repo.ui self.records = unbundlerecords() @@ -310,6 +310,7 @@ # carries value that can modify part behavior self.modes = {} self.source = source + self.force = force def gettransaction(self): transaction = self._gettransaction() @@ -2135,17 +2136,23 @@ if bookmarksmode == 'apply': tr = op.gettransaction() bookstore = op.repo._bookmarks + allhooks = [] + for book, node in changes: + old_node = bookstore.get(book, '') + if not op.force and old_node != '' and node is not None: + if not bookmarks.validdest(op.repo, op.repo[old_node], op.repo[node]): + raise error.Abort(_('push rejected: bookmark "%s" has changed') % book, + hint=_("run 'hg pull', resolve conflicts, and push again")) + hookargs = tr.hookargs.copy() + hookargs['pushkeycompat'] = '1' + hookargs['namespace'] = 'bookmarks' + hookargs['key'] = book + hookargs['old'] = nodemod.hex(old_node) + hookargs['new'] = nodemod.hex(node if node is not None else '') + hookargs['force'] = op.force + allhooks.append(hookargs) + if pushkeycompat: - allhooks = [] - for book, node in changes: - hookargs = tr.hookargs.copy() - hookargs['pushkeycompat'] = '1' - hookargs['namespace'] = 'bookmarks' - hookargs['key'] = book - hookargs['old'] = nodemod.hex(bookstore.get(book, '')) - hookargs['new'] = nodemod.hex(node if node is not None else '') - allhooks.append(hookargs) - for hookargs in allhooks: op.repo.hook('prepushkey', throw=True, **pycompat.strkwargs(hookargs)) To: idlsoft, #hg-reviewers Cc: mercurial-devel _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel