Patchwork [2,of,2,evolve-ext,V3] evolve: replace each obsolete sha1 in the description with its latest successor

login
register
mail settings
Submitter Matt Harbison
Date Aug. 23, 2014, 4:34 a.m.
Message ID <b55312c001122c7b62b5.1408768478@Envy>
Download mbox | patch
Permalink /patch/5558/
State Not Applicable
Headers show

Comments

Matt Harbison - Aug. 23, 2014, 4:34 a.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1407625936 14400
#      Sat Aug 09 19:12:16 2014 -0400
# Node ID b55312c001122c7b62b52cf74b0572891b57aa6b
# Parent  9eb66cdb73c968395cf2f73f40a241ad4920eb24
evolve: replace each obsolete sha1 in the description with its latest successor

Obsolete csets are hidden by default and don't get pushed to the parent repo.
In order to avoid broken references in commit messages, it makes sense to evolve
those references to the latest and greatest successor, as each cset containing
them is evolved.  Of course, stale references can still occur if a commit in
branch 'A' references something in branch 'B', and that something in 'B' is
evolved but 'A' isn't subsequently evolved.

This alleviates the user that is evolving a series of commits from having to

  1) recognize that there is a hash that needs updating in any one of the series
  2) look up the latest successor manually
  3) hg amend -e

The regular expression for matching and the logic for replacing are borrowed
from the convert extension [1].

It might be nice for the output to state the reason that the reference couldn't
be updated (it was pruned, split or diverged), but that may be excessive for
something only displayed in verbose mode.  (Maybe it should be a ui.status()
instead?)

