[PATCH 4 of 4 V4 evolve-ext] metaedit: add support for folding commits while editing their metadata

Pierre-Yves David pierre-yves.david at ens-lyon.org
Mon May 2 16:27:55 UTC 2016


I've pushed this series.

I made two minor followup changeset to adjust details I noted while 
reading them.

On 04/26/2016 06:14 PM, Simon Farnsworth wrote:
> I like this - it's a safe subset of histedit for operations (like code 
> review tools) that want to change metadata but don't want bugs to 
> damage the diff.
>
> I can't see anything wrong with this version.
>
> Simon
>
> On 26/04/2016 00:34, Siddharth Agarwal wrote:
>> # HG changeset patch
>> # User Siddharth Agarwal <sid0 at fb.com>
>> # Date 1461626682 25200
>> #      Mon Apr 25 16:24:42 2016 -0700
>> # Node ID 71e061aa0be879ad6477fbdb724a3a2e69e5af5b
>> # Parent  ea19e5ccc442ac286d4244695365034475b4fa5c
>> metaedit: add support for folding commits while editing their metadata
>>
>> This also allows us to accept multiple commits without dealing with 
>> the thorny
>> algorithmic and UI issues of editing multiple commits at once.
>>
>> Crucially, it is different from 'hg fold --exact' in that it also allows
>> 'folding' a single commit and rewriting its metadata. This is really 
>> useful to
>> have as a single logical operation, for example while preparing a 
>> series of
>> multiple local changesets that will need to be pushed as a single 
>> changeset.
>>
>> diff --git a/hgext/evolve.py b/hgext/evolve.py
>> --- a/hgext/evolve.py
>> +++ b/hgext/evolve.py
>> @@ -3151,14 +3151,18 @@ def fold(ui, repo, *revs, **opts):
>>
>>   @command('^metaedit',
>>            [('r', 'rev', [], _("revision to edit")),
>> +         ('', 'fold', None, _("also fold specified revisions into 
>> one")),
>>            ] + commitopts + commitopts2,
>>            _('hg metaedit [OPTION]... [-r] [REV]'))
>>   def metaedit(ui, repo, *revs, **opts):
>>       """edit commit information
>>
>> -    Edits the commit information for the specified revision. By 
>> default, edits
>> +    Edits the commit information for the specified revisions. By 
>> default, edits
>>       commit information for the working directory parent.
>>
>> +    With --fold, also folds multiple revisions into one if 
>> necessary. In this
>> +    case, the given revisions must form a linear unbroken chain.
>> +
>>       .. container:: verbose
>>
>>        Some examples:
>> @@ -3171,10 +3175,19 @@ def metaedit(ui, repo, *revs, **opts):
>>
>>            hg metaedit --user 'New User <new-email at example.com>'
>>
>> +     - Combine all draft revisions that are ancestors of foo but not 
>> of @ into
>> +       one::
>> +
>> +         hg metaedit --fold 'draft() and only(foo,@)'
>> +
>> +       See :hg:`help phases` for more about draft revisions, and
>> +       :hg:`help revsets` for more about the `draft()` and `only()` 
>> keywords.
>>       """
>>       revs = list(revs)
>>       revs.extend(opts['rev'])
>>       if not revs:
>> +        if opts['fold']:
>> +            raise error.Abort(_('revisions must be specified with 
>> --fold'))
>>           revs = ['.']
>>
>>       wlock = lock = None
>> @@ -3183,7 +3196,7 @@ def metaedit(ui, repo, *revs, **opts):
>>           lock = repo.lock()
>>
>>           revs = scmutil.revrange(repo, revs)
>> -        if len(revs) > 1:
>> +        if not opts['fold'] and len(revs) > 1:
>>               # TODO: handle multiple revisions. This is somewhat 
>> tricky because
>>               # if we want to edit a series of commits:
>>               #
>> @@ -3192,18 +3205,21 @@ def metaedit(ui, repo, *revs, **opts):
>>               # we need to rewrite a first, then directly rewrite b 
>> on top of the
>>               # new a, then rewrite c on top of the new b. So we need 
>> to handle
>>               # revisions in topological order.
>> -            raise error.Abort(_('editing multiple revisions is not '
>> -                                'currently supported'))
>> -
>> -        newunstable = _disallowednewunstable(repo, revs)
>> -        if newunstable:
>> -            raise error.Abort(
>> -                _('cannot edit commit information in the middle of a 
>> stack'),
>> -                hint=_('%s will be affected') % 
>> repo[newunstable.first()])
>> -        if repo.revs("%ld and public()", revs):
>> -            raise error.Abort(_('cannot edit commit information for 
>> public '
>> -                                'revisions'))
>> -        root = head = repo[revs.first()]
>> +            raise error.Abort(_('editing multiple revisions without 
>> --fold is '
>> +                                'not currently supported'))
>> +
>> +        if opts['fold']:
>> +            root, head = _foldcheck(repo, revs)
>> +        else:
>> +            newunstable = _disallowednewunstable(repo, revs)
>> +            if newunstable:
>> +                raise error.Abort(
>> +                    _('cannot edit commit information in the middle 
>> of a stack'),
>> +                    hint=_('%s will be affected') % 
>> repo[newunstable.first()])
>> +            if repo.revs("%ld and public()", revs):
>> +                raise error.Abort(_('cannot edit commit information 
>> for public '
>> +                                    'revisions'))
>> +            root = head = repo[revs.first()]
>>
>>           wctx = repo[None]
>>           p1 = wctx.p1()
>> @@ -3217,7 +3233,12 @@ def metaedit(ui, repo, *revs, **opts):
>>               if commitopts.get('message') or commitopts.get('logfile'):
>>                   commitopts['edit'] = False
>>               else:
>> -                msgs = [head.description()]
>> +                if opts['fold']:
>> +                    msgs = ["HG: This is a fold of %d changesets." % 
>> len(allctx)]
>> +                    msgs += ["HG: Commit message of changeset 
>> %s.\n\n%s\n" %
>> +                             (c.rev(), c.description()) for c in 
>> allctx]
>> +                else:
>> +                    msgs = [head.description()]
>>                   commitopts['message'] =  "\n".join(msgs)
>>                   commitopts['edit'] = True
>>
>> @@ -3239,6 +3260,8 @@ def metaedit(ui, repo, *revs, **opts):
>>           finally:
>>               tr.release()
>>
>> +        if opts['fold']:
>> +            ui.status('%i changesets folded\n' % len(revs))
>>           if newp1 is not None:
>>               hg.update(repo, newp1)
>>       finally:
>> diff --git a/tests/test-evolve.t b/tests/test-evolve.t
>> --- a/tests/test-evolve.t
>> +++ b/tests/test-evolve.t
>> @@ -1468,11 +1468,26 @@ hg metaedit
>>     $ hg metaedit -r 0
>>     abort: cannot edit commit information for public revisions
>>     [255]
>> +  $ hg metaedit --fold
>> +  abort: revisions must be specified with --fold
>> +  [255]
>> +  $ hg metaedit -r 0 --fold
>> +  abort: cannot fold public revisions
>> +  [255]
>> +  $ hg metaedit '36 + 42' --fold
>> +  abort: cannot fold non-linear revisions (multiple roots given)
>> +  [255]
>> +  $ hg metaedit '36::39 + 41' --fold
>> +  abort: cannot fold non-linear revisions (multiple heads given)
>> +  [255]
>>   check that metaedit respects allowunstable
>>     $ hg metaedit '.^' --config 
>> 'experimental.evolution=createmarkers, allnewcommands'
>>     abort: cannot edit commit information in the middle of a stack
>>     (c904da5245b0 will be affected)
>>     [255]
>> +  $ hg metaedit '18::20' --fold --config 
>> 'experimental.evolution=createmarkers, allnewcommands'
>> +  abort: cannot fold chain not ending with a head or with branching
>> +  [255]
>>     $ hg metaedit --user foobar
>>     0 files updated, 0 files merged, 0 files removed, 0 files unresolved
>>     $ hg log --template '{rev}: {author}\n' -r '42:' --hidden
>> @@ -1483,26 +1498,57 @@ check that metaedit respects allowunstab
>>
>>   TODO: support this
>>     $ hg metaedit '.^::.'
>> -  abort: editing multiple revisions is not currently supported
>> +  abort: editing multiple revisions without --fold is not currently 
>> supported
>>     [255]
>>
>> -no new commit is created here because the date is the same
>> -  $ HGEDITOR=cat hg metaedit
>> +  $ HGEDITOR=cat hg metaedit '.^::.' --fold
>> +  HG: This is a fold of 2 changesets.
>> +  HG: Commit message of changeset 41.
>> +
>> +  amended
>> +
>> +  HG: Commit message of changeset 43.
>> +
>>     will be evolved safely
>>
>>
>> +
>>     HG: Enter commit message.  Lines beginning with 'HG:' are removed.
>>     HG: Leave message empty to abort commit.
>>     HG: --
>> -  HG: user: foobar
>> +  HG: user: test
>>     HG: branch 'default'
>>     HG: changed a
>> +  HG: changed newfile
>> +  2 changesets folded
>> +  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +
>> +  $ glog -r .
>> +  @  44:41bf1183869c at default(draft) amended
>> +  |
>> +  ~
>> +
>> +no new commit is created here because the date is the same
>> +  $ HGEDITOR=cat hg metaedit
>> +  amended
>> +
>> +
>> +  will be evolved safely
>> +
>> +
>> +  HG: Enter commit message.  Lines beginning with 'HG:' are removed.
>> +  HG: Leave message empty to abort commit.
>> +  HG: --
>> +  HG: user: test
>> +  HG: branch 'default'
>> +  HG: changed a
>> +  HG: changed newfile
>>     nothing changed
>>
>>     $ glog -r '.^::.'
>> -  @  43:62353add3dfb at default(draft) will be evolved safely
>> +  @  44:41bf1183869c at default(draft) amended
>>     |
>> -  o  41:34ae045ec400 at default(draft) amended
>> +  o  36:43c3f5ef149f at default(draft) add uu
>>     |
>>     ~
>>
>> @@ -1510,15 +1556,22 @@ TODO: don't create a new commit in this
>>     $ hg metaedit --config defaults.metaedit=
>>     0 files updated, 0 files merged, 0 files removed, 0 files unresolved
>>     $ hg log -r '.^::.' --template '{rev}: {desc|firstline}\n'
>> -  41: amended
>> -  44: will be evolved safely
>> +  36: add uu
>> +  45: amended
>>
>>     $ hg up .^
>> -  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> -  $ hg metaedit --user foobar2 44
>> +  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
>> +  $ hg metaedit --user foobar2 45
>>     $ hg log --template '{rev}: {author}\n' -r '42:' --hidden
>>     42: test
>>     43: foobar
>> -  44: foobar
>> -  45: foobar2
>> -  $ hg diff -r 44 -r 45 --hidden
>> +  44: test
>> +  45: test
>> +  46: foobar2
>> +  $ hg diff -r 45 -r 46 --hidden
>> +
>> +'fold' one commit
>> +  $ hg metaedit 39 --fold --user foobar3
>> +  1 changesets folded
>> +  $ hg log -r 47 --template '{rev}: {author}\n'
>> +  47: foobar3
>> _______________________________________________
>> Mercurial-devel mailing list
>> Mercurial-devel at mercurial-scm.org
>> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=CwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=mEgSWILcY4c4W3zjApBQLA&m=UHn3lAnPn2BRfDMVSc9_wLI4N4sjJYZax4FtWUqUWJY&s=nM0aEVfbyAV1jJibZ_K_QhF2VL1XOSRF1FdcDsmXi_k&e= 
>>
>>
>



More information about the Mercurial-devel mailing list