Patchwork [evolve-ext] fold: allow folding one revision with --exact if rewriting is necessary

login
register
mail settings
Submitter Siddharth Agarwal
Date March 2, 2016, 12:01 a.m.
Message ID <def16bbc29a4c23ea7dd.1456876890@dev666.prn1.facebook.com>
Download mbox | patch
Permalink /patch/13521/
State Changes Requested
Delegated to: Pierre-Yves David
Headers show

Comments

Siddharth Agarwal - March 2, 2016, 12:01 a.m.
# HG changeset patch
# User Siddharth Agarwal <sid0@fb.com>
# Date 1456876756 28800
#      Tue Mar 01 15:59:16 2016 -0800
# Branch stable
# Node ID def16bbc29a4c23ea7dd2dcb00abbcaa6e89b575
# Parent  160968654581eb83f58f2b913124a16f7bef56ee
fold: allow folding one revision with --exact if rewriting is necessary

hg fold --exact lets you combine commits into one and change the user or commit
message without actually being on any of the commits. (This is particularly
useful when checking out the revisions would be extremely expensive.) It has
one flaw that prevents it from being used in this way in automated tools,
though -- it doesn't let you rewrite a single commit to have a different user
or message.

This restriction is completely artificial, so drop it.

We still rewrite commits that have the same message and user because that's
likely going to be the rare case and tool writers are often not going to test
for it. This decision allows commands like:

  hg fold --exact REV -u USER && hg log -r 'last(successors(REV))'

to unconditionally work, even if USER is the same as before.
Pierre-Yves David - March 7, 2016, 3:57 p.m.
On 03/02/2016 01:01 AM, Siddharth Agarwal wrote:
> # HG changeset patch
> # User Siddharth Agarwal <sid0@fb.com>
> # Date 1456876756 28800
> #      Tue Mar 01 15:59:16 2016 -0800
> # Branch stable
> # Node ID def16bbc29a4c23ea7dd2dcb00abbcaa6e89b575
> # Parent  160968654581eb83f58f2b913124a16f7bef56ee
> fold: allow folding one revision with --exact if rewriting is necessary

I'm not super enthousiastic at the idea of seeing `hg fold` used as a 
command to rewrite a random commit meta-data. I'll have to think about 
it a bit more.

I think we could find a better command to support this usecase.
Siddharth Agarwal - March 7, 2016, 5:47 p.m.
On 3/7/16 07:57, Pierre-Yves David wrote:
>
>
> On 03/02/2016 01:01 AM, Siddharth Agarwal wrote:
>> # HG changeset patch
>> # User Siddharth Agarwal <sid0@fb.com>
>> # Date 1456876756 28800
>> #      Tue Mar 01 15:59:16 2016 -0800
>> # Branch stable
>> # Node ID def16bbc29a4c23ea7dd2dcb00abbcaa6e89b575
>> # Parent  160968654581eb83f58f2b913124a16f7bef56ee
>> fold: allow folding one revision with --exact if rewriting is necessary
>
> I'm not super enthousiastic at the idea of seeing `hg fold` used as a 
> command to rewrite a random commit meta-data. I'll have to think about 
> it a bit more.

FWIW, I believe the requirements should be:
- allow rewriting one or rewriting + combining a linear series of 
multiple changesets in the same command
- lets you rewrite all commit metadata
- do it to any series of non-public commits in the DAG even if unrelated 
to the working copy
- the operation shouldn't trigger any merge logic

I'm ok with a new 'hg rewrite' command or similar, but I thought that 
'fold' was a fairly straightforward fit.

- Siddharth


>
> I think we could find a better command to support this usecase.
>
Pierre-Yves David - March 9, 2016, 2:08 p.m.
On 03/07/2016 05:47 PM, Siddharth Agarwal wrote:
> On 3/7/16 07:57, Pierre-Yves David wrote:
>>
>>
>> On 03/02/2016 01:01 AM, Siddharth Agarwal wrote:
>>> # HG changeset patch
>>> # User Siddharth Agarwal <sid0@fb.com>
>>> # Date 1456876756 28800
>>> #      Tue Mar 01 15:59:16 2016 -0800
>>> # Branch stable
>>> # Node ID def16bbc29a4c23ea7dd2dcb00abbcaa6e89b575
>>> # Parent  160968654581eb83f58f2b913124a16f7bef56ee
>>> fold: allow folding one revision with --exact if rewriting is necessary
>>
>> I'm not super enthousiastic at the idea of seeing `hg fold` used as a
>> command to rewrite a random commit meta-data. I'll have to think about
>> it a bit more.
>
> FWIW, I believe the requirements should be:
> - allow rewriting one or rewriting + combining a linear series of
> multiple changesets in the same command
> - lets you rewrite all commit metadata
> - do it to any series of non-public commits in the DAG even if unrelated
> to the working copy
> - the operation shouldn't trigger any merge logic
>
> I'm ok with a new 'hg rewrite' command or similar, but I thought that
> 'fold' was a fairly straightforward fit.

Git have a "git filter branch" stuff that do this kind of magic iirc.

* Having for batched metadata rewrite in evolve make sense.

* I would rather gain a new command for now that expand "fold" role too 
far. My current approach for evolve UI experimentation is to focus on a 
single usecase/semantic for each command. Then we'll have all the 
feature we need we can start thinking how to reorganised thing in less 
commands while keeping them with a fairly weel defined semantic.

Feel free to send patch for a metadata update command.

Cheers,

Patch

diff --git a/hgext/evolve.py b/hgext/evolve.py
--- a/hgext/evolve.py
+++ b/hgext/evolve.py
@@ -2957,7 +2957,8 @@  def fold(ui, repo, *revs, **opts):
                                       "of working directory"))
         revs = extrevs
 