[1] http://selenic.com/hg/rev/45562379ce4e
Pierre-Yves David - Sept. 2, 2014, 7:10 p.m.
On 08/23/2014 06:34 AM, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1407625936 14400
> #      Sat Aug 09 19:12:16 2014 -0400
> # Node ID b55312c001122c7b62b52cf74b0572891b57aa6b
> # Parent  9eb66cdb73c968395cf2f73f40a241ad4920eb24
> evolve: replace each obsolete sha1 in the description with its latest successor
>
> Obsolete csets are hidden by default and don't get pushed to the parent repo.
> In order to avoid broken references in commit messages, it makes sense to evolve
> those references to the latest and greatest successor, as each cset containing
> them is evolved.  Of course, stale references can still occur if a commit in
> branch 'A' references something in branch 'B', and that something in 'B' is
> evolved but 'A' isn't subsequently evolved.
>
> This alleviates the user that is evolving a series of commits from having to
>
>    1) recognize that there is a hash that needs updating in any one of the series
>    2) look up the latest successor manually
>    3) hg amend -e
>
> The regular expression for matching and the logic for replacing are borrowed
> from the convert extension [1].
>
> It might be nice for the output to state the reason that the reference couldn't
> be updated (it was pruned, split or diverged), but that may be excessive for
> something only displayed in verbose mode.  (Maybe it should be a ui.status()
> instead?)
>
> [1] http://selenic.com/hg/rev/45562379ce4e
>
> diff --git a/hgext/evolve.py b/hgext/evolve.py
> --- a/hgext/evolve.py
> +++ b/hgext/evolve.py
> @@ -27,6 +27,8 @@
>   from StringIO import StringIO
>   import struct
>   import urllib
> +import re
> +sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
>
>   import mercurial
>   from mercurial import util
> @@ -903,6 +905,31 @@
>       destbookmarks = repo.nodebookmarks(dest.node())
>       nodesrc = orig.node()
>       destphase = repo[nodesrc].phase()
> +    commitmsg = orig.description()
> +
> +    cache = {}
> +    sha1s = re.findall(sha1re, commitmsg)
> +    for sha1 in sha1s:
> +        ctx = None
> +        try:
> +            ctx = repo.unfiltered()[sha1]
> +        except error.RepoLookupError:
> +            continue
> +
> +        if not ctx.obsolete():
> +            continue
> +
> +        successors = obsolete.successorssets(repo, ctx.node(), cache)
> +
> +        # We can't make any assumptions about how to update the hash if the
> +        # cset in question was split or diverged.
> +        if len(successors) == 1 and len(successors[0]) == 1:
> +            newsha1 = node.hex(successors[0][0])
> +            commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)])
> +        else:
> +            repo.ui.note(_('The stale commit message reference to %s could '
> +                           'not be updated') % sha1)
> +
>       tr = repo.transaction('relocate')
>       try:
>           try:
> @@ -913,7 +940,7 @@
>                           'unresolved merge conflicts (see hg help resolve)')
>               cmdutil.duplicatecopies(repo, orig.node(), dest.node())
>               nodenew = rebase.concludenode(repo, orig.node(), dest.node(),
> -                                          node.nullid)
> +                                          node.nullid, commitmsg)
>           except util.Abort, exc:
>               class LocalMergeFailure(MergeFailure, exc.__class__):
>                   pass
> diff --git a/tests/test-evolve.t b/tests/test-evolve.t
> --- a/tests/test-evolve.t
> +++ b/tests/test-evolve.t
> @@ -271,7 +271,7 @@
>     atop:[6] a nifty feature
>     merging main-file-1
>     $ hg log
> -  7	feature-B: another feature (child of 568a468b60fc) - test
> +  7	feature-B: another feature (child of ba0ec09b1bab) - test
>     6	feature-A: a nifty feature - test
>     0	: base - test
>
> @@ -300,7 +300,7 @@
>     $ hg glog
>     @  8	feature-B: another feature that rox - test
>     |
> -  | o  7	: another feature (child of 568a468b60fc) - test
> +  | o  7	: another feature (child of ba0ec09b1bab) - test
>     |/
>     o  6	feature-A: a nifty feature - test
>     |
> @@ -308,13 +308,13 @@
>
>     $ hg evolve --any --traceback
>     recreate:[8] another feature that rox
> -  atop:[7] another feature (child of 568a468b60fc)
> +  atop:[7] another feature (child of ba0ec09b1bab)
>     computing new diff
> -  committed as 8234cfce9af9
> +  committed as 476d0454d60e
>     $ hg glog
> -  @  9	feature-B: bumped update to 5b410c3ae5af: - test
> +  @  9	feature-B: bumped update to 5c9c8d9c2e4e: - test
>     |
> -  o  7	: another feature (child of 568a468b60fc) - test
> +  o  7	: another feature (child of ba0ec09b1bab) - test
>     |
>     o  6	feature-A: a nifty feature - test
>     |
> @@ -376,7 +376,7 @@
>     |
>     o  13	feature-B: dansk! - test
>     |
> -  o  7	: another feature (child of 568a468b60fc) - test
> +  o  7	: another feature (child of ba0ec09b1bab) - test
>     |
>     o  6	feature-A: a nifty feature - test
>     |
> @@ -743,11 +743,11 @@
>     2 changesets folded
>     1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>     $ glog
> -  @  16:d0aee199f74c@default(draft) Folding with custom commit message
> +  @  16:d6239ff09c9f@default(draft) Folding with custom commit message
>     |
> -  o  13:b0258f43f9d0@default(draft) dansk!
> +  o  13:56ade053f46d@default(draft) dansk!
>     |
> -  o  7:5b410c3ae5af@default(public) another feature (child of 568a468b60fc)
> +  o  7:5c9c8d9c2e4e@default(public) another feature (child of ba0ec09b1bab)
>     |
>     o  6:ba0ec09b1bab@default(public) a nifty feature
>     |
> @@ -762,8 +762,8 @@
>     2 changesets folded
>     1 files updated, 0 files merged, 0 files removed, 0 files unresolved
>     $ hg qlog
> -  17 - bf2fd466ccd4 A longer
> +  17 - dba606655966 A longer
>                       commit message (draft)
> -  7 - 5b410c3ae5af another feature (child of 568a468b60fc) (public)
> +  7 - 5c9c8d9c2e4e another feature (child of ba0ec09b1bab) (public)
>     6 - ba0ec09b1bab a nifty feature (public)
>     0 - e55e0562ee93 base (public)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>

Patch

diff --git a/hgext/evolve.py b/hgext/evolve.py
--- a/hgext/evolve.py
+++ b/hgext/evolve.py
@@ -27,6 +27,8 @@ 
 from StringIO import StringIO
 import struct
 import urllib
+import re
+sha1re = re.compile(r'\b[0-9a-f]{6,40}\b')
 
 import mercurial
 from mercurial import util
@@ -903,6 +905,31 @@ 
     destbookmarks = repo.nodebookmarks(dest.node())
     nodesrc = orig.node()
     destphase = repo[nodesrc].phase()
