phases: simplify phase exchange and movement over pushkey
The code now only exchange draft root and only care about movement related to
public//draft boundary.
There is multiple reason to simplify this code:
* Secret are never discovered anymore
* We decided to not support more the three existing phase
Removing phase index from pushkey (if ever decided) will be made in another commit.
--- a/mercurial/localrepo.py Fri Jan 13 01:42:47 2012 +0100
+++ b/mercurial/localrepo.py Fri Jan 13 02:04:16 2012 +0100
@@ -1555,10 +1555,10 @@
if remotephases and not publishing:
# remote is new and unpublishing
subset = common + added
- rheads, rroots = phases.analyzeremotephases(self, subset,
- remotephases)
- for phase, boundary in enumerate(rheads):
- phases.advanceboundary(self, phase, boundary)
+ pheads, _dr = phases.analyzeremotephases(self, subset,
+ remotephases)
+ phases.advanceboundary(self, phases.public, pheads)
+ phases.advanceboundary(self, phases.draft, common + added)
else:
# Remote is old or publishing all common changesets
# should be seen as public
@@ -1627,72 +1627,32 @@
# don't push any phase data as there is nothing to push
else:
ana = phases.analyzeremotephases(self, fut, remotephases)
- rheads, rroots = ana
+ pheads, droots = ana
### Apply remote phase on local
if remotephases.get('publishing', False):
phases.advanceboundary(self, phases.public, fut)
else: # publish = False
- for phase, rpheads in enumerate(rheads):
- phases.advanceboundary(self, phase, rpheads)
+ phases.advanceboundary(self, phases.public, pheads)
+ phases.advanceboundary(self, phases.draft, fut)
### Apply local phase on remote
#
# XXX If push failed we should use strict common and not
- # future to avoir pushing phase data on unknown changeset.
+ # future to avoid pushing phase data on unknown changeset.
# This is to done later.
- # 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:
+ # Get the list of all revs draft on remote by public here.
+ # XXX Beware that revset break if droots is not strictly
+ # XXX root we may want to ensure it is but it is costly
+ outdated = self.set('heads((%ln::%ln) and public())',
+ droots, fut)
+ for newremotehead in outdated:
r = remote.pushkey('phases',
newremotehead.hex(),
- str(oldphase), str(newphase))
+ str(phases.draft),
+ str(phases.public))
if not r:
- self.ui.warn(_('updating phase of %s '
- 'to %s from %s failed!\n')
- % (newremotehead, newphase,
- oldphase))
+ self.ui.warn(_('updating %s to public failed!\n')
+ % newremotehead)
finally:
locallock.release()
finally:
--- a/mercurial/phases.py Fri Jan 13 01:42:47 2012 +0100
+++ b/mercurial/phases.py Fri Jan 13 02:04:16 2012 +0100
@@ -203,9 +203,10 @@
def listphases(repo):
"""List phases root for serialisation over pushkey"""
keys = {}
- for phase in trackedphases:
- for root in repo._phaseroots[phase]:
- keys[hex(root)] = '%i' % phase
+ value = '%i' % draft
+ for root in repo._phaseroots[draft]:
+ keys[hex(root)] = value
+
if repo.ui.configbool('phases', 'publish', True):
# Add an extra data to let remote know we are a publishing repo.
# Publishing repo can't just pretend they are old repo. When pushing to
@@ -264,20 +265,26 @@
Accept unknown element input
"""
# build list from dictionary
- phaseroots = [[] for p in allphases]
+ draftroots = []
+ nm = repo.changelog.nodemap # to filter unknown node
for nhex, phase in roots.iteritems():
if nhex == 'publishing': # ignore data related to publish option
continue
node = bin(nhex)
phase = int(phase)
- if node in repo:
- phaseroots[phase].append(node)
+ if phase == 0:
+ if node != nullid:
+ msg = _('ignoring inconsistense public root from remote: %s')
+ repo.ui.warn(msg, nhex)
+ elif phase == 1:
+ if node in nm:
+ draftroots.append(node)
+ else:
+ msg = _('ignoring unexpected root from remote: %i %s')
+ repo.ui.warn(msg, phase, nhex)
# compute heads
- phaseheads = [[] for p in allphases]
- for phase in allphases[:-1]:
- toproof = phaseroots[phase + 1]
- revset = repo.set('heads((%ln + parents(%ln)) - (%ln::%ln))',
- subset, toproof, toproof, subset)
- phaseheads[phase].extend(c.node() for c in revset)
- return phaseheads, phaseroots
+ revset = repo.set('heads((%ln + parents(%ln)) - (%ln::%ln))',
+ subset, draftroots, draftroots, subset)
+ publicheads = [c.node() for c in revset]
+ return publicheads, draftroots
--- a/tests/test-push-http.t Fri Jan 13 01:42:47 2012 +0100
+++ b/tests/test-push-http.t Fri Jan 13 02:04:16 2012 +0100
@@ -29,7 +29,7 @@
searching for changes
remote: ssl required
remote: ssl required
- updating phase of ba677d0156c1 to 0 from 1 failed!
+ updating ba677d0156c1 to public failed!
% serve errors
expect authorization error