-    if len(revs) == 1:
+    mustrewrite = opts['user'] or opts['message'] or opts['logfile'];
+    if len(revs) == 1 and not (opts['exact'] and mustrewrite):
         ui.write_err(_('single revision specified, nothing to fold\n'))
         return 1
 
diff --git a/tests/test-evolve.t b/tests/test-evolve.t
--- a/tests/test-evolve.t
+++ b/tests/test-evolve.t
@@ -1339,6 +1339,24 @@  Check that fold respects the allowunstab
   $ hg fold --exact "19::"
   2 changesets folded
 
+allow fold --exact to fold a single revision if user/message is specified
+  $ hg fold --exact 31
+  single revision specified, nothing to fold
+  [1]
+  $ hg fold --exact 31 -u foo
+  1 changesets folded
+  $ hg fold --exact 31 -m 'foo message' --hidden
+  1 changesets folded
+  2 new divergent changesets
+(in this case the message is the same)
+  $ hg fold --exact 31 -m 'add gg' --hidden
+  1 changesets folded
+  1 new divergent changesets
+  $ hg log -r 'successors(31)' --hidden
+  32	: add gg - foo
+  33	: foo message - test
+  34	: add gg - test
+
 Check that evolve shows error while handling split commits
 --------------------------------------
 
@@ -1348,8 +1366,12 @@  Check that evolve shows error while hand
   > EOF
 
   $ glog -r "18::"
-  o  31:580886d07058@default(draft) add gg
+  o  34:bf15a00cfc47@default(draft) add gg
   |
+  | o  33:f45f64d8db25@default(draft) foo message
+  |/
+  | o  32:e2b0e9b26f0a@default(draft) add gg
+  |/
   | @  30:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
   | o  20:e02107f98737@default(draft) add gh
@@ -1376,16 +1398,20 @@  Create a split commit
   1 changesets pruned
   1 new unstable changesets
   $ glog -r "18::"
-  @  35:7a555adf2b4a@default(draft) _pp
+  @  38:7a555adf2b4a@default(draft) _pp
   |
-  o  34:2be4d2d5bf34@default(draft) _oo
+  o  37:2be4d2d5bf34@default(draft) _oo
   |
-  | o  33:53f0c003e03e@default(draft) add uu
+  | o  36:53f0c003e03e@default(draft) add uu
   | |
-  | x  32:1bf2152f4f82@default(draft) oo+pp
+  | x  35:1bf2152f4f82@default(draft) oo+pp
   |/
-  | o  31:580886d07058@default(draft) add gg
+  | o  34:bf15a00cfc47@default(draft) add gg
   | |
+  | | o  33:f45f64d8db25@default(draft) foo message
+  | |/
+  | | o  32:e2b0e9b26f0a@default(draft) add gg
+  | |/
   o |  30:68330ac625b8@default(draft) add unstableifparentisfolded
   |/
   | o  20:e02107f98737@default(draft) add gh
@@ -1393,8 +1419,8 @@  Create a split commit
   o  18:edc3c9de504e@default(draft) a3
   |
   $ hg evolve --rev "18::"
-  move:[33] add uu
-  atop:[35] _pp
+  move:[36] add uu
+  atop:[38] _pp
   working directory is now at 43c3f5ef149f
 
 
@@ -1404,7 +1430,7 @@  Check that dirstate changes are kept at 
   $ echo "will be amended" > newfile
   $ hg commit -m "will be amended"
   $ hg parents
-  37	: will be amended - test
+  40	: will be amended - test
 
   $ echo "will be evolved safely" >> a
   $ hg commit -m "will be evolved safely"
@@ -1414,16 +1440,16 @@  Check that dirstate changes are kept at 
   $ hg add newlyadded
   $ hg commit -m "will cause conflict at evolve"
 
-  $ hg update -q 37
+  $ hg update -q 40
   $ echo "amended" > newfile
   $ hg amend -m "amended"
   2 new unstable changesets
 
-  $ hg evolve --rev "37::"
-  move:[38] will be evolved safely
-  atop:[41] amended
-  move:[39] will cause conflict at evolve
-  atop:[42] will be evolved safely
+  $ hg evolve --rev "40::"
+  move:[41] will be evolved safely
+  atop:[44] amended
+  move:[42] will cause conflict at evolve
+  atop:[45] will be evolved safely
   merging newfile
   warning: conflicts while merging newfile! (edit, then use 'hg resolve --mark')
   evolve failed!
@@ -1431,20 +1457,20 @@  Check that dirstate changes are kept at 
   abort: unresolved merge conflicts (see hg help resolve)
   [255]
 
-  $ glog -r "36::" --hidden
-  @  42:c904da5245b0@default(draft) will be evolved safely
+  $ glog -r "39::" --hidden
+  @  45:c904da5245b0@default(draft) will be evolved safely
   |
-  o  41:34ae045ec400@default(draft) amended
+  o  44:34ae045ec400@default(draft) amended
   |
-  | x  40:e88bee38ffc2@default(draft) temporary amend commit for 36030b147271
+  | x  43:e88bee38ffc2@default(draft) temporary amend commit for 36030b147271
   | |
-  | | o  39:02e943732647@default(draft) will cause conflict at evolve
+  | | o  42:02e943732647@default(draft) will cause conflict at evolve
   | | |
-  | | x  38:f8e30e9317aa@default(draft) will be evolved safely
+  | | x  41:f8e30e9317aa@default(draft) will be evolved safely
   | |/
-  | x  37:36030b147271@default(draft) will be amended
+  | x  40:36030b147271@default(draft) will be amended
   |/
-  o  36:43c3f5ef149f@default(draft) add uu
+  o  39:43c3f5ef149f@default(draft) add uu
   |
 
   $ hg status newlyadded