Initial commit for TF-A CI scripts
Signed-off-by: Fathi Boudra <fathi.boudra@linaro.org>
diff --git a/script/static-checks/check-copyright.py b/script/static-checks/check-copyright.py
new file mode 100755
index 0000000..350381b
--- /dev/null
+++ b/script/static-checks/check-copyright.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+"""
+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
+import datetime
+import collections
+import fnmatch
+import shlex
+import os
+import re
+import sys
+import utils
+from itertools import islice
+
+# File extensions to check
+VALID_FILE_EXTENSIONS = ('.c', '.S', '.h', 'Makefile', '.mk', '.dts', '.dtsi', '.ld')
+
+# Paths inside the tree to ignore. Hidden folders and files are always ignored.
+# They mustn't end in '/'.
+IGNORED_FOLDERS = (
+ 'include/lib/libfdt',
+ 'lib/compiler-rt',
+ 'lib/libfdt',
+ 'lib/zlib'
+)
+
+# List of ignored files in folders that aren't ignored
+IGNORED_FILES = (
+ 'include/tools_share/uuid.h'
+)
+
+# Supported comment styles (Python regex)
+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
+)
+
+# Compiled license pattern
+RE_PATTERN = re.compile(LICENSE_PATTERN, re.MULTILINE)
+
+COPYRIGHT_OK = 0
+COPYRIGHT_ERROR = 1
+COPYRIGHT_WARNING = 2
+
+def check_copyright(path):
+ '''Checks a file for a correct copyright header.'''
+
+ with open(path) as file_:
+ file_content = file_.read()
+
+ if RE_PATTERN.search(file_content):
+ return COPYRIGHT_OK
+
+ 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
+
+ return COPYRIGHT_ERROR
+
+
+def main(args):
+ print("Checking the copyrights in the code...")
+
+ all_files_correct = True
+
+ if args.patch:
+ print("Checking files modified between patches " + args.from_ref
+ + " and " + args.to_ref + "...")
+
+ (rc, stdout, stderr) = utils.shell_command(['git', 'diff',
+ '--diff-filter=ACMRT', '--name-only', args.from_ref, args.to_ref ])
+ if rc:
+ return 1
+
+ files = stdout.splitlines()
+
+ else:
+ print("Checking all files tracked by git...")
+
+ (rc, stdout, stderr) = utils.shell_command([ 'git', 'ls-files' ])
+ if rc:
+ return 1
+
+ files = stdout.splitlines()
+
+ count_ok = 0
+ count_warning = 0
+ count_error = 0
+
+ for f in files:
+
+ if utils.file_is_ignored(f, VALID_FILE_EXTENSIONS, IGNORED_FILES, IGNORED_FOLDERS):
+ if args.verbose:
+ print("Ignoring file " + f)
+ continue
+
+ if args.verbose:
+ print("Checking file " + f)
+
+ rc = check_copyright(f)
+
+ 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))
+
+ if count_warning == 0 and count_error == 0:
+ print("\tNo errors found")
+ return 0
+
+ if count_error > 0:
+ print("\t{} errors found".format(count_error))
+
+ if count_warning > 0:
+ print("\t{} warnings found".format(count_warning))
+
+
+def parse_cmd_line(argv, prog_name):
+ parser = argparse.ArgumentParser(
+ prog=prog_name,
+ formatter_class=argparse.RawTextHelpFormatter,
+ description="Check copyright of all files of codebase",
+ epilog="""
+For each source file in the tree, checks that the copyright header
+has the correct format.
+""")
+
+ parser.add_argument("--tree", "-t",
+ help="Path to the source tree to check (default: %(default)s)",
+ default=os.curdir)
+
+ parser.add_argument("--verbose", "-v",
+ help="Increase verbosity to the source tree to check (default: %(default)s)",
+ action='store_true', default=False)
+
+ parser.add_argument("--patch", "-p",
+ help="""
+Patch mode.
+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")
+ parser.add_argument("--from-ref",
+ help="Base commit in patch mode (default: %(default)s)",
+ default="master")
+ parser.add_argument("--to-ref",
+ help="Final commit in patch mode (default: %(default)s)",
+ default="HEAD")
+
+ args = parser.parse_args(argv)
+ return args
+
+
+if __name__ == "__main__":
+ args = parse_cmd_line(sys.argv[1:], sys.argv[0])
+
+ os.chdir(args.tree)
+
+ rc = main(args)
+
+ sys.exit(rc)