Mercurial > hg-stable
diff mercurial/localrepo.py @ 7233:9f0e52e1df77
fix pull racing with push/commit (issue1320)
changegroup() has a problem when nodes which does not descend from a node
in <bases> are added to remote after the discovery phase.
If that happens, changegroup() won't send the correct set of nodes, ie.
some nodes will be missing.
To correct it we have to find the set of nodes that both remote and self
have (called <common>), and send all the nodes not in <common>.
This fix has some overhead, in the worst case it will re-send a whole branch.
A proper fix to avoid this overhead might be to change the protocol so that
the <common> nodes are sent (instead of the <bases> of the missing nodes).
author | Benoit Boissinot <benoit.boissinot@ens-lyon.org> |
---|---|
date | Tue, 21 Oct 2008 17:00:35 +0200 |
parents | 7946503ec76e |
children | ae70fe6143fc |
line wrap: on
line diff
--- a/mercurial/localrepo.py Thu Oct 23 23:03:09 2008 +0200 +++ b/mercurial/localrepo.py Tue Oct 21 17:00:35 2008 +0200 @@ -1578,6 +1578,20 @@ the linkrev. """ + if extranodes is None: + # can we go through the fast path ? + heads.sort() + allheads = self.heads() + allheads.sort() + if heads == allheads: + common = [] + # parents of bases are known from both sides + for n in bases: + for p in self.changelog.parents(n): + if p != nullid: + common.append(p) + return self._changegroup(common, source) + self.hook('preoutgoing', throw=True, source=source) # Set up some initial variables @@ -1854,16 +1868,22 @@ return util.chunkbuffer(gengroup()) def changegroup(self, basenodes, source): + # to avoid a race we use changegroupsubset() (issue1320) + return self.changegroupsubset(basenodes, self.heads(), source) + + def _changegroup(self, common, source): """Generate a changegroup of all nodes that we have that a recipient doesn't. This is much easier than the previous function as we can assume that - the recipient has any changenode we aren't sending them.""" + the recipient has any changenode we aren't sending them. + + common is the set of common nodes between remote and self""" self.hook('preoutgoing', throw=True, source=source) cl = self.changelog - nodes = cl.nodesbetween(basenodes, None)[0] + nodes = cl.findmissing(common) revset = dict.fromkeys([cl.rev(n) for n in nodes]) self.changegroupinfo(nodes, source)