Patchwork [evolve-ext] rebase: refuse to create divergence when using changeset evolution

login
register
mail settings
Submitter Laurent Charignon
Date Nov. 20, 2015, 11:14 p.m.
Message ID <b817cfe239a326017e93.1448061240@dev5073.prn1.facebook.com>
Download mbox | patch
Permalink /patch/11553/
State Changes Requested
Headers show

Comments

Laurent Charignon - Nov. 20, 2015, 11:14 p.m.
# HG changeset patch
# User Laurent Charignon <lcharignon@fb.com>
# Date 1447957389 28800
#      Thu Nov 19 10:23:09 2015 -0800
# Node ID b817cfe239a326017e9345744963c19ef6b8c0e8
# Parent  8b9c04fb4c7e6d6cb872c63f7289ea679296dd3e
rebase: refuse to create divergence when using changeset evolution

When a rebase operation is about to create divergence, rebase now aborts.
If the user wants to create divergence anyway, it can be done using the config
option: rebase.allowdivergence.
The error message looks like:
    abort: rebase cannot create divergent changesets
    (set the config rebase.allowdivergence=True if you want to allow divergence)

In the test output we don't see the warning message about divergence being
created because evolve is not enabled for the test.
Pierre-Yves David - Nov. 22, 2015, 1:24 a.m.
On 11/20/2015 03:14 PM, Laurent Charignon wrote:
> # HG changeset patch
> # User Laurent Charignon <lcharignon@fb.com>
> # Date 1447957389 28800
> #      Thu Nov 19 10:23:09 2015 -0800
> # Node ID b817cfe239a326017e9345744963c19ef6b8c0e8
> # Parent  8b9c04fb4c7e6d6cb872c63f7289ea679296dd3e
> rebase: refuse to create divergence when using changeset evolution
>
> When a rebase operation is about to create divergence, rebase now aborts.
> If the user wants to create divergence anyway, it can be done using the config
> option: rebase.allowdivergence.

I'm not sure about the option, do we have a rebase section already? Wr 
should probably move forward with an experiemental option. The skipping 
behavior probably need controllability too. We should probably think 
about both at the same time.

> The error message looks like:
>      abort: rebase cannot create divergent changesets
>      (set the config rebase.allowdivergence=True if you want to allow divergence)
>
> In the test output we don't see the warning message about divergence being
> created because evolve is not enabled for the test.
>
> diff --git a/hgext/rebase.py b/hgext/rebase.py
> --- a/hgext/rebase.py
> +++ b/hgext/rebase.py
> @@ -1222,6 +1222,15 @@
>                   # plain prune
>                   obsoletenotrebased[s] = None
>
> +        # Divergence is created if an obsolete commit is rebased on a
> +        # destination with none of its successors
> +        if not repo.ui.configbool('rebase', 'allowdivergence'):
> +            if set(allsuccessors.values()) - set(obsoletenotrebased.keys()):
> +                hint = _('set the config rebase.allowdivergence=True if you'
> +                         ' want to allow divergence')
> +                raise error.Abort(
> +                    _('rebase cannot create divergent changesets'), hint=hint)
> +

I think I see a simpler version of this logic. We already have some code 
that:

1) detect if the changeset is obsolete
2) skip if the successors are in destination (or pruned)

If the changeset is obsolete (1) but not in destination (2), creating a 
successors for it will create divergence. So reusing the conditional for 
the existing skipping code may be better here.

Patch

diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -1222,6 +1222,15 @@ 
                 # plain prune
                 obsoletenotrebased[s] = None
 
+        # Divergence is created if an obsolete commit is rebased on a
+        # destination with none of its successors
+        if not repo.ui.configbool('rebase', 'allowdivergence'):
+            if set(allsuccessors.values()) - set(obsoletenotrebased.keys()):
+                hint = _('set the config rebase.allowdivergence=True if you'
+                         ' want to allow divergence')
+                raise error.Abort(
+                    _('rebase cannot create divergent changesets'), hint=hint)
+
     return obsoletenotrebased
 
 def summaryhook(ui, repo):
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -1284,6 +1284,14 @@ 
 ``assume-tty``
     If true, ALWAYS show a progress bar, unless disable is given.
 
+``rebase``
+----------
+
+``allowdivergence``
+    When using changeset evolution, if true, allows rebase to create divergent
+    changesets. Otherwise rebase will abort instead of creating divergent
+    changesets.
+
 ``revsetalias``
 ---------------
 
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
@@ -685,3 +685,77 @@ 
   rebasing 4:ff2c4d47b71d "C"
   note: not rebasing 7:360bbaa7d3ce "O", it has no successor
   rebasing 8:8d47583e023f "P" (tip)
+
+Rebase should abort when the operation is going to create divergent changesets
+  $ cat >> $HGRCPATH << EOF
+  > [experimental]
+  > evolution=all
+  > EOF
+
+  $ hg log -G
+  @  10:121d9e3bc4c6 P
+  |
+  o  9:4be60e099a77 C
+  |
+  o  6:9c48361117de D
+  |
+  o  2:261e70097290 B2
+  |
+  o  0:4a2df7238c3b A
+  
+  $ hg up -C 2
+  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ echo "Q" > Q
+  $ hg add Q
+  $ hg commit -m Q
+  created new head
+  $ hg up -C 6
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo "R" > R
+  $ hg add R
+  $ hg commit -m R --amend
+  $ hg log -G
+  @  13:84f40ac83951 R
+  |
+  | o  11:8d2e6e25498d Q
+  |/
+  | o  10:121d9e3bc4c6 P
+  | |
+  | o  9:4be60e099a77 C
+  | |
+  | x  6:9c48361117de D
+  |/
+  o  2:261e70097290 B2
+  |
+  o  0:4a2df7238c3b A
+  
+
+Here rebasing 6 on 11 would create a new successor of 6, divergent from 13,
+the other successor of 6
+
+  $ hg rebase -r 6:: -d 11
+  abort: rebase cannot create divergent changesets
+  (set the config rebase.allowdivergence=True if you want to allow divergence)
+  [255]
+
+We can force the rebase to create divergence with a config option
+
+  $ hg rebase -r 6:: -d 11 --config rebase.allowdivergence=True
+  rebasing 6:9c48361117de "D"
+  rebasing 9:4be60e099a77 "C"
+  rebasing 10:121d9e3bc4c6 "P"
+  $ hg log -G
+  o  16:aaf3bc4b75c5 P
+  |
+  o  15:abc56d73bb25 C
+  |
+  o  14:08cd84652ed3 D
+  |
+  | @  13:84f40ac83951 R
+  | |
+  o |  11:8d2e6e25498d Q
+  |/
+  o  2:261e70097290 B2
+  |
+  o  0:4a2df7238c3b A
+