[PATCH] rebase: don't rebase obsolete commits with no successor

Pierre-Yves David pierre-yves.david at ens-lyon.org
Wed Nov 18 22:27:07 CST 2015



On 11/18/2015 08:24 PM, Martin von Zweigbergk wrote:
>
>
> On Wed, Nov 18, 2015 at 5:08 PM Laurent Charignon <lcharignon at fb.com
> <mailto:lcharignon at fb.com>> wrote:
>
>
>      > On Nov 18, 2015, at 1:46 PM, Laurent Charignon <lcharignon at fb.com
>     <mailto:lcharignon at fb.com>> wrote:
>      >
>      > # HG changeset patch
>      > # User Laurent Charignon <lcharignon at fb.com
>     <mailto:lcharignon at fb.com>>
>      > # Date 1447883069 28800
>      > #      Wed Nov 18 13:44:29 2015 -0800
>      > # Node ID aa8771a01f32c86b4f9df8c45386bfe880a4e9dd
>      > # Parent  2da6a2dbfc42bdec4bcaf47da947c64ff959a59c
>      > rebase: don't rebase obsolete commits with no successor
>      >
>      > This patch avoids unnecessary conflicts to resolve during rebase
>     for the users
>      > of changeset evolution.
>      >
>      > This patch modifies rebase to skip obsolete commits with no
>     successor.
>      > It introduces a new rebase state 'revpruned' for these revisions
>     that are
>      > being skipped and a new message to inform the user of what is
>     happening.
>      > This feature is gated behind the config flag
>     experimental.rebaseskipobsolete
>      >
>      > When an obsolete commit is skipped, the output is:
>      > note: not rebasing 7:360bbaa7d3ce "O", it has no successor
>      >
>      > diff --git a/hgext/rebase.py b/hgext/rebase.py
>      > --- a/hgext/rebase.py
>      > +++ b/hgext/rebase.py
>      > @@ -32,6 +32,7 @@
>      > revignored = -3
>      > # To do with obsolescence
>      > revprecursor = -4
>      > +revpruned = -5
>      >
>      > cmdtable = {}
>      > command = cmdutil.command(cmdtable)
>      > @@ -487,6 +488,9 @@
>      >                              targetctx.description().split('\n',
>     1)[0])
>      >                 msg = _('note: not rebasing %s, already in
>     destination as %s\n')
>      >                 ui.status(msg % (desc, desctarget))
>      > +            elif state[rev] == revpruned:
>      > +                msg = _('note: not rebasing %s, it has no
>     successor\n')
>      > +                ui.status(msg % desc)
>      >             else:
>      >                 ui.status(_('already rebased %s as %s\n') %
>      >                           (desc, repo[state[rev]]))
>      > @@ -676,7 +680,7 @@
>      >     elif p1n in state:
>      >         if state[p1n] == nullmerge:
>      >             p1 = target
>      > -        elif state[p1n] in (revignored, revprecursor):
>      > +        elif state[p1n] in (revignored, revprecursor, revpruned):
>      >             p1 = nearestrebased(repo, p1n, state)
>      >             if p1 is None:
>      >                 p1 = target
>      > @@ -692,7 +696,7 @@
>      >         if p2n in state:
>      >             if p1 == target: # p1n in targetancestors or external
>      >                 p1 = state[p2n]
>      > -            elif state[p2n] in (revignored, revprecursor):
>      > +            elif state[p2n] in (revignored, revprecursor,
>     revpruned):
>      >                 p2 = nearestrebased(repo, p2n, state)
>      >                 if p2 is None:
>      >                     # no ancestors rebased yet, detach
>      > @@ -882,7 +886,7 @@
>      >             else:
>      >                 oldrev, newrev = l.split(':')
>      >                 if newrev in (str(nullmerge), str(revignored),
>      > -                              str(revprecursor)):
>      > +                              str(revprecursor), str(revpruned)):
>      >                     state[repo[oldrev].rev()] = int(newrev)
>      >                 elif newrev == nullid:
>      >                     state[repo[oldrev].rev()] = revtodo
>      > @@ -1066,7 +1070,10 @@
>      >         for ignored in set(rebasedomain) - set(rebaseset):
>      >             state[ignored] = revignored
>      >     for r in obsoletenotrebased:
>      > -        state[r] = revprecursor
>      > +        if obsoletenotrebased[r] is None:
>      > +            state[r] = revpruned
>      > +        else:
>      > +            state[r] = revprecursor
>      >     return repo['.'].rev(), dest.rev(), state
>      >
>      > def clearrebased(ui, repo, state, skipped, collapsedas=None):
>      > @@ -1177,7 +1184,9 @@
>      >
>      > def _computeobsoletenotrebased(repo, rebasesetrevs, dest):
>      >     """return a mapping obsolete => successor for all obsolete
>     nodes to be
>      > -    rebased that have a successors in the destination"""
>      > +    rebased that have a successors in the destination
>      > +
>      > +    obsolete => None entries in the mapping indicate nodes with
>     no succesor"""
>      >     obsoletenotrebased = {}
>      >
>      >     # Build a mapping successor => obsolete nodes for the obsolete
>      > @@ -1203,6 +1212,11 @@
>      >         for s in allsuccessors:
>      >             if s in ancs:
>      >                 obsoletenotrebased[allsuccessors[s]] = s
>      > +            elif (s == allsuccessors[s] and
>      > +                  allsuccessors.values().count(s) == 1):
>      > +                # plain prune
>      > +                obsoletenotrebased[s] = None
>      > +
>      >     return obsoletenotrebased
>      >
>      > def summaryhook(ui, repo):
>      > diff --git a/tests/test-rebase-obsolete.t
>     b/tests/test-rebase-obsolete.t
>      > --- a/tests/test-rebase-obsolete.t
>      > +++ b/tests/test-rebase-obsolete.t
>      > @@ -659,3 +659,31 @@
>      >   $ hg rebase -d 'desc(B2)'
>      >   note: not rebasing 1:a8b11f55fb19 "B0", already in destination
>     as 2:261e70097290 "B2"
>      >   rebasing 5:1a79b7535141 "D" (tip)
>      > +  $ hg up 4
>      > +  1 files updated, 0 files merged, 1 files removed, 0 files
>     unresolved
>      > +  $ echo "O" > O
>      > +  $ hg add O
>      > +  $ hg commit -m O
>      > +  $ echo "P" > P
>      > +  $ hg add P
>      > +  $ hg commit -m P
>      > +  $ hg log -G
>      > +  @  8:8d47583e023f P
>      > +  |
>      > +  o  7:360bbaa7d3ce O
>      > +  |
>      > +  | o  6:9c48361117de D
>      > +  | |
>      > +  o |  4:ff2c4d47b71d C
>      > +  |/
>      > +  o  2:261e70097290 B2
>      > +  |
>      > +  o  0:4a2df7238c3b A
>      > +
>      > +  $ hg prune 7 --config experimental.evolution=all --config
>     extensions.evolve=
>
>     Looking back on this patch, this does not seem right isn't it?
>     It introduces a dependency on evolve to run this test for one of the
>     extension of core.
>     Do we have a way to do a plain prune with what is in core?
>
>
> I think you can use debugobsolete. There are plenty of invocations of it
> in tests/ already.

I've actually already did not in flight.

-- 
Pierre-Yves David


More information about the Mercurial-devel mailing list