From e2a1e2cc835b917b2696b43fd6eae1f11314bff2 Mon Sep 17 00:00:00 2001 From: Al Grant Date: Sat, 1 Feb 2025 14:20:55 +0000 Subject: [PATCH] update source license checker --- check_for_license.py | 70 ++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 18 deletions(-) mode change 100755 => 100644 check_for_license.py diff --git a/check_for_license.py b/check_for_license.py old mode 100755 new mode 100644 index 802b557..8ba4d10 --- a/check_for_license.py +++ b/check_for_license.py @@ -24,8 +24,13 @@ import os, sys + +o_verbose = 0 + + ## Distance we need to find the license text in -LICENSE_MAX_LINE = 20 +LICENSE_MAX_LINE = 32 + ## Texts to search for, with a flag to say if it's the 'approved' license LICENSE_TEXT = { @@ -35,14 +40,19 @@ } +# Source extensions. +# Other files (e.g. makefiles) may be considered sources on an ad-hoc basis. +SOURCE_EXTS = [".c", ".cpp", ".h", ".py", ".json", ".xml"] + + def fn_is_source(fn): """ Test a filename to check that it's source code and needs a license. """ - base, ext = os.path.splitext(fn) - if "makefile" in base: - return base - return ext in [".c", ".cpp", ".h", ".py", ".json", ".xml"] + (base, ext) = os.path.splitext(fn) + if base in ["makefile", "Makefile"]: + return True + return ext in SOURCE_EXTS def fn_is_licensed(fn): @@ -50,24 +60,35 @@ def fn_is_licensed(fn): Check that a source file already has appropriate license text embedded in it., within the first LICENSE_MAX_LINE lines. """ - found = None + if o_verbose: + print("checking: %s..." % fn) + license_found = None + copyright_found = None + license_is_irregular = False f = open(fn) lno = 0 for ln in f: lno += 1 - for ltext, is_regular in LICENSE_TEXT.items(): + for (ltext, is_regular) in LICENSE_TEXT.items(): ix = ln.find(ltext) if ix >= 0: - found = lno - break - if found is not None: + license_found = lno + if lno > LICENSE_MAX_LINE: + print("%s: license found at line %u, later than expected" % (fn, lno), file=sys.stderr) + if not is_regular: + print("%s: irregular license waiver" % (fn), file=sys.stderr) + license_is_irregular = True break - if lno > LICENSE_MAX_LINE: + if "Copyright" in ln and ("ARM" in ln) or ("Arm" in ln): + copyright_found = lno + if license_found is not None and copyright_found is not None: break - if False: - if found is not None: - print("%s: found at line %u" % (fn, found)) - return found is not None + if lno > LICENSE_MAX_LINE*5: + break + if o_verbose: + if license_found is not None: + print("%s: license found at line %u" % (fn, license_found)) + return license_found is not None and ((copyright_found is not None) or license_is_irregular) def check_all_sources_licensed(dir): @@ -76,9 +97,11 @@ def check_all_sources_licensed(dir): """ n_files = 0 n_unlicensed = 0 - for root, dirs, files in os.walk(dir): + for (root, dirs, files) in os.walk(dir): + if root != "." and root.startswith("."): + continue for f in files: - fn = os.path.join(root, f) + fn = os.path.join(root, f) if fn_is_source(fn): n_files += 1 if not fn_is_licensed(fn): @@ -88,5 +111,16 @@ def check_all_sources_licensed(dir): if __name__ == "__main__": - sys.exit(check_all_sources_licensed(os.path.dirname(os.path.realpath(__file__))) > 0) + import argparse + parser = argparse.ArgumentParser(description="check source files for licenses") + parser.add_argument("dirs", nargs="*", help="source directories to check") + parser.add_argument("-v", "--verbose", action="count", default=0, help="increase verbosity") + opts = parser.parse_args() + o_verbose = opts.verbose + if not opts.dirs: + opts.dirs = [os.path.dirname(os.path.realpath(__file__))] + n_unlicensed = 0 + for dir in opts.dirs: + n_unlicensed += check_all_sources_licensed(dir) + sys.exit(n_unlicensed > 0)