Mercurial > public > mercurial-scm > hg
diff 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 |
line wrap: on
line diff
--- a/mercurial/localrepo.py Fri Jan 06 10:04:20 2012 +0100 +++ b/mercurial/localrepo.py Wed Jan 04 01:12:31 2012 +0100 @@ -1632,21 +1632,60 @@ # XXX If push failed we should use strict common and not # future to avoir pushing phase data on unknown changeset. # This is to done later. - futctx = [self[n] for n in fut if n != nullid] - for phase in phases.trackedphases[::-1]: - prevphase = phase -1 - # get all candidate for head in previous phase - inprev = [ctx for ctx in futctx - if ctx.phase() == prevphase] - for newremotehead in self.set('heads(%ld & (%ln::))', - inprev, rroots[phase]): - r = remote.pushkey('phases', - newremotehead.hex(), - str(phase), str(prevphase)) - if not r: - self.ui.warn(_('updating phase of %s' - 'to %s failed!\n') - % (newremotehead, prevphase)) + + # element we want to push + topush = [] + + # store details of known remote phase of several revision + # /!\ set of index I holds rev where: I <= rev.phase() + # /!\ public phase (index 0) is ignored + remdetails = [set() for i in xrange(len(phases.allphases))] + _revs = set() + for relremphase in phases.trackedphases[::-1]: + # we iterate backward because the list alway grows + # when filled in this direction. + _revs.update(self.revs('%ln::%ln', + rroots[relremphase], fut)) + remdetails[relremphase].update(_revs) + + for phase in phases.allphases[:-1]: + # We don't need the last phase as we will never want to + # move anything to it while moving phase backward. + + # Get the list of all revs on remote which are in a + # phase higher than currently processed phase. + relremrev = remdetails[phase + 1] + + if not relremrev: + # no candidate to remote push anymore + # break before any expensive revset + break + + #dynamical inject appropriate phase symbol + phasename = phases.phasenames[phase] + odrevset = 'heads(%%ld and %s())' % phasename + outdated = self.set(odrevset, relremrev) + for od in outdated: + candstart = len(remdetails) - 1 + candstop = phase + 1 + candidateold = xrange(candstart, candstop, -1) + for oldphase in candidateold: + if od.rev() in remdetails[oldphase]: + break + else: # last one: no need to search + oldphase = phase + 1 + topush.append((oldphase, phase, od)) + + # push every needed data + for oldphase, newphase, newremotehead in topush: + r = remote.pushkey('phases', + newremotehead.hex(), + str(oldphase), str(newphase)) + if not r: + self.ui.warn(_('updating phase of %s ' + 'to %s from %s failed!\n') + % (newremotehead, newphase, + oldphase)) finally: locallock.release() finally: