Submitter | Siddharth Agarwal |
---|---|
Date | April 25, 2016, 11:34 p.m. |
Message ID | <71e061aa0be879ad6477.1461627283@dev666.prn1.facebook.com> |
Download | mbox | patch |
Permalink | /patch/14791/ |
State | Accepted |
Delegated to: | Pierre-Yves David |
Headers | show |
Comments
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@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@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@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@default(draft) will be evolved safely > + @ 44:41bf1183869c@default(draft) amended > | > - o 41:34ae045ec400@default(draft) amended > + o 36:43c3f5ef149f@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@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= >
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@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@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@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@default(draft) will be evolved safely >> + @ 44:41bf1183869c@default(draft) amended >> | >> - o 41:34ae045ec400@default(draft) amended >> + o 36:43c3f5ef149f@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@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= >> >> >
On 5/2/16 09:27, Pierre-Yves David wrote: > I've pushed this series. Thanks :) > > 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@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@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@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@default(draft) will be evolved safely >>> + @ 44:41bf1183869c@default(draft) amended >>> | >>> - o 41:34ae045ec400@default(draft) amended >>> + o 36:43c3f5ef149f@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@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= >>> >>> >> > > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Patch
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@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@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@default(draft) will be evolved safely + @ 44:41bf1183869c@default(draft) amended | - o 41:34ae045ec400@default(draft) amended + o 36:43c3f5ef149f@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