Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:44

0001 #!/usr/bin/env python3
0002 import argparse
0003 import os
0004 import sys
0005 from subprocess import check_output
0006 import re
0007 import difflib
0008 from datetime import datetime
0009 from fnmatch import fnmatch
0010 
0011 EXCLUDE = []
0012 
0013 
0014 class bcolors:
0015     HEADER = "\033[95m"
0016     OKBLUE = "\033[94m"
0017     OKGREEN = "\033[92m"
0018     WARNING = "\033[93m"
0019     FAIL = "\033[91m"
0020     ENDC = "\033[0m"
0021     BOLD = "\033[1m"
0022     UNDERLINE = "\033[4m"
0023 
0024 
0025 CROSS_SYMBOL = "\u2717"
0026 
0027 
0028 def err(string):
0029     if sys.stdout.isatty():
0030         return bcolors.FAIL + bcolors.BOLD + string + bcolors.ENDC
0031     else:
0032         return string
0033 
0034 
0035 def main():
0036     p = argparse.ArgumentParser()
0037     p.add_argument("input", nargs="+")
0038     p.add_argument(
0039         "--fix", action="store_true", help="Attempt to fix any license issues found."
0040     )
0041     p.add_argument("--exclude", "-e", action="append", default=EXCLUDE)
0042 
0043     args = p.parse_args()
0044     print(args.exclude)
0045 
0046     extensions = ["cpp", "hpp", "ipp", "cuh", "cu", "C", "h"]
0047 
0048     if len(args.input) == 1 and os.path.isdir(args.input[0]):
0049         find_command = ["find", args.input[0]]
0050         for ext in extensions:
0051             find_command.extend(["-iname", f"*.{ext}", "-or"])
0052         # Remove the last "-or" for a valid command
0053         find_command = find_command[:-1]
0054 
0055         srcs = (
0056             str(
0057                 check_output(find_command),
0058                 "utf-8",
0059             )
0060             .strip()
0061             .split("\n")
0062         )
0063         srcs = filter(lambda p: not p.startswith("./build"), srcs)
0064     else:
0065         srcs = args.input
0066 
0067     founding_year = 2016
0068     year_str = f"{founding_year}"
0069     year = year_str
0070 
0071     raw = """// This file is part of the ACTS project.
0072 //
0073 // Copyright (C) {year} CERN for the benefit of the ACTS project
0074 //
0075 // This Source Code Form is subject to the terms of the Mozilla Public
0076 // License, v. 2.0. If a copy of the MPL was not distributed with this
0077 // file, You can obtain one at https://mozilla.org/MPL/2.0/."""
0078 
0079     reg = (
0080         r"\A// This file is part of the ACTS project.\n"
0081         + r"//\n"
0082         + r"// Copyright \(C\) (?P<year>.*) CERN for the benefit of the ACTS project\n"
0083         + r"//\n"
0084         + r"// This Source Code Form is subject to the terms of the Mozilla Public\n"
0085         + r"// License, v\. 2\.0\. If a copy of the MPL was not distributed with this\n"
0086         + r"// file, You can obtain one at https://mozilla.org/MPL/2.0/.\Z"
0087     )
0088 
0089     ref = re.compile(reg, re.M)
0090     clean_re = re.compile(r"(\(C\)) (.*) (CERN)", re.M)
0091 
0092     def clean(s):
0093         return clean_re.sub(r"\1 XXXX \3", s)
0094 
0095     def get_clean_lines(s):
0096         return [clean(l) + "\n" for l in s.split("\n")]
0097 
0098     error_summary = ""
0099 
0100     def eprint(string):
0101         nonlocal error_summary
0102         error_summary += string + "\n"
0103 
0104     exit = 0
0105     srcs = list(srcs)
0106     nsrcs = len(srcs)
0107     step = max(int(nsrcs / 20), 1)
0108     # Iterate over all files
0109     for i, src in enumerate(srcs):
0110         if any([fnmatch(src, e) for e in args.exclude]):
0111             continue
0112 
0113         # Print progress
0114         if nsrcs > 1 and i % step == 0:
0115             string = f"{i}/{nsrcs} -> {i / float(nsrcs) * 100.0:.2f}%"
0116             if sys.stdout.isatty():
0117                 sys.stdout.write(string + "\r")
0118             else:
0119                 print(string)
0120 
0121         # Read the header
0122         with open(src, "r+") as f:
0123             license = ""
0124             for _ in range(len(raw)):
0125                 line = f.readline()
0126                 if not line.startswith("//"):
0127                     break
0128                 license += line
0129             license = ("".join(license)).strip()
0130             m = ref.search(license)
0131 
0132             # License could not be found in header
0133             if m is None:
0134                 eprint("Invalid / missing license in " + src + "")
0135 
0136                 exp = [l + "\n" for l in raw.format(year=year_str).split("\n")]
0137                 act = get_clean_lines(license)
0138 
0139                 diff = difflib.unified_diff(exp, act)
0140                 eprint("".join(diff))
0141                 eprint("")
0142 
0143                 if args.fix:
0144                     eprint("-> fixing file (prepend)")
0145                     f.seek(0)
0146                     file_content = f.read()
0147                     f.seek(0)
0148                     stmnt = raw.format(year=year_str)
0149                     f.write(stmnt + "\n\n")
0150                     f.write(file_content)
0151 
0152                 exit = 1
0153                 continue
0154 
0155             # We have a match, need to verify year string is right
0156             year_act = m.group("year")
0157             if year_act != year_str:
0158                 exit = 1
0159 
0160                 eprint(f"File: {src}")
0161                 eprint(f"=> License should say {year_str}")
0162                 eprint(err(f"{CROSS_SYMBOL} But says: {year_act}"))
0163 
0164                 if args.fix:
0165                     eprint("-> fixing file (patch year)")
0166 
0167                     new_license = raw.format(year=year_str)
0168 
0169                     # preserve rest of file as is
0170                     old_license_len = len(license)
0171                     f.seek(old_license_len)
0172                     file_body = f.read()
0173                     f.seek(0)
0174                     f.truncate()
0175 
0176                     f.seek(0)
0177                     f.write(new_license)
0178                     f.write(file_body)
0179 
0180                 eprint("")
0181 
0182     print(error_summary)
0183 
0184     if exit != 0 and not args.fix:
0185         print("License problems found. You can try running again with --fix")
0186 
0187     sys.exit(exit)
0188 
0189 
0190 if "__main__" == __name__:
0191     main()