Patchwork [4,of,4] debugrevspec: add option to verify optimized result

login
register
mail settings
Submitter Yuya Nishihara
Date Sept. 12, 2016, 1:36 p.m.
Message ID <a378406437403d761975.1473687399@mimosa>
Download mbox | patch
Permalink /patch/16594/
State Accepted
Headers show

Comments

Yuya Nishihara - Sept. 12, 2016, 1:36 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1471752981 -32400
#      Sun Aug 21 13:16:21 2016 +0900
# Node ID a378406437403d761975f68b039ec71ede070846
# Parent  87e3a09996cb563315210364c1b9b47f04042726
debugrevspec: add option to verify optimized result

This provides a convenient way to diff "hg debugrevspec" outputs generated
with/without --no-optimized option.
Augie Fackler - Sept. 12, 2016, 2:08 p.m.
On Mon, Sep 12, 2016 at 10:36:39PM +0900, Yuya Nishihara wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya@tcha.org>
> # Date 1471752981 -32400
> #      Sun Aug 21 13:16:21 2016 +0900
> # Node ID a378406437403d761975f68b039ec71ede070846
> # Parent  87e3a09996cb563315210364c1b9b47f04042726
> debugrevspec: add option to verify optimized result

These are queued, thanks.

>
> This provides a convenient way to diff "hg debugrevspec" outputs generated
> with/without --no-optimized option.
>
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -3516,6 +3516,7 @@ def debugrevlog(ui, repo, file_=None, **
>       ('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 @@ def debugrevspec(ui, repo, expr, **opts)
>
>      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 @@ def debugrevspec(ui, repo, expr, **opts)
>      ]
>      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 @@ def debugrevspec(ui, repo, expr, **opts)
>                  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:
> diff --git a/tests/test-completion.t b/tests/test-completion.t
> --- a/tests/test-completion.t
> +++ b/tests/test-completion.t
> @@ -269,7 +269,7 @@ Show all commands + options
>    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:
> diff --git a/tests/test-revset.t b/tests/test-revset.t
> --- a/tests/test-revset.t
> +++ b/tests/test-revset.t
> @@ -554,6 +554,37 @@ parsed tree at stages:
>    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.
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3516,6 +3516,7 @@  def debugrevlog(ui, repo, file_=None, **
      ('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 @@  def debugrevspec(ui, repo, expr, **opts)
 
     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 @@  def debugrevspec(ui, repo, expr, **opts)
     ]
     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 @@  def debugrevspec(ui, repo, expr, **opts)
                 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:
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -269,7 +269,7 @@  Show all commands + options
   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: 
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -554,6 +554,37 @@  parsed tree at stages:
   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.