hgext/evolve.py
changeset 1107 1c227ecb744d
parent 1097 580a2d838996
parent 1106 6b0cf1b73693
child 1108 87d60434b434
--- a/hgext/evolve.py	Fri Aug 29 16:13:19 2014 +0200
+++ b/hgext/evolve.py	Tue Sep 02 20:11:45 2014 +0200
@@ -22,11 +22,13 @@
 testedwith = ''
 buglink = 'http://bz.selenic.com/'
 
-import sys
+import sys, os
 import random
 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
@@ -69,6 +71,7 @@
 from mercurial import localrepo
 from mercurial.hgweb import hgweb_mod
 from mercurial import bundle2
+from mercurial import util
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
@@ -376,8 +379,13 @@
         ui.setconfig('alias', 'odiff',
             "diff --hidden --rev 'limit(precursors(.),1)' --rev .")
     if ui.config('alias', 'grab', None) is None:
-        ui.setconfig('alias', 'grab',
-            "! $HG rebase --dest . --rev $@ && $HG up tip")
+        if os.name == 'nt':
+            ui.setconfig('alias', 'grab',
+                "! " + util.hgexecutable() + " rebase --dest . --rev  && "
+                 + util.hgexecutable() + " up tip")
+        else:
+            ui.setconfig('alias', 'grab',
+                "! $HG rebase --dest . --rev $@ && $HG up tip")
 
 
 ### Troubled revset symbol
@@ -776,6 +784,32 @@
     destbookmarks = repo.nodebookmarks(dest.node())
     nodesrc = orig.node()
     destphase = repo[nodesrc].phase()
+    commitmsg = orig.description()
+
+    cache = {}
+    sha1s = re.findall(sha1re, commitmsg)
+    unfi = repo.unfiltered()
+    for sha1 in sha1s:
+        ctx = None
+        try:
+            ctx = unfi[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:
@@ -786,7 +820,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
@@ -1112,6 +1146,8 @@
     confirmopt = opts['confirm']
     ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'evolve')
 
+    startnode = repo['.']
+
     if contopt:
         if anyopt:
             raise util.Abort('cannot specify both "--any" and "--continue"')
@@ -1155,7 +1191,10 @@
                     print 'hg update %s' % ctx.rev()
                     return 0
                 else:
-                    return hg.update(repo, ctx.rev())
+                    res = hg.update(repo, ctx.rev())
+                    if ctx != startnode:
+                        ui.status(_('working directory is now at %s\n') % ctx)
+                    return res
 
         troubled = repo.revs('troubled()')
         if troubled:
@@ -1188,6 +1227,8 @@
         progresscb()
         seen += 1
         if not allopt:
+            if repo['.'] != startnode:
+                ui.status(_('working directory is now at %s\n') % repo['.'])
             return result
         progresscb()
         tro = _picknexttroubled(ui, repo, anyopt or allopt)
@@ -1195,6 +1236,9 @@
     if allopt:
         ui.progress('evolve', None)
 
+    if repo['.'] != startnode:
+        ui.status(_('working directory is now at %s\n') % repo['.'])
+
 
 def _evolveany(ui, repo, tro, dryrunopt, confirmopt, progresscb):
     repo = repo.unfiltered()
@@ -1733,11 +1777,19 @@
         if bookmark:
             _deletebookmark(ui, marks, bookmark)
         for ctx in repo.unfiltered().set('bookmark() and %ld', precs):
-            ldest = list(repo.set('max((::%d) - obsolete())', ctx))
-            if ldest:
-                dest = ldest[0]
-                updatebookmarks = _bookmarksupdater(repo, ctx.node())
-                updatebookmarks(dest.node())
+            # used to be:
+            #
+            #   ldest = list(repo.set('max((::%d) - obsolete())', ctx))
+            #   if ldest:
+            #      c = ldest[0]
+            #
+            # but then revset took a lazy arrow in the knee and became much
+            # slower. The new forms makes as much sense and a much faster.
+            for dest in ctx.ancestors():
+                if not dest.obsolete():
+                    updatebookmarks = _bookmarksupdater(repo, ctx.node())
+                    updatebookmarks(dest.node())
+                    break
     finally:
         lockmod.release(lock, wlock)