hgstyle.py revision 11409
112837Sgabeblack@google.com#! /usr/bin/env python 212837Sgabeblack@google.com# Copyright (c) 2014 ARM Limited 312837Sgabeblack@google.com# All rights reserved 412837Sgabeblack@google.com# 512837Sgabeblack@google.com# The license below extends only to copyright in the software and shall 612837Sgabeblack@google.com# not be construed as granting a license to any other intellectual 712837Sgabeblack@google.com# property including but not limited to intellectual property relating 812837Sgabeblack@google.com# to a hardware implementation of the functionality of the software 912837Sgabeblack@google.com# licensed hereunder. You may use the software subject to the license 1012837Sgabeblack@google.com# terms below provided that you ensure that this notice is replicated 1112837Sgabeblack@google.com# unmodified and in its entirety in all distributions of the software, 1212837Sgabeblack@google.com# modified or unmodified, in source code or in binary form. 1312837Sgabeblack@google.com# 1412837Sgabeblack@google.com# Copyright (c) 2006 The Regents of The University of Michigan 1512837Sgabeblack@google.com# Copyright (c) 2007,2011 The Hewlett-Packard Development Company 1612837Sgabeblack@google.com# Copyright (c) 2016 Advanced Micro Devices, Inc. 1712837Sgabeblack@google.com# All rights reserved. 1812837Sgabeblack@google.com# 1912837Sgabeblack@google.com# Redistribution and use in source and binary forms, with or without 2012837Sgabeblack@google.com# modification, are permitted provided that the following conditions are 2112837Sgabeblack@google.com# met: redistributions of source code must retain the above copyright 2212837Sgabeblack@google.com# notice, this list of conditions and the following disclaimer; 2312837Sgabeblack@google.com# redistributions in binary form must reproduce the above copyright 2412837Sgabeblack@google.com# notice, this list of conditions and the following disclaimer in the 2512837Sgabeblack@google.com# documentation and/or other materials provided with the distribution; 2612837Sgabeblack@google.com# neither the name of the copyright holders nor the names of its 2712837Sgabeblack@google.com# contributors may be used to endorse or promote products derived from 2812837Sgabeblack@google.com# this software without specific prior written permission. 2912837Sgabeblack@google.com# 3012837Sgabeblack@google.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3112837Sgabeblack@google.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3212862Sgabeblack@google.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3312837Sgabeblack@google.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3412862Sgabeblack@google.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3512837Sgabeblack@google.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3612956Sgabeblack@google.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3712862Sgabeblack@google.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3812837Sgabeblack@google.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3912956Sgabeblack@google.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 4012837Sgabeblack@google.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4112861Sgabeblack@google.com# 4212837Sgabeblack@google.com# Authors: Nathan Binkert 4312949Sgabeblack@google.com# Steve Reinhardt 4412949Sgabeblack@google.com 4512837Sgabeblack@google.comimport sys 4612837Sgabeblack@google.comimport os 4712837Sgabeblack@google.comfrom os.path import join as joinpath 4812837Sgabeblack@google.com 4912837Sgabeblack@google.comcurrent_dir = os.path.dirname(__file__) 5012837Sgabeblack@google.comsys.path.insert(0, current_dir) 5112837Sgabeblack@google.com 5212837Sgabeblack@google.comfrom style.verifiers import all_verifiers 5312837Sgabeblack@google.comfrom style.style import MercurialUI, check_ignores 5412837Sgabeblack@google.comfrom style.region import * 5512837Sgabeblack@google.com 5612837Sgabeblack@google.comfrom mercurial import bdiff, mdiff, commands 5712862Sgabeblack@google.com 5812862Sgabeblack@google.comdef modified_regions(old_data, new_data): 5912862Sgabeblack@google.com regions = Regions() 6012862Sgabeblack@google.com beg = None 6112862Sgabeblack@google.com for pbeg, pend, fbeg, fend in bdiff.blocks(old_data, new_data): 6212949Sgabeblack@google.com if beg is not None and beg != fbeg: 6312949Sgabeblack@google.com regions.append(beg, fbeg) 6412949Sgabeblack@google.com beg = fend 6512949Sgabeblack@google.com return regions 6612949Sgabeblack@google.com 6712949Sgabeblack@google.comdef modregions(wctx, fname): 6812862Sgabeblack@google.com fctx = wctx.filectx(fname) 6912862Sgabeblack@google.com pctx = fctx.parents() 7012862Sgabeblack@google.com 7112862Sgabeblack@google.com file_data = fctx.data() 7212862Sgabeblack@google.com lines = mdiff.splitnewlines(file_data) 7312837Sgabeblack@google.com if len(pctx) in (1, 2): 7412837Sgabeblack@google.com mod_regions = modified_regions(pctx[0].data(), file_data) 7512837Sgabeblack@google.com if len(pctx) == 2: 7612837Sgabeblack@google.com m2 = modified_regions(pctx[1].data(), file_data) 7712837Sgabeblack@google.com # only the lines that are new in both 7812837Sgabeblack@google.com mod_regions &= m2 7912837Sgabeblack@google.com else: 8012837Sgabeblack@google.com mod_regions = Regions() 8112837Sgabeblack@google.com mod_regions.append(0, len(lines)) 8212837Sgabeblack@google.com 8312837Sgabeblack@google.com return mod_regions 8412837Sgabeblack@google.com 8512837Sgabeblack@google.com 8612837Sgabeblack@google.comdef _modified_regions(repo, patterns, **kwargs): 8712837Sgabeblack@google.com opt_all = kwargs.get('all', False) 8812837Sgabeblack@google.com opt_no_ignore = kwargs.get('no_ignore', False) 8912837Sgabeblack@google.com 9012837Sgabeblack@google.com # Import the match (repository file name matching helper) 9112837Sgabeblack@google.com # function. Different versions of Mercurial keep it in different 9212837Sgabeblack@google.com # modules and implement them differently. 9312837Sgabeblack@google.com try: 9412837Sgabeblack@google.com from mercurial import scmutil 9512837Sgabeblack@google.com m = scmutil.match(repo[None], patterns, kwargs) 9612837Sgabeblack@google.com except ImportError: 9712837Sgabeblack@google.com from mercurial import cmdutil 9812837Sgabeblack@google.com m = cmdutil.match(repo, patterns, kwargs) 9912837Sgabeblack@google.com 10012837Sgabeblack@google.com modified, added, removed, deleted, unknown, ignore, clean = \ 10112837Sgabeblack@google.com repo.status(match=m, clean=opt_all) 10212837Sgabeblack@google.com 10312837Sgabeblack@google.com if not opt_all: 10412837Sgabeblack@google.com try: 10512837Sgabeblack@google.com wctx = repo.workingctx() 10612837Sgabeblack@google.com except: 10712837Sgabeblack@google.com from mercurial import context 10812837Sgabeblack@google.com wctx = context.workingctx(repo) 10912837Sgabeblack@google.com 11012862Sgabeblack@google.com files = [ (fn, all_regions) for fn in added ] + \ 11112837Sgabeblack@google.com [ (fn, modregions(wctx, fn)) for fn in modified ] 11212837Sgabeblack@google.com else: 11312837Sgabeblack@google.com files = [ (fn, all_regions) for fn in added + modified + clean ] 11412837Sgabeblack@google.com 11512837Sgabeblack@google.com for fname, mod_regions in files: 11612837Sgabeblack@google.com if opt_no_ignore or not check_ignores(fname): 11712837Sgabeblack@google.com yield fname, mod_regions 11812837Sgabeblack@google.com 11912837Sgabeblack@google.com 12012837Sgabeblack@google.comdef do_check_style(hgui, repo, *pats, **opts): 12112837Sgabeblack@google.com """check files for proper m5 style guidelines 12212837Sgabeblack@google.com 12312861Sgabeblack@google.com Without an argument, checks all modified and added files for gem5 12412861Sgabeblack@google.com coding style violations. A list of files can be specified to limit 12512861Sgabeblack@google.com the checker to a subset of the repository. The style rules are 12612862Sgabeblack@google.com normally applied on a diff of the repository state (i.e., added 12712862Sgabeblack@google.com files are checked in their entirety while only modifications of 12812862Sgabeblack@google.com modified files are checked). 12912837Sgabeblack@google.com 13012837Sgabeblack@google.com The --all option can be specified to include clean files and check 13112837Sgabeblack@google.com modified files in their entirety. 13212837Sgabeblack@google.com 13312837Sgabeblack@google.com The --fix-<check>, --ignore-<check>, and --skip-<check> options 13412837Sgabeblack@google.com can be used to control individual style checks: 13512837Sgabeblack@google.com 13612837Sgabeblack@google.com --fix-<check> will perform the check and automatically attempt to 13712837Sgabeblack@google.com fix sny style error (printing a warning if unsuccessful) 13812837Sgabeblack@google.com 13912837Sgabeblack@google.com --ignore-<check> will perform the check but ignore any errors 14012837Sgabeblack@google.com found (other than printing a message for each) 14112837Sgabeblack@google.com 14212837Sgabeblack@google.com --skip-<check> will skip performing the check entirely 14312860Sgabeblack@google.com 14412860Sgabeblack@google.com If none of these options are given, all checks will be performed 14512860Sgabeblack@google.com and the user will be prompted on how to handle each error. 14612862Sgabeblack@google.com 14712862Sgabeblack@google.com --fix-all, --ignore-all, and --skip-all are equivalent to specifying 14812862Sgabeblack@google.com --fix-<check>, --ignore-<check>, or --skip-<check> for all checks, 14912862Sgabeblack@google.com respectively. However, option settings for specific checks take 15012862Sgabeblack@google.com precedence. Thus --skip-all --fix-white can be used to skip every 15112860Sgabeblack@google.com check other than whitespace errors, which will be checked and 15212860Sgabeblack@google.com automatically fixed. 15312860Sgabeblack@google.com 15412860Sgabeblack@google.com The -v/--verbose flag will display the offending line(s) as well 15512860Sgabeblack@google.com as their location. 15612860Sgabeblack@google.com """ 15712860Sgabeblack@google.com 15812860Sgabeblack@google.com ui = MercurialUI(hgui, verbose=hgui.verbose) 15912860Sgabeblack@google.com 16012860Sgabeblack@google.com # instantiate varifier objects 16112860Sgabeblack@google.com verifiers = [v(ui, opts, base=repo.root) for v in all_verifiers] 16212862Sgabeblack@google.com 16312862Sgabeblack@google.com for fname, mod_regions in _modified_regions(repo, pats, **opts): 16412862Sgabeblack@google.com for verifier in verifiers: 16512862Sgabeblack@google.com if verifier.apply(joinpath(repo.root, fname), mod_regions): 16612862Sgabeblack@google.com return True 16712862Sgabeblack@google.com 16812860Sgabeblack@google.com return False 16912860Sgabeblack@google.com 17012860Sgabeblack@google.comdef check_hook(hooktype): 17112860Sgabeblack@google.com if hooktype not in ('pretxncommit', 'pre-qrefresh'): 17212860Sgabeblack@google.com raise AttributeError, \ 17312861Sgabeblack@google.com "This hook is not meant for %s" % hooktype 17412861Sgabeblack@google.com 17512861Sgabeblack@google.com# This function provides a hook that is called before transaction 17612861Sgabeblack@google.com# commit and on qrefresh 17712861Sgabeblack@google.comdef check_style(ui, repo, hooktype, **kwargs): 17812861Sgabeblack@google.com check_hook(hooktype) 17912860Sgabeblack@google.com args = {} 18012860Sgabeblack@google.com 18112860Sgabeblack@google.com try: 18212860Sgabeblack@google.com return do_check_style(ui, repo, **args) 18312860Sgabeblack@google.com except Exception, e: 18412861Sgabeblack@google.com import traceback 18512860Sgabeblack@google.com traceback.print_exc() 18612860Sgabeblack@google.com return True 18712860Sgabeblack@google.com 18812860Sgabeblack@google.comtry: 18912860Sgabeblack@google.com from mercurial.i18n import _ 19012860Sgabeblack@google.comexcept ImportError: 19112860Sgabeblack@google.com def _(arg): 19212860Sgabeblack@google.com return arg 19312860Sgabeblack@google.com 19412860Sgabeblack@google.com_common_region_options = [ 19512860Sgabeblack@google.com ('a', 'all', False, 19612956Sgabeblack@google.com _("include clean files and unmodified parts of modified files")), 19712956Sgabeblack@google.com ('', 'no-ignore', False, _("ignore the style ignore list")), 19812956Sgabeblack@google.com ] 19912956Sgabeblack@google.com 20012956Sgabeblack@google.com 20112860Sgabeblack@google.comfix_opts = [('f', 'fix-all', False, _("fix all style errors"))] + \ 20212860Sgabeblack@google.com [('', 'fix-' + v.opt_name, False, 20312860Sgabeblack@google.com _('fix errors in ' + v.test_name)) for v in all_verifiers] 20412860Sgabeblack@google.comignore_opts = [('', 'ignore-all', False, _("ignore all style errors"))] + \ 20512860Sgabeblack@google.com [('', 'ignore-' + v.opt_name, False, 20612956Sgabeblack@google.com _('ignore errors in ' + v.test_name)) for v in all_verifiers] 20712860Sgabeblack@google.comskip_opts = [('', 'skip-all', False, _("skip all style error checks"))] + \ 20812860Sgabeblack@google.com [('', 'skip-' + v.opt_name, False, 20912860Sgabeblack@google.com _('skip checking for ' + v.test_name)) for v in all_verifiers] 21012860Sgabeblack@google.comall_opts = fix_opts + ignore_opts + skip_opts 21112860Sgabeblack@google.com 21212861Sgabeblack@google.com 21312860Sgabeblack@google.comcmdtable = { 21412860Sgabeblack@google.com '^m5style' : ( 21512860Sgabeblack@google.com do_check_style, all_opts + _common_region_options + commands.walkopts, 21612860Sgabeblack@google.com _('hg m5style [-a] [FILE]...')), 21712860Sgabeblack@google.com} 21812860Sgabeblack@google.com 21912860Sgabeblack@google.comif __name__ == '__main__': 22012860Sgabeblack@google.com print >> sys.stderr, "This file cannot be used from the command line. Use" 22112860Sgabeblack@google.com print >> sys.stderr, "style.py instead." 22212860Sgabeblack@google.com sys.exit(1) 22312860Sgabeblack@google.com