[PATCH 4 of 4 phases] phases: fix phase synchronization on push

Matt Mackall mpm at selenic.com
Thu Jan 5 21:49:21 CST 2012


On Wed, 2012-01-04 at 01:20 +0100, Pierre-Yves David wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
> # Date 1325635951 -3600
> # Node ID e2a8777c92bd878fb52add317c0dd1ab7e56dc80
> # Parent  e68589dcd419836ce7e2321f459ce58fe86ace2b
> phases: fix phase synchronization on push

Is this dependent on the others?

I think we still need to resolve the question: why does it make sense to
report any phases other than the public/draft boundary via pushkey? By
definition, remote has no business knowing about secret changesets.

> 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.
> 
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -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:
> diff --git a/tests/test-phases.t b/tests/test-phases.t
> --- a/tests/test-phases.t
> +++ b/tests/test-phases.t
> @@ -91,6 +91,10 @@
>  Test secret changeset are not pushed
>  
>    $ hg init ../push-dest
> +  $ cat > ../push-dest/.hg/hgrc << EOF
> +  > [phases]
> +  > publish=False
> +  > EOF
>    $ hg push ../push-dest -f # force because we push multiple heads
>    pushing to ../push-dest
>    searching for changes
> @@ -100,18 +104,18 @@
>    added 5 changesets with 5 changes to 5 files (+1 heads)
>    $ hglog
>    7 2 merge B' and E
> -  6 0 B'
> +  6 1 B'
>    5 2 H
>    4 2 E
> -  3 0 D
> -  2 0 C
> +  3 1 D
> +  2 1 C
>    1 0 B
>    0 0 A
>    $ cd ../push-dest
>    $ hglog
> -  4 0 B'
> -  3 0 D
> -  2 0 C
> +  4 1 B'
> +  3 1 D
> +  2 1 C
>    1 0 B
>    0 0 A
>    $ cd ..
> @@ -142,10 +146,10 @@
>    $ hglog -r 'public()'
>    0 0 A
>    1 0 B
> -  2 0 C
> -  3 0 D
> -  6 0 B'
>    $ hglog -r 'draft()'
> +  2 1 C
> +  3 1 D
> +  6 1 B'
>    $ hglog -r 'secret()'
>    4 2 E
>    5 2 H
> diff --git a/tests/test-push-http.t b/tests/test-push-http.t
> --- a/tests/test-push-http.t
> +++ b/tests/test-push-http.t
> @@ -29,7 +29,7 @@
>    searching for changes
>    remote: ssl required
>    remote: ssl required
> -  updating phase of ba677d0156c1to 0 failed!
> +  updating phase of ba677d0156c1 to 0 from 1 failed!
>    % serve errors
>  
>  expect authorization error


-- 
Mathematics is the supreme nostalgia of our time.




More information about the Mercurial-devel mailing list