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
--- 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