comparison mercurial/localrepo.py @ 15956:5653f2d166ea stable

push: prevent moving phases outside of the pushed subset
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Fri, 20 Jan 2012 21:21:13 +0100
parents ec8a9e06cf05
children ba959f6e10f8
comparison
equal deleted inserted replaced
15955:5a14f48d6b9a 15956:5653f2d166ea
1552 clstart = len(self.changelog) 1552 clstart = len(self.changelog)
1553 result = self.addchangegroup(cg, 'pull', remote.url()) 1553 result = self.addchangegroup(cg, 'pull', remote.url())
1554 clend = len(self.changelog) 1554 clend = len(self.changelog)
1555 added = [self.changelog.node(r) for r in xrange(clstart, clend)] 1555 added = [self.changelog.node(r) for r in xrange(clstart, clend)]
1556 1556
1557 # compute target subset
1558 if heads is None:
1559 # We pulled every thing possible
1560 # sync on everything common
1561 subset = common + added
1562 else:
1563 # We pulled a specific subset
1564 # sync on this subset
1565 subset = heads
1557 1566
1558 # Get remote phases data from remote 1567 # Get remote phases data from remote
1559 remotephases = remote.listkeys('phases') 1568 remotephases = remote.listkeys('phases')
1560 publishing = bool(remotephases.get('publishing', False)) 1569 publishing = bool(remotephases.get('publishing', False))
1561 if remotephases and not publishing: 1570 if remotephases and not publishing:
1562 # remote is new and unpublishing 1571 # remote is new and unpublishing
1563 subset = common + added
1564 pheads, _dr = phases.analyzeremotephases(self, subset, 1572 pheads, _dr = phases.analyzeremotephases(self, subset,
1565 remotephases) 1573 remotephases)
1566 phases.advanceboundary(self, phases.public, pheads) 1574 phases.advanceboundary(self, phases.public, pheads)
1567 phases.advanceboundary(self, phases.draft, common + added) 1575 phases.advanceboundary(self, phases.draft, subset)
1568 else: 1576 else:
1569 # Remote is old or publishing all common changesets 1577 # Remote is old or publishing all common changesets
1570 # should be seen as public 1578 # should be seen as public
1571 phases.advanceboundary(self, phases.public, common + added) 1579 phases.advanceboundary(self, phases.public, subset)
1572 finally: 1580 finally:
1573 lock.release() 1581 lock.release()
1574 1582
1575 return result 1583 return result
1576 1584
1650 ret = remote.unbundle(cg, remoteheads, 'push') 1658 ret = remote.unbundle(cg, remoteheads, 'push')
1651 else: 1659 else:
1652 # we return an integer indicating remote head count change 1660 # we return an integer indicating remote head count change
1653 ret = remote.addchangegroup(cg, 'push', self.url()) 1661 ret = remote.addchangegroup(cg, 'push', self.url())
1654 1662
1655 cheads = outgoing.commonheads[:]
1656 if ret: 1663 if ret:
1657 # push succeed, synchonize common + pushed 1664 # push succeed, synchonize target of the push
1658 # this is a no-op if there was nothing to push 1665 cheads = outgoing.missingheads
1659 cheads += outgoing.missingheads 1666 elif revs is None:
1667 # All out push fails. synchronize all common
1668 cheads = outgoing.commonheads
1669 else:
1670 # I want cheads = heads(::missingheads and ::commonheads)
1671 # (missingheads is revs with secret changeset filtered out)
1672 #
1673 # This can be expressed as:
1674 # cheads = ( (missingheads and ::commonheads)
1675 # + (commonheads and ::missingheads))"
1676 # )
1677 #
1678 # while trying to push we already computed the following:
1679 # common = (::commonheads)
1680 # missing = ((commonheads::missingheads) - commonheads)
1681 #
1682 # We can pick:
1683 # * missingheads part of comon (::commonheads)
1684 common = set(outgoing.common)
1685 cheads = [n for node in revs if n in common]
1686 # and
1687 # * commonheads parents on missing
1688 rvset = repo.revset('%ln and parents(roots(%ln))',
1689 outgoing.commonheads,
1690 outgoing.missing)
1691 cheads.extend(c.node() for c in rvset)
1660 # even when we don't push, exchanging phase data is useful 1692 # even when we don't push, exchanging phase data is useful
1661 remotephases = remote.listkeys('phases') 1693 remotephases = remote.listkeys('phases')
1662 if not remotephases: # old server or public only repo 1694 if not remotephases: # old server or public only repo
1663 phases.advanceboundary(self, phases.public, cheads) 1695 phases.advanceboundary(self, phases.public, cheads)
1664 # don't push any phase data as there is nothing to push 1696 # don't push any phase data as there is nothing to push