autoland: Update rewritecommitdescriptions to output all revisions (bug 1253393) r?smacleod,gps draft
authorbyron jones <glob@mozilla.com>
Tue, 19 Jul 2016 14:44:57 +0800
changeset 8976 08fdf631ddc7a8e5d803d1c1424f2e8c6c131fd1
parent 8975 fa1e02f2094fe92966eddfff2a2e7421b8d755e3
child 8977 c5f3e9f300126f4adc9cb832c7867e37a95e0666
push id1036
push userbjones@mozilla.com
push dateWed, 20 Jul 2016 07:34:03 +0000
reviewerssmacleod, gps
bugs1253393
autoland: Update rewritecommitdescriptions to output all revisions (bug 1253393) r?smacleod,gps Under certain conditions rewritecommitdescriptions is selecting the wrong revision as to base the rebase off. Rework the extension to never skip revisions listed in the commit-descriptions.json, and output the old and new sha1's for every commit to simplify debugging. MozReview-Commit-ID: LEU1FaAb6Wq
autoland/autoland/transplant.py
autoland/hgext/rewritecommitdescriptions.py
autoland/tests/test-rewritecommitdescriptions.t
--- a/autoland/autoland/transplant.py
+++ b/autoland/autoland/transplant.py
@@ -99,26 +99,30 @@ def _transplant(logger, client, tree, de
     if commit_descriptions:
         with tempfile.NamedTemporaryFile() as f:
             json.dump(commit_descriptions, f)
             f.flush()
 
             try:
                 cmd = ['rewritecommitdescriptions',
                        '--descriptions=%s' % f.name, rev]
-                base_revision = run_hg(cmd)
+                cmd_output = run_hg(cmd)
             except hglib.error.CommandError as e:
-                return False, formulate_hg_error(['hg'] + cmd, base_revision)
+                return False, formulate_hg_error(['hg'] + cmd, cmd_output)
 
-        m = re.search(r'base: ([0-9a-z]+)$', base_revision)
-        if not m or not m.groups():
+        for line in cmd_output.splitlines():
+            m = re.search(r'^rev: [0-9a-z]+ -> ([0-9a-z]+)', line)
+            if m and m.groups():
+                base_revision = m.groups()[0]
+                break
+
+        if not base_revision:
             return False, ('Could not determine base revision for rebase: ' +
-                           base_revision)
+                           cmd_output)
 
-        base_revision = m.groups()[0]
         logger.info('base revision: %s' % base_revision)
 
     if not trysyntax and not base_revision:
         return False, 'Could not determine base revision for rebase'
 
     # Perform rebase if necessary
     if not trysyntax:
         try:
--- a/autoland/hgext/rewritecommitdescriptions.py
+++ b/autoland/hgext/rewritecommitdescriptions.py
@@ -1,96 +1,106 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 import json
 import os
 
 from mercurial import (context,
                        cmdutil,
                        encoding,
+                       error,
+                       extensions,
                        phases)
 
-from mercurial.i18n import _
-
 OUR_DIR = os.path.normpath(os.path.dirname(__file__))
 execfile(os.path.join(OUR_DIR, '..', '..', 'hgext', 'bootstrap.py'))
 
 from mozhg import rewrite
 
 testedwith = '3.5'
 
 cmdtable = {}
 command = cmdutil.command(cmdtable)
 
 
 @command('rewritecommitdescriptions',
          [('', 'descriptions', '',
            'path to json file with new commit descriptions', 'string')],
-         _('hg rewritecommitdescriptions'))
-def rewrite_commit_descriptions(ui, repo, node, descriptions=None):
+         'hg rewritecommitdescriptions')
+def rewrite_commit_descriptions(ui, repo, base_node, descriptions=None):
+
+    def sha1_of(node):
+        return repo[node].hex()[:12]
 
+    # Rewriting fails if the evolve extension is enabled.
+    try:
+        extensions.find('evolve')
+        raise error.Abort('Cannot continue as the "evolve" extension is '
+                          'enabled.')
+    except KeyError:
+        pass
+
+    # Read commit descriptions map.
     description_map = {}
     with open(descriptions, 'rb') as f:
         raw_descriptions = json.load(f)
-        for k in raw_descriptions:
-            description_map[k[:12]] = encoding.tolocal(
-                raw_descriptions[k].encode('utf-8'))
+        for sha1 in raw_descriptions:
+            description_map[sha1[:12]] = encoding.tolocal(
+                raw_descriptions[sha1].encode('utf-8'))
+
+    # Collect nodes listed by description_map.
+    nodes = []
 
-    if not node:
-        node = 'tip'
+    def add_node(ctx):
+        node = ctx.node()
+        if sha1_of(node) in description_map:
+            nodes.append(node)
 
-    ctx = repo[node]
-    nodes = [ctx.node()]
+    ctx = repo[base_node]
+    add_node(ctx)
     for ancestor in ctx.ancestors():
-        ctx = repo[ancestor]
         if ctx.phase() != phases.draft:
             break
-        sha1 = repo[ctx.node()].hex()[:12]
-        if sha1 in description_map:
-            nodes.append(ctx.node())
+        add_node(repo[ancestor])
     nodes.reverse()
 
     if not nodes:
-        ui.write(_('no commits found to be rewritten\n'))
-        return 1
+        raise error.Abort('No commits found to be rewritten.')
 
