--- a/mercurial/bundle2.py Tue Oct 17 15:39:34 2017 +0200
+++ b/mercurial/bundle2.py Tue Oct 17 15:26:16 2017 +0200
@@ -1982,40 +1982,55 @@
def handlebookmark(op, inpart):
"""transmit bookmark information
- The part contains binary encoded bookmark information. The bookmark
- information is applied as is to the unbundling repository. Make sure a
- 'check:bookmarks' part is issued earlier to check for race condition in
- such update.
+ The part contains binary encoded bookmark information.
+
+ The exact behavior of this part can be controlled by the 'bookmarks' mode
+ on the bundle operation.
- This behavior is suitable for pushing. Semantic adjustment will be needed
- for pull.
+ When mode is 'apply' (the default) the bookmark information is applied as
+ is to the unbundling repository. Make sure a 'check:bookmarks' part is
+ issued earlier to check for push races in such update. This behavior is
+ suitable for pushing.
+
+ When mode is 'records', the information is recorded into the 'bookmarks'
+ records of the bundle operation. This behavior is suitable for pulling.
"""
changes = bookmarks.binarydecode(inpart)
- tr = op.gettransaction()
- bookstore = op.repo._bookmarks
+ pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
+ bookmarksmode = op.modes.get('bookmarks', 'apply')
- pushkeycompat = op.repo.ui.configbool('server', 'bookmarks-pushkey-compat')
- if pushkeycompat:
- allhooks = []
+ if bookmarksmode == 'apply':
+ tr = op.gettransaction()
+ bookstore = op.repo._bookmarks
+ if pushkeycompat:
+ allhooks = []
+ for book, node in changes:
+ hookargs = tr.hookargs.copy()
+ hookargs['pushkeycompat'] = '1'
+ hookargs['namespace'] = 'bookmark'
+ 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, **hookargs)
+
+ bookstore.applychanges(op.repo, op.gettransaction(), changes)
+
+ if pushkeycompat:
+ def runhook():
+ for hookargs in allhooks:
+ op.repo.hook('prepushkey', **hookargs)
+ op.repo._afterlock(runhook)
+
+ elif bookmarksmode == 'records':
for book, node in changes:
- hookargs = tr.hookargs.copy()
- hookargs['pushkeycompat'] = '1'
- hookargs['namespace'] = 'bookmark'
- 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, **hookargs)
-
- bookstore.applychanges(op.repo, tr, changes)
-
- if pushkeycompat:
- def runhook():
- for hookargs in allhooks:
- op.repo.hook('prepushkey', **hookargs)
- op.repo._afterlock(runhook)
+ record = {'bookmark': book, 'node': node}
+ op.records.add('bookmarks', record)
+ else:
+ raise error.ProgrammingError('unkown bookmark mode: %s' % bookmarksmode)
@parthandler('phase-heads')
def handlephases(op, inpart):