comparison mercurial/localrepo.py @ 15820:2673006f7989

phases: fix phase synchronization on push The bugs seemed to show up when element not in future common changeset should hold new hold phase data. The whole phase push machinery was rewritten in the process.
author Pierre-Yves David <pierre-yves.david@ens-lyon.org>
date Wed, 04 Jan 2012 01:12:31 +0100
parents 57241845a4bb
children cd956049fc14
comparison
equal deleted inserted replaced
15819:33ca11b010e2 15820:2673006f7989
1630 ### Apply local phase on remote 1630 ### Apply local phase on remote
1631 # 1631 #
1632 # XXX If push failed we should use strict common and not 1632 # XXX If push failed we should use strict common and not
1633 # future to avoir pushing phase data on unknown changeset. 1633 # future to avoir pushing phase data on unknown changeset.
1634 # This is to done later. 1634 # This is to done later.
1635 futctx = [self[n] for n in fut if n != nullid] 1635
1636 for phase in phases.trackedphases[::-1]: 1636 # element we want to push
1637 prevphase = phase -1 1637 topush = []
1638 # get all candidate for head in previous phase 1638
1639 inprev = [ctx for ctx in futctx 1639 # store details of known remote phase of several revision
1640 if ctx.phase() == prevphase] 1640 # /!\ set of index I holds rev where: I <= rev.phase()
1641 for newremotehead in self.set('heads(%ld & (%ln::))', 1641 # /!\ public phase (index 0) is ignored
1642 inprev, rroots[phase]): 1642 remdetails = [set() for i in xrange(len(phases.allphases))]
1643 r = remote.pushkey('phases', 1643 _revs = set()
1644 newremotehead.hex(), 1644 for relremphase in phases.trackedphases[::-1]:
1645 str(phase), str(prevphase)) 1645 # we iterate backward because the list alway grows
1646 if not r: 1646 # when filled in this direction.
1647 self.ui.warn(_('updating phase of %s' 1647 _revs.update(self.revs('%ln::%ln',
1648 'to %s failed!\n') 1648 rroots[relremphase], fut))
1649 % (newremotehead, prevphase)) 1649 remdetails[relremphase].update(_revs)
1650
1651 for phase in phases.allphases[:-1]:
1652 # We don't need the last phase as we will never want to
1653 # move anything to it while moving phase backward.
1654
1655 # Get the list of all revs on remote which are in a
1656 # phase higher than currently processed phase.
1657 relremrev = remdetails[phase + 1]
1658
1659 if not relremrev:
1660 # no candidate to remote push anymore
1661 # break before any expensive revset
1662 break
1663
1664 #dynamical inject appropriate phase symbol
1665 phasename = phases.phasenames[phase]
1666 odrevset = 'heads(%%ld and %s())' % phasename
1667 outdated = self.set(odrevset, relremrev)
1668 for od in outdated:
1669 candstart = len(remdetails) - 1
1670 candstop = phase + 1
1671 candidateold = xrange(candstart, candstop, -1)
1672 for oldphase in candidateold:
1673 if od.rev() in remdetails[oldphase]:
1674 break
1675 else: # last one: no need to search
1676 oldphase = phase + 1
1677 topush.append((oldphase, phase, od))
1678
1679 # push every needed data
1680 for oldphase, newphase, newremotehead in topush:
1681 r = remote.pushkey('phases',
1682 newremotehead.hex(),
1683 str(oldphase), str(newphase))
1684 if not r:
1685 self.ui.warn(_('updating phase of %s '
1686 'to %s from %s failed!\n')
1687 % (newremotehead, newphase,
1688 oldphase))
1650 finally: 1689 finally:
1651 locallock.release() 1690 locallock.release()
1652 finally: 1691 finally:
1653 if lock is not None: 1692 if lock is not None:
1654 lock.release() 1693 lock.release()