+    commitmsg = orig.description()
+
+    cache = {}
+    sha1s = re.findall(sha1re, commitmsg)
+    for sha1 in sha1s:
+        ctx = None
+        try:
+            ctx = repo.unfiltered()[sha1]
+        except error.RepoLookupError:
+            continue
+
+        if not ctx.obsolete():
+            continue
+
+        successors = obsolete.successorssets(repo, ctx.node(), cache)
+
+        # We can't make any assumptions about how to update the hash if the
+        # cset in question was split or diverged.
+        if len(successors) == 1 and len(successors[0]) == 1:
+            newsha1 = node.hex(successors[0][0])
+            commitmsg = commitmsg.replace(sha1, newsha1[:len(sha1)])
+        else:
+            repo.ui.note(_('The stale commit message reference to %s could '
+                           'not be updated') % sha1)
+
     tr = repo.transaction('relocate')
     try:
         try:
@@ -913,7 +940,7 @@ 
                         'unresolved merge conflicts (see hg help resolve)')
             cmdutil.duplicatecopies(repo, orig.node(), dest.node())
             nodenew = rebase.concludenode(repo, orig.node(), dest.node(),
-                                          node.nullid)
+                                          node.nullid, commitmsg)
         except util.Abort, exc:
             class LocalMergeFailure(MergeFailure, exc.__class__):
                 pass
diff --git a/tests/test-evolve.t b/tests/test-evolve.t
--- a/tests/test-evolve.t
+++ b/tests/test-evolve.t
@@ -271,7 +271,7 @@ 
   atop:[6] a nifty feature
   merging main-file-1
   $ hg log
-  7	feature-B: another feature (child of 568a468b60fc) - test
+  7	feature-B: another feature (child of ba0ec09b1bab) - test
   6	feature-A: a nifty feature - test
   0	: base - test
 
@@ -300,7 +300,7 @@ 
   $ hg glog
   @  8	feature-B: another feature that rox - test
   |
-  | o  7	: another feature (child of 568a468b60fc) - test
+  | o  7	: another feature (child of ba0ec09b1bab) - test
   |/
   o  6	feature-A: a nifty feature - test
   |
@@ -308,13 +308,13 @@ 
   
   $ hg evolve --any --traceback
   recreate:[8] another feature that rox
-  atop:[7] another feature (child of 568a468b60fc)
+  atop:[7] another feature (child of ba0ec09b1bab)
   computing new diff
-  committed as 8234cfce9af9
+  committed as 476d0454d60e
   $ hg glog
-  @  9	feature-B: bumped update to 5b410c3ae5af: - test
+  @  9	feature-B: bumped update to 5c9c8d9c2e4e: - test
   |
-  o  7	: another feature (child of 568a468b60fc) - test
+  o  7	: another feature (child of ba0ec09b1bab) - test
   |
   o  6	feature-A: a nifty feature - test
   |
@@ -376,7 +376,7 @@ 
   |
   o  13	feature-B: dansk! - test
   |
-  o  7	: another feature (child of 568a468b60fc) - test
+  o  7	: another feature (child of ba0ec09b1bab) - test
   |
   o  6	feature-A: a nifty feature - test
   |
@@ -743,11 +743,11 @@ 
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ glog
-  @  16:d0aee199f74c@default(draft) Folding with custom commit message
+  @  16:d6239ff09c9f@default(draft) Folding with custom commit message
   |
-  o  13:b0258f43f9d0@default(draft) dansk!
+  o  13:56ade053f46d@default(draft) dansk!
   |
-  o  7:5b410c3ae5af@default(public) another feature (child of 568a468b60fc)
+  o  7:5c9c8d9c2e4e@default(public) another feature (child of ba0ec09b1bab)
   |
   o  6:ba0ec09b1bab@default(public) a nifty feature
   |
@@ -762,8 +762,8 @@ 
   2 changesets folded
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg qlog
-  17 - bf2fd466ccd4 A longer
+  17 - dba606655966 A longer
                     commit message (draft)
-  7 - 5b410c3ae5af another feature (child of 568a468b60fc) (public)
+  7 - 5c9c8d9c2e4e another feature (child of ba0ec09b1bab) (public)
   6 - ba0ec09b1bab a nifty feature (public)
   0 - e55e0562ee93 base (public)