[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