9f9230833b50b8271840dc2c12bd1e94d9df7d12Alexander Pyhalov#!@PYTHON@
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# This program is free software; you can redistribute it and/or modify
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# it under the terms of the GNU General Public License version 2
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# as published by the Free Software Foundation.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# This program is distributed in the hope that it will be useful,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# but WITHOUT ANY WARRANTY; without even the implied warranty of
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# GNU General Public License for more details.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# You should have received a copy of the GNU General Public License
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# along with this program; if not, write to the Free Software
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# Copyright 2008, 2012 Richard Lowe
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# Copyright 2014 Garrett D'Amore <garrett@damore.org>
e55874358132a4aa6132178335bf567ca79c87c3Joshua M. Clulow# Copyright (c) 2014, Joyent, Inc.
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweimport getopt
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweimport os
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweimport re
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweimport subprocess
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweimport sys
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Loweimport tempfile
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowefrom cStringIO import StringIO
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# Adjust the load path based on our location and the version of python into
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# which it is being loaded. This assumes the normal onbld directory
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# structure, where we are in bin/ and the modules are in
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# lib/python(version)?/onbld/Scm/. If that changes so too must this.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowesys.path.insert(1, os.path.join(os.path.dirname(__file__), "..", "lib",
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe "python%d.%d" % sys.version_info[:2]))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# Add the relative path to usr/src/tools to the load path, such that when run
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe# from the source tree we use the modules also within the source tree.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe#
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowesys.path.insert(2, os.path.join(os.path.dirname(__file__), ".."))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
e55874358132a4aa6132178335bf567ca79c87c3Joshua M. Clulowfrom onbld.Scm import Ignore
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowefrom onbld.Checks import Comments, Copyright, CStyle, HdrChk
71af3be340c57171837478555e2eb0d496318cfcCody Peter Mellofrom onbld.Checks import JStyle, Keywords, ManLint, Mapfile, SpellCheck
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweclass GitError(Exception):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe pass
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git(command):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Run a command and return a stream containing its stdout (and write its
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe stderr to its stdout)"""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if type(command) != list:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe command = command.split()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe command = ["git"] + command
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe try:
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe tmpfile = tempfile.TemporaryFile(prefix="git-nits")
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe except EnvironmentError, e:
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe raise GitError("Could not create temporary file: %s\n" % e)
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe try:
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe p = subprocess.Popen(command,
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe stdout=tmpfile,
380fd671753dd199e149f10e9f73ec52cdfe4230Matthew Ahrens stderr=subprocess.PIPE)
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe except OSError, e:
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe raise GitError("could not execute %s: %s\n" (command, e))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe err = p.wait()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if err != 0:
380fd671753dd199e149f10e9f73ec52cdfe4230Matthew Ahrens raise GitError(p.stderr.read())
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe tmpfile.seek(0)
ff50e8e5ae1af23788a33c5296dd2009f3b8baf7Richard Lowe return tmpfile
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git_root():
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return the root of the current git workspace"""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe p = git('rev-parse --git-dir')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Failed finding git workspace\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(err)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return os.path.abspath(os.path.join(p.readlines()[0],
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe os.path.pardir))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git_branch():
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return the current git branch"""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe p = git('branch')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Failed finding git branch\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(err)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for elt in p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if elt[0] == '*':
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if elt.endswith('(no branch)'):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return None
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return elt.split()[1]
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git_parent_branch(branch):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return the parent of the current git branch.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe If this branch tracks a remote branch, return the remote branch which is
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe tracked. If not, default to origin/master."""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not branch:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return None
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe p = git("for-each-ref --format=%(refname:short) %(upstream:short) " +
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe "refs/heads/")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Failed finding git parent branch\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(err)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for line in p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # Git 1.7 will leave a ' ' trailing any non-tracking branch
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if ' ' in line and not line.endswith(' \n'):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe local, remote = line.split()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if local == branch:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return remote
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return 'origin/master'
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git_comments(parent):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return a list of any checkin comments on this git branch"""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
27495383ee5e81658b2c3bbd8f51f5b0dddeb3d8Richard Lowe p = git('log --pretty=tformat:%%B:SEP: %s..' % parent)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Failed getting git comments\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(err)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
27495383ee5e81658b2c3bbd8f51f5b0dddeb3d8Richard Lowe return [x.strip() for x in p.readlines() if x != ':SEP:\n']
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef git_file_list(parent, paths=None):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return the set of files which have ever changed on this branch.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe NB: This includes files which no longer exist, or no longer actually
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe differ."""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe p = git("log --name-only --pretty=format: %s.. %s" %
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe (parent, ' '.join(paths)))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not p:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Failed building file-list from git\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(err)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = set()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for fname in p:
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie if fname and not fname.isspace() and fname not in ret:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret.add(fname.strip())
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef not_check(root, cmd):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return a function which returns True if a file given as an argument
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe should be excluded from the check named by 'cmd'"""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ignorefiles = filter(os.path.exists,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe [os.path.join(root, ".git", "%s.NOT" % cmd),
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe os.path.join(root, "exception_lists", cmd)])
e55874358132a4aa6132178335bf567ca79c87c3Joshua M. Clulow return Ignore.ignore(root, ignorefiles)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef gen_files(root, parent, paths, exclude):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Return a function producing file names, relative to the current
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe directory, of any file changed on this branch (limited to 'paths' if
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe requested), and excluding files for which exclude returns a true value """
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # Taken entirely from Python 2.6's os.path.relpath which we would use if we
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # could.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe def relpath(path, here):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe c = os.path.abspath(os.path.join(root, path)).split(os.path.sep)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe s = os.path.abspath(here).split(os.path.sep)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe l = len(os.path.commonprefix((s, c)))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return os.path.join(*[os.path.pardir] * (len(s)-l) + c[l:])
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe def ret(select=None):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not select:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe select = lambda x: True
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in git_file_list(parent, paths):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe f = relpath(f, '.')
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie try:
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie res = git("diff %s HEAD %s" % (parent, f))
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie except GitError, e:
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie # This ignores all the errors that can be thrown. Usually, this means
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie # that git returned non-zero because the file doesn't exist, but it
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie # could also fail if git can't create a new file or it can't be
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie # executed. Such errors are 1) unlikely, and 2) will be caught by other
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie # invocations of git().
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie continue
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie empty = not res.readline()
93d2a904d17ac0073fa98bf62f89294d980c8b3dPaul Dagnelie if (os.path.exists(f) and not empty and select(f) and not exclude(f)):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe yield f
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef comchk(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("Comments:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return Comments.comchk(git_comments(parent), check_db=True,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output=output)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef mapfilechk(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # We are interested in examining any file that has the following
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # in its final path segment:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # - Contains the word 'mapfile'
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # - Begins with 'map.'
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # - Ends with '.map'
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # We don't want to match unless these things occur in final path segment
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # because directory names with these strings don't indicate a mapfile.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # We also ignore files with suffixes that tell us that the files
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe # are not mapfiles.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe MapfileRE = re.compile(r'.*((mapfile[^/]*)|(/map\.+[^/]*)|(\.map))$',
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe re.IGNORECASE)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe NotMapSuffixRE = re.compile(r'.*\.[ch]$', re.IGNORECASE)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("Mapfile comments:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist(lambda x: MapfileRE.match(x) and not
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe NotMapSuffixRE.match(x)):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= Mapfile.mapfilechk(fh, output=output)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef copyright(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("Copyrights:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist():
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= Copyright.copyright(fh, output=output)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef hdrchk(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("Header format:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist(lambda x: x.endswith('.h')):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= HdrChk.hdrchk(fh, lenient=True, output=output)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef cstyle(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("C style:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist(lambda x: x.endswith('.c') or x.endswith('.h')):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= CStyle.cstyle(fh, output=output, picky=True,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe check_posix_types=True,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe check_continuation=True)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef jstyle(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("Java style:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist(lambda x: x.endswith('.java')):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= JStyle.jstyle(fh, output=output, picky=True)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoredef manlint(root, parent, flist, output):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ret = 0
71af3be340c57171837478555e2eb0d496318cfcCody Peter Mello output.write("Man page format/spelling:\n")
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ManfileRE = re.compile(r'.*\.[0-9][a-z]*$', re.IGNORECASE)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for f in flist(lambda x: ManfileRE.match(x)):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fh = open(f, 'r')
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ret |= ManLint.manlint(fh, output=output, picky=True)
71af3be340c57171837478555e2eb0d496318cfcCody Peter Mello ret |= SpellCheck.spellcheck(fh, output=output)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore fh.close()
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return ret
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef keywords(root, parent, flist, output):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output.write("SCCS Keywords:\n")
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for f in flist():
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh = open(f, 'r')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= Keywords.keywords(fh, output=output)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe fh.close()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef run_checks(root, parent, cmds, paths='', opts={}):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe """Run the checks given in 'cmds', expected to have well-known signatures,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe and report results for any which fail.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe Return failure if any of them did.
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe NB: the function name of the commands passed in is used to name the NOT
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe file which excepts files from them."""
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret = 0
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for cmd in cmds:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe s = StringIO()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe exclude = not_check(root, cmd.func_name)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe result = cmd(root, parent, gen_files(root, parent, paths, exclude),
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe output=s)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe ret |= result
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if result != 0:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe print s.getvalue()
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe return ret
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef nits(root, parent, paths):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe cmds = [copyright,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe cstyle,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe hdrchk,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe jstyle,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe keywords,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore manlint,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe mapfilechk]
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe run_checks(root, parent, cmds, paths)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef pbchk(root, parent, paths):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe cmds = [comchk,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe copyright,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe cstyle,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe hdrchk,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe jstyle,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe keywords,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore manlint,
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe mapfilechk]
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe run_checks(root, parent, cmds)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowedef main(cmd, args):
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe parent_branch = None
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe try:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe opts, args = getopt.getopt(args, 'b:')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe except getopt.GetoptError, e:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write(str(e) + '\n')
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("Usage: %s [-b branch] [path...]\n" % cmd)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(1)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe for opt, arg in opts:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if opt == '-b':
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe parent_branch = arg
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if not parent_branch:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe parent_branch = git_parent_branch(git_branch())
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe func = nits
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if cmd == 'git-pbchk':
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe func = pbchk
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe if args:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("only complete workspaces may be pbchk'd\n");
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(1)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe func(git_root(), parent_branch, args)
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Loweif __name__ == '__main__':
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe try:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe main(os.path.basename(sys.argv[0]), sys.argv[1:])
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe except GitError, e:
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.stderr.write("failed to run git:\n %s\n" % str(e))
8bcea973790ad3e762bf78b7c6ad5776e463fd51Richard Lowe sys.exit(1)