Sync scripts with Arm internal CI
This patch syncs utility scripts and scripts
in the script directory with the internal CI.
Where a path update is required,
the changes have been commented out.
Signed-off-by: Zelalem <zelalem.aweke@arm.com>
Change-Id: Ifa4bd805e345184d1378e8423e5f878a2fbfbcd4
diff --git a/script/static-checks/check-copyright.py b/script/static-checks/check-copyright.py
index 350381b..39863c7 100755
--- a/script/static-checks/check-copyright.py
+++ b/script/static-checks/check-copyright.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -8,8 +8,10 @@
"""
Check if a given file includes the copyright boiler plate.
This checker supports the following comment styles:
- * Used by .c, .h, .S, .dts and .dtsi files
- # Used by Makefile (including .mk)
+ /*
+ *
+ //
+ #
"""
import argparse
@@ -24,7 +26,9 @@
from itertools import islice
# File extensions to check
-VALID_FILE_EXTENSIONS = ('.c', '.S', '.h', 'Makefile', '.mk', '.dts', '.dtsi', '.ld')
+VALID_FILE_EXTENSIONS = ('.c', '.conf', '.dts', '.dtsi', '.editorconfig',
+ '.h', '.i', '.ld', 'Makefile', '.mk', '.msvc',
+ '.py', '.S', '.scat', '.sh')
# Paths inside the tree to ignore. Hidden folders and files are always ignored.
# They mustn't end in '/'.
@@ -41,47 +45,64 @@
)
# Supported comment styles (Python regex)
-COMMENT_PATTERN = '^(( \* ?)|(\# ?))'
+COMMENT_PATTERN = '(\*|/\*|\#|//)'
-# License pattern to match
-LICENSE_PATTERN = '''(?P<copyright_prologue>
-{0}Copyright \(c\) (?P<years>[0-9]{{4}}(-[0-9]{{4}})?), (Arm Limited|ARM Limited and Contributors)\. All rights reserved\.$
-{0}$
-{0}SPDX-License-Identifier: BSD-3-Clause$
-)'''.format(
- COMMENT_PATTERN
-)
+# Any combination of spaces and/or tabs
+SPACING = '[ \t]*'
-# Compiled license pattern
-RE_PATTERN = re.compile(LICENSE_PATTERN, re.MULTILINE)
+# Line must start with a comment and optional spacing
+LINE_START = '^' + SPACING + COMMENT_PATTERN + SPACING
+
+# Line end with optional spacing
+EOL = SPACING + '$'
+
+# Year or period as YYYY or YYYY-YYYY
+TIME_PERIOD = '[0-9]{4}(-[0-9]{4})?'
+
+# Any string with valid license ID, don't allow adding postfix
+LICENSE_ID = '.*(BSD-3-Clause|BSD-2-Clause-FreeBSD)([ ,.\);].*)?'
+
+# File must contain both lines to pass the check
+COPYRIGHT_LINE = LINE_START + 'Copyright' + '.*' + TIME_PERIOD + '.*' + EOL
+LICENSE_ID_LINE = LINE_START + 'SPDX-License-Identifier:' + LICENSE_ID + EOL
+
+# Compiled license patterns
+COPYRIGHT_PATTERN = re.compile(COPYRIGHT_LINE, re.MULTILINE)
+LICENSE_ID_PATTERN = re.compile(LICENSE_ID_LINE, re.MULTILINE)
+
+CURRENT_YEAR = str(datetime.datetime.now().year)
COPYRIGHT_OK = 0
COPYRIGHT_ERROR = 1
-COPYRIGHT_WARNING = 2
-def check_copyright(path):
+def check_copyright(path, args, encoding='utf-8'):
'''Checks a file for a correct copyright header.'''
- with open(path) as file_:
+ result = COPYRIGHT_OK
+
+ with open(path, encoding=encoding) as file_:
file_content = file_.read()
- if RE_PATTERN.search(file_content):
- return COPYRIGHT_OK
+ copyright_line = COPYRIGHT_PATTERN.search(file_content)
+ if not copyright_line:
+ print("ERROR: Missing copyright in " + file_.name)
+ result = COPYRIGHT_ERROR
+ elif CURRENT_YEAR not in copyright_line.group():
+ print("WARNING: Copyright is out of date in " + file_.name + ": '" +
+ copyright_line.group() + "'")
- for line in file_content.split('\n'):
- if 'SPDX-License-Identifier' in line:
- if ('BSD-3-Clause' in line or
- 'BSD-2-Clause-FreeBSD' in line):
- return COPYRIGHT_WARNING
- break
+ if not LICENSE_ID_PATTERN.search(file_content):
+ print("ERROR: License ID error in " + file_.name)
+ result = COPYRIGHT_ERROR
- return COPYRIGHT_ERROR
-
+ return result
def main(args):
print("Checking the copyrights in the code...")
- all_files_correct = True
+ if args.verbose:
+ print ("Copyright regexp: " + COPYRIGHT_LINE)
+ print ("License regexp: " + LICENSE_ID_LINE)
if args.patch:
print("Checking files modified between patches " + args.from_ref
@@ -90,7 +111,7 @@
(rc, stdout, stderr) = utils.shell_command(['git', 'diff',
'--diff-filter=ACMRT', '--name-only', args.from_ref, args.to_ref ])
if rc:
- return 1
+ return COPYRIGHT_ERROR
files = stdout.splitlines()
@@ -99,7 +120,7 @@
(rc, stdout, stderr) = utils.shell_command([ 'git', 'ls-files' ])
if rc:
- return 1
+ return COPYRIGHT_ERROR
files = stdout.splitlines()
@@ -117,30 +138,22 @@
if args.verbose:
print("Checking file " + f)
- rc = check_copyright(f)
+ rc = check_copyright(f, args)
if rc == COPYRIGHT_OK:
count_ok += 1
- elif rc == COPYRIGHT_WARNING:
- count_warning += 1
- print("WARNING: " + f)
elif rc == COPYRIGHT_ERROR:
count_error += 1
- print("ERROR: " + f)
print("\nSummary:")
- print("\t{} files analyzed".format(count_ok + count_warning + count_error))
+ print("\t{} files analyzed".format(count_ok + count_error))
- if count_warning == 0 and count_error == 0:
+ if count_error == 0:
print("\tNo errors found")
- return 0
-
- if count_error > 0:
+ return COPYRIGHT_OK
+ else:
print("\t{} errors found".format(count_error))
-
- if count_warning > 0:
- print("\t{} warnings found".format(count_warning))
-
+ return COPYRIGHT_ERROR
def parse_cmd_line(argv, prog_name):
parser = argparse.ArgumentParser(
@@ -166,9 +179,20 @@
Instead of checking all files in the source tree, the script will consider
only files that are modified by the latest patch(es).""",
action="store_true")
+
+ (rc, stdout, stderr) = utils.shell_command(['git', 'merge-base', 'HEAD', 'master'])
+ if rc:
+ print("Git merge-base command failed. Cannot determine base commit.")
+ sys.exit(rc)
+ merge_bases = stdout.splitlines()
+
+ # This should not happen, but it's better to be safe.
+ if len(merge_bases) > 1:
+ print("WARNING: Multiple merge bases found. Using the first one as base commit.")
+
parser.add_argument("--from-ref",
help="Base commit in patch mode (default: %(default)s)",
- default="master")
+ default=merge_bases[0])
parser.add_argument("--to-ref",
help="Final commit in patch mode (default: %(default)s)",
default="HEAD")