comparison mercurial/exchange.py @ 32709:16ada4cbb1a9

push: add a way to allow concurrent pushes on unrelated heads Client has a mechanism for the server to check that nothing changed server side since the client prepared a push. That check is wide and any head changed on the server will lead to an aborted push. We introduce a way for the client to send a less strict checking. That logic will check that no heads impacted by the push have been affected. If other unrelated heads (including named branches heads) have been affected, the push will proceed. This is very helpful for repositories with high developers traffic on different heads, a common setup. That behavior is currently controlled by an experimental option. The config should live in the "server" section but bike-shedding of the name will happen in the next changesets. Servers advertise this capability through a new bundle2 capability 'checkeads', using the value 'related'. The 'test-push-race.t' is updated to check that new capabilities on the documented cases.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 29 May 2017 05:53:58 +0200
parents 9929af2b09b4
children a470bbb4e3af
comparison
equal deleted inserted replaced
32708:90cb4ec8df64 32709:16ada4cbb1a9
321 self.cgresult = None 321 self.cgresult = None
322 # Boolean value for the bookmark push 322 # Boolean value for the bookmark push
323 self.bkresult = None 323 self.bkresult = None
324 # discover.outgoing object (contains common and outgoing data) 324 # discover.outgoing object (contains common and outgoing data)
325 self.outgoing = None 325 self.outgoing = None
326 # all remote heads before the push 326 # all remote topological heads before the push
327 self.remoteheads = None 327 self.remoteheads = None
328 # Details of the remote branch pre and post push
329 #
330 # mapping: {'branch': ([remoteheads],
331 # [newheads],
332 # [unsyncedheads],
333 # [discardedheads])}
334 # - branch: the branch name
335 # - remoteheads: the list of remote heads known locally
336 # None if the branch is new
337 # - newheads: the new remote heads (known locally) with outgoing pushed
338 # - unsyncedheads: the list of remote heads unknown locally.
339 # - discardedheads: the list of remote heads made obsolete by the push
340 self.pushbranchmap = None
328 # testable as a boolean indicating if any nodes are missing locally. 341 # testable as a boolean indicating if any nodes are missing locally.
329 self.incoming = None 342 self.incoming = None
330 # phases changes that must be pushed along side the changesets 343 # phases changes that must be pushed along side the changesets
331 self.outdatedphases = None 344 self.outdatedphases = None
332 # phases changes that must be pushed if changeset push fails 345 # phases changes that must be pushed if changeset push fails
710 def _pushb2ctxcheckheads(pushop, bundler): 723 def _pushb2ctxcheckheads(pushop, bundler):
711 """Generate race condition checking parts 724 """Generate race condition checking parts
712 725
713 Exists as an independent function to aid extensions 726 Exists as an independent function to aid extensions
714 """ 727 """
715 if not pushop.force: 728 # * 'force' do not check for push race,
716 bundler.newpart('check:heads', data=iter(pushop.remoteheads)) 729 # * if we don't push anything, there are nothing to check.
730 if not pushop.force and pushop.outgoing.missingheads:
731 allowunrelated = 'related' in bundler.capabilities.get('checkheads', ())
732 if not allowunrelated:
733 bundler.newpart('check:heads', data=iter(pushop.remoteheads))
734 else:
735 affected = set()
736 for branch, heads in pushop.pushbranchmap.iteritems():
737 remoteheads, newheads, unsyncedheads, discardedheads = heads
738 if remoteheads is not None:
739 remote = set(remoteheads)
740 affected |= set(discardedheads) & remote
741 affected |= remote - set(newheads)
742 if affected:
743 data = iter(sorted(affected))
744 bundler.newpart('check:updated-heads', data=data)
717 745
718 @b2partsgenerator('changeset') 746 @b2partsgenerator('changeset')
719 def _pushb2ctx(pushop, bundler): 747 def _pushb2ctx(pushop, bundler):
720 """handle changegroup push through bundle2 748 """handle changegroup push through bundle2
721 749