-    oldest_relevant_commit = repo[nodes[0]].hex()[:12]
+    # We need to store the original sha1 values because we won't be able to
+    # look them up once they are rewritten.
+    original_sha1s = {}
+    for node in nodes:
+        original_sha1s[node] = sha1_of(node)
 
+    # Update changed nodes.
     def prune_unchanged(node):
-        sha1 = repo[node].hex()[:12]
-        description = repo[node].description()
-        revised_description = description_map.get(sha1, description)
-        if description == revised_description:
-            ui.write(_('not rewriting %s - description unchanged\n' % sha1))
-            return False
-        return True
+        return repo[node].description() != description_map[sha1_of(node)]
 
-    nodes = filter(prune_unchanged, nodes)
-    if not nodes:
-        ui.write(_('no commits found to be rewritten\n'))
-        # in this case, we need to output the sha1 of the oldest commit
-        # present in commit descriptions
-        ui.write('base: ' + oldest_relevant_commit + '\n')
-        return 0
-
-    def createfn(repo, ctx, revmap, filectxfn):
+    def create_func(repo, ctx, revmap, filectxfn):
         parents = rewrite.newparents(repo, ctx, revmap)
 
         sha1 = ctx.hex()[:12]
-        if sha1 in description_map:
-            description = description_map[sha1]
-        else:
-            description = ctx.description()
+        description = description_map[sha1]
 
         memctx = context.memctx(repo, parents, description,
                                 ctx.files(), filectxfn, user=ctx.user(),
                                 date=ctx.date(), extra=ctx.extra())
         status = ctx.p1().status(ctx)
         memctx.modified = lambda: status[0]
         memctx.added = lambda: status[1]
         memctx.removed = lambda: status[2]
 
         return memctx
 
-    # we output the sha1 of the oldest modified commit
-    nodemap = rewrite.replacechangesets(repo, nodes, createfn)
-    ui.write('base: ' + repo[nodemap[nodes[0]]].hex()[:12] + '\n')
-    return 0
+    node_map = {}
+    changed_nodes = filter(prune_unchanged, nodes)
+    if changed_nodes:
+        node_map = rewrite.replacechangesets(repo, changed_nodes, create_func)
+
+    # Output result.
+    for node in nodes:
+        original_sha1 = original_sha1s[node]
+        if node in node_map:
+            new_sha1 = sha1_of(node_map[node])
+        else:
+            new_sha1 = original_sha1s[node]
+        ui.write('rev: %s -> %s\n' % (original_sha1, new_sha1))
--- a/autoland/tests/test-rewritecommitdescriptions.t
+++ b/autoland/tests/test-rewritecommitdescriptions.t
@@ -21,19 +21,18 @@ Create some commits to rewrite
   $ REV=`hg log -r . --template "{node|short}"`
 
 We handle having no commits which match commit_descriptions properly
 
   $ cat > descriptions.json << EOF
   > {"42": "non-existent commit"}
   > EOF
   $ hg rewritecommitdescriptions --descriptions descriptions.json .
-  not rewriting 10f03055d22c - description unchanged
-  no commits found to be rewritten
-  base: 10f03055d22c
+  abort: No commits found to be rewritten.
+  [255]
   $ hg --encoding utf-8 log
   changeset:   2:10f03055d22c
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     bug 1 - more stuff
   
   changeset:   1:599eee383634
@@ -48,19 +47,17 @@ We handle having no commits which match 
   
 
 We handle having no commits to rewrite properly
 
   $ cat > descriptions.json << EOF
   > {"$REV": "bug 1 - more stuff"}
   > EOF
   $ hg rewritecommitdescriptions --descriptions descriptions.json .
-  not rewriting 10f03055d22c - description unchanged
-  no commits found to be rewritten
-  base: 10f03055d22c
+  rev: 10f03055d22c -> 10f03055d22c
   $ hg --encoding utf-8 log
   changeset:   2:10f03055d22c
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     bug 1 - more stuff
   
   changeset:   1:599eee383634
@@ -76,17 +73,18 @@ We handle having no commits to rewrite p
 
 We handle unicode commit descriptions properly
 
   $ cat > descriptions.json << EOF
   > {"$REV": "bug 1 - こんにちは", "$PARENT": "bug 1 - stuff++"}
   > EOF
   $ hg rewritecommitdescriptions --descriptions descriptions.json .
   saved backup bundle to $TESTTMP/clone/.hg/strip-backup/10f03055d22c-f5e0148f-replacing.hg (glob)
-  base: a1dea3050632
+  rev: 599eee383634 -> a1dea3050632
+  rev: 10f03055d22c -> 99d16379ed19
 
   $ hg --encoding utf-8 log
   changeset:   2:99d16379ed19
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     bug 1 - \xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf (esc)
   
@@ -104,17 +102,17 @@ We handle unicode commit descriptions pr
 We handle long sha1s properly
 
   $ REV=`hg log -r . --template "{node}"`
   $ cat > descriptions.json << EOF
   > {"$REV": "bug 1 - long sha1 is ok"}
   > EOF
   $ hg rewritecommitdescriptions --descriptions descriptions.json .
   saved backup bundle to $TESTTMP/clone/.hg/strip-backup/99d16379ed19-6e1da412-replacing.hg (glob)
-  base: 2c6f2ddf672a
+  rev: 99d16379ed19 -> 2c6f2ddf672a
 
   $ hg --encoding utf-8 log
   changeset:   2:2c6f2ddf672a
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     bug 1 - long sha1 is ok