From 896ef305bcbe2b83c44e2bc90d76b5bd5634ecaf Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 4 Jan 2016 14:41:25 -0800 Subject: Add copyright checks to sanity; make them verify copyright year is valid --- tools/distrib/check_copyright.py | 98 ++++++++++++++++++++++------------------ tools/run_tests/run_sanity.sh | 1 + 2 files changed, 56 insertions(+), 43 deletions(-) (limited to 'tools') diff --git a/tools/distrib/check_copyright.py b/tools/distrib/check_copyright.py index 1693f7ce9e..6c66a29180 100755 --- a/tools/distrib/check_copyright.py +++ b/tools/distrib/check_copyright.py @@ -1,6 +1,6 @@ #!/usr/bin/env python2.7 -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -30,7 +30,9 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse +import datetime import os +import re import sys import subprocess @@ -52,10 +54,6 @@ argp.add_argument('-a', '--ancient', default=0, action='store_const', const=1) -argp.add_argument('-f', '--fix', - default=0, - action='store_const', - const=1) args = argp.parse_args() # open the license text @@ -66,34 +64,46 @@ with open('LICENSE') as f: # key is the file extension, value is a format string # that given a line of license text, returns what should # be in the file -LICENSE_FMT = { - '.c': ' * %s', - '.cc': ' * %s', - '.h': ' * %s', - '.m': ' * %s', - '.php': ' * %s', - '.py': '# %s', - '.rb': '# %s', - '.sh': '# %s', - '.proto': '// %s', - '.js': ' * %s', - '.cs': '// %s', - '.mak': '# %s', - 'Makefile': '# %s', - 'Dockerfile': '# %s', +LICENSE_PREFIX = { + '.c': r'\s*\*\s*', + '.cc': r'\s*\*\s*', + '.h': r'\s*\*\s*', + '.m': r'\s*\*\s*', + '.php': r'\s*\*\s*', + '.js': r'\s*\*\s*', + '.py': r'#\s*', + '.rb': r'#\s*', + '.sh': r'#\s*', + '.proto': r'//\s*', + '.cs': r'//\s*', + '.mak': r'#\s*', + 'Makefile': r'#\s*', + 'Dockerfile': r'#\s*', + 'LICENSE': '', } KNOWN_BAD = set([ 'src/php/tests/bootstrap.php', ]) -# pregenerate the actual text that we should have -LICENSE_TEXT = dict( - (k, '\n'.join((v % line).rstrip() for line in LICENSE)) - for k, v in LICENSE_FMT.iteritems()) -OLD_LICENSE_TEXT = dict( - (k, v.replace('2015', '2014')) for k, v in LICENSE_TEXT.iteritems()) +RE_YEAR = r'Copyright (?:[0-9]+\-)?([0-9]+), Google Inc\.' +RE_LICENSE = dict( + (k, r'\n'.join( + LICENSE_PREFIX[k] + + (RE_YEAR if re.search(RE_YEAR, line) else re.escape(line)) + for line in LICENSE)) + for k, v in LICENSE_PREFIX.iteritems()) + + +def load(name): + with open(name) as f: + return '\n'.join(line.rstrip() for line in f.read().splitlines()) + + +assert(re.search(RE_LICENSE['LICENSE'], load('LICENSE'))) +assert(re.search(RE_LICENSE['Makefile'], load('Makefile'))) + def log(cond, why, filename): if not cond: return @@ -102,30 +112,32 @@ def log(cond, why, filename): else: print filename + # scan files, validate the text for filename in subprocess.check_output('git ls-tree -r --name-only -r HEAD', shell=True).splitlines(): if filename in KNOWN_BAD: continue ext = os.path.splitext(filename)[1] base = os.path.basename(filename) - if ext in LICENSE_TEXT: - license = LICENSE_TEXT[ext] - old_license = OLD_LICENSE_TEXT[ext] - elif base in LICENSE_TEXT: - license = LICENSE_TEXT[base] - old_license = OLD_LICENSE_TEXT[base] + if ext in RE_LICENSE: + re_license = RE_LICENSE[ext] + elif base in RE_LICENSE: + re_license = RE_LICENSE[base] else: log(args.skips, 'skip', filename) continue - with open(filename) as f: - text = '\n'.join(line.rstrip() for line in f.read().splitlines()) - if license in text: - pass - elif old_license in text: - log(args.ancient, 'old', filename) - if args.fix: - with open(filename, 'w') as f: - f.write(text.replace('Copyright 2014, Google Inc.', 'Copyright 2015, Google Inc.') + '\n') - elif 'DO NOT EDIT' not in text and 'AssemblyInfo.cs' not in filename: - log(1, 'missing', filename) + text = load(filename) + ok = True + m = re.search(re_license, text) + if m: + last_modified = int(subprocess.check_output('git log -1 --format="%ad" --date=short -- ' + filename, shell=True)[0:4]) + latest_claimed = int(m.group(1)) + if last_modified > latest_claimed: + print '%s modified %d but copyright only extends to %d' % (filename, last_modified, latest_claimed) + ok = False + elif 'DO NOT EDIT' not in text and 'AssemblyInfo.cs' not in filename and filename != 'src/boringssl/err_data.c': + log(1, 'copyright missing', filename) + ok = False + +sys.exit(0 if ok else 1) diff --git a/tools/run_tests/run_sanity.sh b/tools/run_tests/run_sanity.sh index 1e8fe5c1a7..81efdb70b3 100755 --- a/tools/run_tests/run_sanity.sh +++ b/tools/run_tests/run_sanity.sh @@ -58,5 +58,6 @@ if [ -f cache.mk ] ; then fi ./tools/buildgen/generate_projects.sh +./tools/distrib/check_copyright.py ./tools/distrib/clang_format_code.sh -- cgit v1.2.3