Mercurial > hg-stable
comparison 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 |
comparison
equal
deleted
inserted
replaced
7232:c2ac09f81ec9 | 7233:9f0e52e1df77 |
---|---|
1575 where the keys are the filenames (or 1 for the manifest), and the | 1575 where the keys are the filenames (or 1 for the manifest), and the |
1576 values are lists of (node, linknode) tuples, where node is a wanted | 1576 values are lists of (node, linknode) tuples, where node is a wanted |
1577 node and linknode is the changelog node that should be transmitted as | 1577 node and linknode is the changelog node that should be transmitted as |
1578 the linkrev. | 1578 the linkrev. |
1579 """ | 1579 """ |
1580 | |
1581 if extranodes is None: | |
1582 # can we go through the fast path ? | |
1583 heads.sort() | |
1584 allheads = self.heads() | |
1585 allheads.sort() | |
1586 if heads == allheads: | |
1587 common = [] | |
1588 # parents of bases are known from both sides | |
1589 for n in bases: | |
1590 for p in self.changelog.parents(n): | |
1591 if p != nullid: | |
1592 common.append(p) | |
1593 return self._changegroup(common, source) | |
1580 | 1594 |
1581 self.hook('preoutgoing', throw=True, source=source) | 1595 self.hook('preoutgoing', throw=True, source=source) |
1582 | 1596 |
1583 # Set up some initial variables | 1597 # Set up some initial variables |
1584 # Make it easy to refer to self.changelog | 1598 # Make it easy to refer to self.changelog |
1852 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source) | 1866 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source) |
1853 | 1867 |
1854 return util.chunkbuffer(gengroup()) | 1868 return util.chunkbuffer(gengroup()) |
1855 | 1869 |
1856 def changegroup(self, basenodes, source): | 1870 def changegroup(self, basenodes, source): |
1871 # to avoid a race we use changegroupsubset() (issue1320) | |
1872 return self.changegroupsubset(basenodes, self.heads(), source) | |
1873 | |
1874 def _changegroup(self, common, source): | |
1857 """Generate a changegroup of all nodes that we have that a recipient | 1875 """Generate a changegroup of all nodes that we have that a recipient |
1858 doesn't. | 1876 doesn't. |
1859 | 1877 |
1860 This is much easier than the previous function as we can assume that | 1878 This is much easier than the previous function as we can assume that |
1861 the recipient has any changenode we aren't sending them.""" | 1879 the recipient has any changenode we aren't sending them. |
1880 | |
1881 common is the set of common nodes between remote and self""" | |
1862 | 1882 |
1863 self.hook('preoutgoing', throw=True, source=source) | 1883 self.hook('preoutgoing', throw=True, source=source) |
1864 | 1884 |
1865 cl = self.changelog | 1885 cl = self.changelog |
1866 nodes = cl.nodesbetween(basenodes, None)[0] | 1886 nodes = cl.findmissing(common) |
1867 revset = dict.fromkeys([cl.rev(n) for n in nodes]) | 1887 revset = dict.fromkeys([cl.rev(n) for n in nodes]) |
1868 self.changegroupinfo(nodes, source) | 1888 self.changegroupinfo(nodes, source) |
1869 | 1889 |
1870 def identity(x): | 1890 def identity(x): |
1871 return x | 1891 return x |