comparison mercurial/commands.py @ 29924:45bf56a89197

debugrevspec: add option to verify optimized result This provides a convenient way to diff "hg debugrevspec" outputs generated with/without --no-optimized option.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 21 Aug 2016 13:16:21 +0900
parents 429fd2747d9a
children e7cacb45c4be
comparison
equal deleted inserted replaced
29923:429fd2747d9a 29924:45bf56a89197
3514 [('', 'optimize', None, 3514 [('', 'optimize', None,
3515 _('print parsed tree after optimizing (DEPRECATED)')), 3515 _('print parsed tree after optimizing (DEPRECATED)')),
3516 ('p', 'show-stage', [], 3516 ('p', 'show-stage', [],
3517 _('print parsed tree at the given stage'), _('NAME')), 3517 _('print parsed tree at the given stage'), _('NAME')),
3518 ('', 'no-optimized', False, _('evaluate tree without optimization')), 3518 ('', 'no-optimized', False, _('evaluate tree without optimization')),
3519 ('', 'verify-optimized', False, _('verify optimized result')),
3519 ], 3520 ],
3520 ('REVSPEC')) 3521 ('REVSPEC'))
3521 def debugrevspec(ui, repo, expr, **opts): 3522 def debugrevspec(ui, repo, expr, **opts):
3522 """parse and apply a revision specification 3523 """parse and apply a revision specification
3523 3524
3524 Use -p/--show-stage option to print the parsed tree at the given stages. 3525 Use -p/--show-stage option to print the parsed tree at the given stages.
3525 Use -p all to print tree at every stage. 3526 Use -p all to print tree at every stage.
3527
3528 Use --verify-optimized to compare the optimized result with the unoptimized
3529 one. Returns 1 if the optimized result differs.
3526 """ 3530 """
3527 stages = [ 3531 stages = [
3528 ('parsed', lambda tree: tree), 3532 ('parsed', lambda tree: tree),
3529 ('expanded', lambda tree: revset.expandaliases(ui, tree)), 3533 ('expanded', lambda tree: revset.expandaliases(ui, tree)),
3530 ('concatenated', revset.foldconcat), 3534 ('concatenated', revset.foldconcat),
3531 ('analyzed', revset.analyze), 3535 ('analyzed', revset.analyze),
3532 ('optimized', revset.optimize), 3536 ('optimized', revset.optimize),
3533 ] 3537 ]
3534 if opts['no_optimized']: 3538 if opts['no_optimized']:
3535 stages = stages[:-1] 3539 stages = stages[:-1]
3540 if opts['verify_optimized'] and opts['no_optimized']:
3541 raise error.Abort(_('cannot use --verify-optimized with '
3542 '--no-optimized'))
3536 stagenames = set(n for n, f in stages) 3543 stagenames = set(n for n, f in stages)
3537 3544
3538 showalways = set() 3545 showalways = set()
3539 showchanged = set() 3546 showchanged = set()
3540 if ui.verbose and not opts['show_stage']: 3547 if ui.verbose and not opts['show_stage']:
3551 for n in opts['show_stage']: 3558 for n in opts['show_stage']:
3552 if n not in stagenames: 3559 if n not in stagenames:
3553 raise error.Abort(_('invalid stage name: %s') % n) 3560 raise error.Abort(_('invalid stage name: %s') % n)
3554 showalways.update(opts['show_stage']) 3561 showalways.update(opts['show_stage'])
3555 3562
3563 treebystage = {}
3556 printedtree = None 3564 printedtree = None
3557 tree = revset.parse(expr, lookup=repo.__contains__) 3565 tree = revset.parse(expr, lookup=repo.__contains__)
3558 for n, f in stages: 3566 for n, f in stages:
3559 tree = f(tree) 3567 treebystage[n] = tree = f(tree)
3560 if n in showalways or (n in showchanged and tree != printedtree): 3568 if n in showalways or (n in showchanged and tree != printedtree):
3561 if opts['show_stage'] or n != 'parsed': 3569 if opts['show_stage'] or n != 'parsed':
3562 ui.write(("* %s:\n") % n) 3570 ui.write(("* %s:\n") % n)
3563 ui.write(revset.prettyformat(tree), "\n") 3571 ui.write(revset.prettyformat(tree), "\n")
3564 printedtree = tree 3572 printedtree = tree
3573
3574 if opts['verify_optimized']:
3575 arevs = revset.makematcher(treebystage['analyzed'])(repo)
3576 brevs = revset.makematcher(treebystage['optimized'])(repo)
3577 if ui.verbose:
3578 ui.note(("* analyzed set:\n"), revset.prettyformatset(arevs), "\n")
3579 ui.note(("* optimized set:\n"), revset.prettyformatset(brevs), "\n")
3580 arevs = list(arevs)
3581 brevs = list(brevs)
3582 if arevs == brevs:
3583 return 0
3584 ui.write(('--- analyzed\n'), label='diff.file_a')
3585 ui.write(('+++ optimized\n'), label='diff.file_b')
3586 sm = difflib.SequenceMatcher(None, arevs, brevs)
3587 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3588 if tag in ('delete', 'replace'):
3589 for c in arevs[alo:ahi]:
3590 ui.write('-%s\n' % c, label='diff.deleted')
3591 if tag in ('insert', 'replace'):
3592 for c in brevs[blo:bhi]:
3593 ui.write('+%s\n' % c, label='diff.inserted')
3594 if tag == 'equal':
3595 for c in arevs[alo:ahi]:
3596 ui.write(' %s\n' % c)
3597 return 1
3565 3598
3566 func = revset.makematcher(tree) 3599 func = revset.makematcher(tree)
3567 revs = func(repo) 3600 revs = func(repo)
3568 if ui.verbose: 3601 if ui.verbose:
3569 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n") 3602 ui.note(("* set:\n"), revset.prettyformatset(revs), "\n")