[PATCH 4 of 5 RFC] revset: add a predicate for finding rebased changesets

Matt Harbison matt_harbison at yahoo.com
Wed May 16 12:18:34 CDT 2012


Pierre-Yves David <pierre-yves.david <at> logilab.fr> writes:

> 
> On Tue, May 15, 2012 at 06:56:40PM +0200, Sune Foldager wrote:
> > 
> > > Matt Harbison <matt_harbison <at> yahoo.com> writes:
> > > 
> > >> # HG changeset patch
> > >> # User Matt Harbison <matt_harbison <at> yahoo.com>
> > >> # Date 1336884852 14400
> > >> # Node ID 5de639cd52e36c27b4c8bbbaa5fdb44803efee72
> > >> # Parent  2612b6d41579adce0df8f6b744f2879868125b5b
> > >> revset: add a predicate for finding rebased changesets
> > >> 
> > >> This selects changesets added because of rebases. If a revision is
> > >> specified, the set will be empty if that revision is not the source of
> > >> a rebase, or it will contain a destination changeset for each time the
> > >> specified revision was rebased. This can be useful for figuring out
> > >> where a particular changeset has been propagated.
> > 
> > Rebased changeset originals no longer exist, though, as opposed to grafted
and locally transplanted
> ones, so what would you use it for?
> 
> Various extras key are used:
> 
>     graft:'source',
>     rebase: 'rebase_source',
>     transplant: 'rebase_source',
> 
> A first step seems to unify all this to the common "source" extra.[1]
> 
> Then, a single revset predicate make sense.
> 
> (rebase --keep make a copy. It make sense to have the same behavior that graft
there.)
> 

That may be worth doing, but I'm not sure I agree it is a first step- the
predicate would have to look at the old strings anyway, otherwise it wouldn't
work for commits prior to whenever that change ships.  But this and the other
comments gives me an idea:

{graft|transplant|rebase --keep} without a subsequent strip of the source csets
are essentially copy based ops.  Plain rebase is a move, as are
{graft|transplant} with a subsequent strip of the source.  It doesn't seem like
it matters what particular operation was done, so a predicate for each is
probably the wrong way to attack it.

How about a copied([set]), a moved([set]), the origin([set]) that Matt suggested
above, and a destination([set]) which is the thing I was originally after?  For
the sake of these examples, let there be a cset 2, and when
{graft|transplant|rebase} is done to it, a cset 3 is added.

copied() would for each item in the revset it is provided, see if there is a
cset anywhere in the repo that references it via the extra field.  If so, the
rev in the set is kept.

   hg log -r "copied(branch(default))" -> [2] # all csets in default with copies
   hg log -r "copied(1 or 2)" -> [2]  # Does 1 or 2 have a copy?
   hg log -r "copied(3)" -> []   # 3 wasn't grafted|transplanted|rebased

This means a revset can cover the rebase --keep case, but the revset isn't in
the way without the --keep, or with a strip after a graft or transplant: there's
no longer a source rev to give to the predicate in these cases.

moved() would for each item in the revset it is provided, see if that rev has a
reference to some other cset.  If so, the rev in the set is kept.

   hg log -r "moved(branch(default))" -> [3] # all cloned/moved csets in default
   hg log -r "moved(3)" -> [3]
   hg log -r "moved(2)" -> []   # 2's extra doesn't reference anything
   hg strip -r 2
   hg log -r "moved(3)" -> [3]  # The extra field still shows the move

destination() would then be the opposite of origin().  e.g. destination(2) ->
[3].  Maybe somebody can suggest a shorter name.  But let's get the first two
squared away before this.

A side benefit is this addresses the name concerns, though maybe it causes a new
one where the destination cset of a copy operation thinks it is a move.  move()
could be made smarter to not select a rev if the source cset is valid, but I
would think you would want to select those somehow.

--Matt




More information about the Mercurial-devel mailing list