Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/commands.py @ 41054:bad05a6afdc8
pull: fix inconsistent view of bookmarks during pull (issue4700)
I had a share where a pull apparently pulled a bookmark but not the
revision pointed to by the bookmark, which I suspect is due to this
(and if not, we might as well remove known issues in this area).
I do this by combining doing all the queries that could read the
bookmarks in one round trip.
I had to change the handling of the case where the server doesn't
support the lookup query, because if it fails, it would otherwise make
fremotebookmark.result() block forever. This is due to
wireprotov1peer.peerexecutor.sendcommands's behavior (it fills a
single future if any query fails synchronously and leaves all other
futures unchanged), but I don't know if the fix is to cancel all other
futures, or to keep going with the other queries.
Differential Revision: https://phab.mercurial-scm.org/D5449
author | Valentin Gatien-Baron <valentin.gatienbaron@gmail.com> |
---|---|
date | Thu, 20 Dec 2018 22:28:39 -0500 |
parents | 92c574684f75 |
children | 4506f801e492 |
comparison
equal
deleted
inserted
replaced
41053:6faaf3a1c6ec | 41054:bad05a6afdc8 |
---|---|
4412 other = hg.peer(repo, opts, source) | 4412 other = hg.peer(repo, opts, source) |
4413 try: | 4413 try: |
4414 revs, checkout = hg.addbranchrevs(repo, other, branches, | 4414 revs, checkout = hg.addbranchrevs(repo, other, branches, |
4415 opts.get('rev')) | 4415 opts.get('rev')) |
4416 | 4416 |
4417 | |
4418 pullopargs = {} | 4417 pullopargs = {} |
4419 if opts.get('bookmark'): | 4418 |
4420 if not revs: | 4419 nodes = None |
4421 revs = [] | 4420 if opts['bookmark'] or revs: |
4422 # The list of bookmark used here is not the one used to actually | 4421 # The list of bookmark used here is the same used to actually update |
4423 # update the bookmark name. This can result in the revision pulled | 4422 # the bookmark names, to avoid the race from issue 4689 and we do |
4424 # not ending up with the name of the bookmark because of a race | 4423 # all lookup and bookmark queries in one go so they see the same |
4425 # condition on the server. (See issue 4689 for details) | 4424 # version of the server state (issue 4700). |
4426 remotebookmarks = other.listkeys('bookmarks') | 4425 nodes = [] |
4426 fnodes = [] | |
4427 revs = revs or [] | |
4428 if revs and not other.capable('lookup'): | |
4429 err = _("other repository doesn't support revision lookup, " | |
4430 "so a rev cannot be specified.") | |
4431 raise error.Abort(err) | |
4432 with other.commandexecutor() as e: | |
4433 fremotebookmarks = e.callcommand('listkeys', { | |
4434 'namespace': 'bookmarks' | |
4435 }) | |
4436 for r in revs: | |
4437 fnodes.append(e.callcommand('lookup', {'key': r})) | |
4438 remotebookmarks = fremotebookmarks.result() | |
4427 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks) | 4439 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks) |
4428 pullopargs['remotebookmarks'] = remotebookmarks | 4440 pullopargs['remotebookmarks'] = remotebookmarks |
4429 for b in opts['bookmark']: | 4441 for b in opts['bookmark']: |
4430 b = repo._bookmarks.expandname(b) | 4442 b = repo._bookmarks.expandname(b) |
4431 if b not in remotebookmarks: | 4443 if b not in remotebookmarks: |
4432 raise error.Abort(_('remote bookmark %s not found!') % b) | 4444 raise error.Abort(_('remote bookmark %s not found!') % b) |
4433 revs.append(hex(remotebookmarks[b])) | 4445 nodes.append(remotebookmarks[b]) |
4434 | 4446 for i, rev in enumerate(revs): |
4435 if revs: | 4447 node = fnodes[i].result() |
4436 try: | 4448 nodes.append(node) |
4437 # When 'rev' is a bookmark name, we cannot guarantee that it | 4449 if rev == checkout: |
4438 # will be updated with that name because of a race condition | 4450 checkout = node |
4439 # server side. (See issue 4689 for details) | |
4440 oldrevs = revs | |
4441 revs = [] # actually, nodes | |
4442 for r in oldrevs: | |
4443 with other.commandexecutor() as e: | |
4444 node = e.callcommand('lookup', {'key': r}).result() | |
4445 | |
4446 revs.append(node) | |
4447 if r == checkout: | |
4448 checkout = node | |
4449 except error.CapabilityError: | |
4450 err = _("other repository doesn't support revision lookup, " | |
4451 "so a rev cannot be specified.") | |
4452 raise error.Abort(err) | |
4453 | 4451 |
4454 wlock = util.nullcontextmanager() | 4452 wlock = util.nullcontextmanager() |
4455 if opts.get('update'): | 4453 if opts.get('update'): |
4456 wlock = repo.wlock() | 4454 wlock = repo.wlock() |
4457 with wlock: | 4455 with wlock: |
4458 pullopargs.update(opts.get('opargs', {})) | 4456 pullopargs.update(opts.get('opargs', {})) |
4459 modheads = exchange.pull(repo, other, heads=revs, | 4457 modheads = exchange.pull(repo, other, heads=nodes, |
4460 force=opts.get('force'), | 4458 force=opts.get('force'), |
4461 bookmarks=opts.get('bookmark', ()), | 4459 bookmarks=opts.get('bookmark', ()), |
4462 opargs=pullopargs).cgresult | 4460 opargs=pullopargs).cgresult |
4463 | 4461 |
4464 # brev is a name, which might be a bookmark to be activated at | 4462 # brev is a name, which might be a bookmark to be activated at |