comparison mercurial/commands.py @ 25425:9263f86b9681 stable

pull: avoid race condition with 'hg pull --rev name --update' (issue4706) The previous scheme was: 1) lookup node for all pulled revision, 2) pull said node 3) lookup the node of the checkout target 4) update the repository there. If the remote repo changes between (1) and (3), the resolved name will be different and (3) crash. There is actually no need for a remote lookup during (3), we could just set the value in (1). This prevent the race condition and save a possible network roundtrip.
author Pierre-Yves David <pierre-yves.david@fb.com>
date Wed, 03 Jun 2015 14:29:11 -0700
parents a4ee6f774f14
children d0c7ffc4c8bc 8dd0b23161bf
comparison
equal deleted inserted replaced
25396:78e8890cfb4b 25425:9263f86b9681
5110 raise util.Abort(_('remote bookmark %s not found!') % b) 5110 raise util.Abort(_('remote bookmark %s not found!') % b)
5111 revs.append(remotebookmarks[b]) 5111 revs.append(remotebookmarks[b])
5112 5112
5113 if revs: 5113 if revs:
5114 try: 5114 try:
5115 revs = [other.lookup(rev) for rev in revs] 5115 oldrevs = revs
5116 revs = [] # actually, nodes
5117 for r in oldrevs:
5118 node = other.lookup(r)
5119 revs.append(node)
5120 if r == checkout:
5121 checkout = node
5116 except error.CapabilityError: 5122 except error.CapabilityError:
5117 err = _("other repository doesn't support revision lookup, " 5123 err = _("other repository doesn't support revision lookup, "
5118 "so a rev cannot be specified.") 5124 "so a rev cannot be specified.")
5119 raise util.Abort(err) 5125 raise util.Abort(err)
5120 5126
5121 modheads = exchange.pull(repo, other, heads=revs, 5127 modheads = exchange.pull(repo, other, heads=revs,
5122 force=opts.get('force'), 5128 force=opts.get('force'),
5123 bookmarks=opts.get('bookmark', ())).cgresult 5129 bookmarks=opts.get('bookmark', ())).cgresult
5124 if checkout: 5130 if checkout:
5125 checkout = str(repo.changelog.rev(other.lookup(checkout))) 5131 checkout = str(repo.changelog.rev(checkout))
5126 repo._subtoppath = source 5132 repo._subtoppath = source
5127 try: 5133 try:
5128 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout) 5134 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5129 5135
5130 finally: 5136 finally: