From 9ee32b060be3a4d82eeef5b382448d7001b48b24 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Mon, 13 Jan 2025 14:56:46 -0800 Subject: [PATCH] WIP --- lib/spack/spack/cmd/license.py | 39 +++++++++++++++++++---------- lib/spack/spack/test/cmd/license.py | 16 ++++++++++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/spack/spack/cmd/license.py b/lib/spack/spack/cmd/license.py index 3460a947c1c..3445bdc1be1 100644 --- a/lib/spack/spack/cmd/license.py +++ b/lib/spack/spack/cmd/license.py @@ -211,50 +211,63 @@ def _fix_path(path: str) -> List[str]: Returns: List of fixed lines, if a fix was possible, otherwise an empty list. """ - lines = open(path, encoding="utf-8").read().split("\n") + comment, fixed = "#", fixed_lines + if path.endswith(".lp"): + fixed = [line.replace(comment, "%") for line in fixed_lines] + comment = "%" - # only try to fix python files / scripts - if not (path.endswith(".py") or path.endswith(".sh") or (lines and lines[0].startswith("#!"))): + try: + if path.endswith(".py") or path.endswith(".sh"): + with open(path, encoding="utf-8") as f: + lines = f.read().split("\n") + else: + with open(path, encoding="utf-8") as f: + if f.read(2) != "#!": + return [] + f.seek(0) + lines = f.read().split("\n") + except UnicodeDecodeError: return [] # easy case: license looks mostly familiar - start = next((i for i, line in enumerate(lines) if re.match(r"#\s*Copyright", line)), -1) - end = next((i for i, line in enumerate(lines) if re.match(r"#\s*SPDX-", line)), -1) - + start = next( + (i for i, line in enumerate(lines) if re.match(rf"{comment}\s*Copyright", line)), -1 + ) + end = next((i for i, line in enumerate(lines) if re.match(rf"{comment}\s*SPDX-", line)), -1) # here we just replace a bad license with the fixed one if start >= 0 and end >= 0: # filter out weird cases and make sure we mostly know what we're fixing if ( end < start or end - start > 6 - or not all(lines[i].startswith("#") for i in range(start, end)) + or not all(lines[i].startswith(comment) for i in range(start, end)) ): return [] if start < (license_lines - len(license_line_regexes)): # replace license where it is - lines[start : end + 1] = fixed_lines + lines[start : end + 1] = fixed else: # move license to beginning of file del lines[start : end + 1] start = 0 - while any(lines[start].startswith(s) for s in ("#!", "# -*-")): + while any(lines[start].startswith(s) for s in ("#!", f"{comment} -*-")): start += 1 - lines[start:start] = fixed_lines + lines[start:start] = fixed return lines # no license in the file yet, so we add it if start == -1 and end == -1: start = 0 - while any(lines[start].startswith(s) for s in ("#!", "# -*-")): + while any(lines[start].startswith(s) for s in ("#!", f"{comment} -*-")): start += 1 # add an empty line if needed - if not re.match(r"#\s*$", lines[start]): - lines[start:start] = "#" + if not re.match(rf"{comment}\s*$", lines[start]): + lines[start:start] = comment start += 1 lines[start:start] = fixed_lines diff --git a/lib/spack/spack/test/cmd/license.py b/lib/spack/spack/test/cmd/license.py index e9036e118c1..53c4af71370 100644 --- a/lib/spack/spack/test/cmd/license.py +++ b/lib/spack/spack/test/cmd/license.py @@ -91,6 +91,20 @@ def test_list_files(): GOOD_HEADER, False, ), + ( + "old_llnl.lp", + r"files not containing expected license:\s*1", + textwrap.dedent( + """\ + % Copyright 2013-2024 Lawrence Livermore National Security, LLC and other + % Spack Project Developers. See top-level COPYRIGHT file for details. + % + % SPDX-License-Identifier: (Apache-2.0 OR MIT) + """ + ), + GOOD_HEADER.replace("#", "%"), + False, + ), ("no_header.py", r"files without license in first 7 lines:\s*1", "", GOOD_HEADER, False), ( "test-script", @@ -141,6 +155,7 @@ def test_list_files(): False, ), ("good.py", "", GOOD_HEADER, GOOD_HEADER, True), + ("good.lp", "", GOOD_HEADER.replace("#", "%"), GOOD_HEADER.replace("#", "%"), True), ] @@ -185,6 +200,7 @@ def test_license_fix(self, filename, expected_txt, header, fixed_header, good, t return if fixed_header: + print("OUT", out) assert f"Fixed {str(source_file)}" in out assert license.returncode == 0