debugrevspec: add option to verify optimized result
This provides a convenient way to diff "hg debugrevspec" outputs generated
with/without --no-optimized option.
--- a/mercurial/commands.py Sun Aug 21 12:40:02 2016 +0900
+++ b/mercurial/commands.py Sun Aug 21 13:16:21 2016 +0900
@@ -3516,6 +3516,7 @@
('p', 'show-stage', [],
_('print parsed tree at the given stage'), _('NAME')),
('', 'no-optimized', False, _('evaluate tree without optimization')),
+ ('', 'verify-optimized', False, _('verify optimized result')),
],
('REVSPEC'))
def debugrevspec(ui, repo, expr, **opts):
@@ -3523,6 +3524,9 @@
Use -p/--show-stage option to print the parsed tree at the given stages.
Use -p all to print tree at every stage.
+
+ Use --verify-optimized to compare the optimized result with the unoptimized
+ one. Returns 1 if the optimized result differs.
"""
stages = [
('parsed', lambda tree: tree),
@@ -3533,6 +3537,9 @@
]
if opts['no_optimized']:
stages = stages[:-1]
+ if opts['verify_optimized'] and opts['no_optimized']:
+ raise error.Abort(_('cannot use --verify-optimized with '
+ '--no-optimized'))
stagenames = set(n for n, f in stages)
showalways = set()
@@ -3553,16 +3560,42 @@
raise error.Abort(_('invalid stage name: %s') % n)
showalways.update(opts['show_stage'])
+ treebystage = {}
printedtree = None
tree = revset.parse(expr, lookup=repo.__contains__)
for n, f in stages:
- tree = f(tree)
+ treebystage[n] = tree = f(tree)
if n in showalways or (n in showchanged and tree != printedtree):
if opts['show_stage'] or n != 'parsed':
ui.write(("* %s:\n") % n)
ui.write(revset.prettyformat(tree), "\n")
printedtree = tree
+ if opts['verify_optimized']:
+ arevs = revset.makematcher(treebystage['analyzed'])(repo)
+ brevs = revset.makematcher(treebystage['optimized'])(repo)
+ if ui.verbose:
+ ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
+ ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
+ arevs = list(arevs)
+ brevs = list(brevs)
+ if arevs == brevs:
+ return 0
+ ui.write(('--- analyzed\n'), label='diff.file_a')
+ ui.write(('+++ optimized\n'), label='diff.file_b')
+ sm = difflib.SequenceMatcher(None, arevs, brevs)
+ for tag, alo, ahi, blo, bhi in sm.get_opcodes():
+ if tag in ('delete', 'replace'):
+ for c in arevs[alo:ahi]:
+ ui.write('-%s\n' % c, label='diff.deleted')
+ if tag in ('insert', 'replace'):
+ for c in brevs[blo:bhi]:
+ ui.write('+%s\n' % c, label='diff.inserted')
+ if tag == 'equal':
+ for c in arevs[alo:ahi]:
+ ui.write(' %s\n' % c)
+ return 1
+
func = revset.makematcher(tree)
revs = func(repo)
if ui.verbose:
--- a/tests/test-completion.t Sun Aug 21 12:40:02 2016 +0900
+++ b/tests/test-completion.t Sun Aug 21 13:16:21 2016 +0900
@@ -269,7 +269,7 @@
debugrebuildfncache:
debugrename: rev
debugrevlog: changelog, manifest, dir, dump
- debugrevspec: optimize, show-stage, no-optimized
+ debugrevspec: optimize, show-stage, no-optimized, verify-optimized
debugsetparents:
debugsub: rev
debugsuccessorssets:
--- a/tests/test-revset.t Sun Aug 21 12:40:02 2016 +0900
+++ b/tests/test-revset.t Sun Aug 21 13:16:21 2016 +0900
@@ -554,6 +554,37 @@
abort: cannot use --optimize with --show-stage
[255]
+verify optimized tree:
+
+ $ hg debugrevspec --verify '0|1'
+
+ $ hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'
+ * analyzed:
+ (and
+ (func
+ ('symbol', 'r3232')
+ None)
+ ('symbol', '2'))
+ * optimized:
+ (and
+ ('symbol', '2')
+ (func
+ ('symbol', 'r3232')
+ None))
+ * analyzed set:
+ <baseset [2]>
+ * optimized set:
+ <baseset [2, 2]>
+ --- analyzed
+ +++ optimized
+ 2
+ +2
+ [1]
+
+ $ hg debugrevspec --no-optimized --verify-optimized '0'
+ abort: cannot use --verify-optimized with --no-optimized
+ [255]
+
Test that symbols only get parsed as functions if there's an opening
parenthesis.