Skip to content

Commit

Permalink
Enable updating existing multi-year license headers with single_year
Browse files Browse the repository at this point in the history
  • Loading branch information
llugin authored and greenbonebot committed Aug 13, 2024
1 parent b7a3bd0 commit 3f37803
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 34 deletions.
4 changes: 2 additions & 2 deletions pontos/updateheader/_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ def parse_args(args: Optional[Sequence[str]] = None) -> Namespace:
action="store_true",
default=False,
help=(
"If set, will not update license with from-to years format "
"(YYYY-YYYY) if it has single (only creation) year format (YYYY). "
"If set, will format license headers in from-to year format "
"into single (creation) year format. "
"Default is %(default)s."
),
)
Expand Down
86 changes: 55 additions & 31 deletions pontos/updateheader/updateheader.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
Also it appends a header if it is missing in the file.
"""

import io
import re
import sys
from dataclasses import dataclass
Expand Down Expand Up @@ -208,39 +209,43 @@ def update_file(
return

# replace found header and write it to file
if copyright_match and (
not copyright_match.modification_year
and copyright_match.creation_year < year
or copyright_match.modification_year
and copyright_match.modification_year < year
):
if copyright_match:

# use different target license formats depending on provided single_year argument
if single_year:
# In case of single year updating the license with modification date doesn't make sense.
# Changing the existing license header with created-modified years to single year is not supported.
return
copyright_term = (
f"SPDX-FileCopyrightText: "
f"{copyright_match.creation_year}"
f"-{year} {company}"
)
new_line = re.sub(copyright_regex, copyright_term, line)
fp_write = fp.tell() - len(line) # save position to insert
rest_of_file = fp.read()
fp.seek(fp_write)
fp.write(new_line)
fp.write(rest_of_file)
# in some cases we replace "YYYY - YYYY" with "YYYY-YYYY"
# resulting in 2 characters left at the end of the file
# so we truncate the file, just in case!
fp.truncate()
print(
f"{file}: Changed License Header Copyright Year "
f"{copyright_match.modification_year} -> "
f"{year}"
)
copyright_term = (
f"SPDX-FileCopyrightText: "
f"{copyright_match.creation_year} "
f"{company}"
)
else:
copyright_term = (
f"SPDX-FileCopyrightText: "
f"{copyright_match.creation_year}"
f"-{year} {company}"
)

with_multi_year = copyright_match.creation_year and copyright_match.modification_year
with_single_year_outdated = not copyright_match.modification_year and copyright_match.creation_year < year
with_multi_year_outdated = with_multi_year and copyright_match.modification_year < year

if single_year and with_multi_year:
_substitute_license_text(fp, line, copyright_regex, copyright_term)
print(
f"{file}: Changed License Header Copyright Year format to single year "
f"{copyright_match.creation_year}-{year} -> "
f"{copyright_match.creation_year}"
)
elif not single_year and (with_multi_year_outdated or with_single_year_outdated):
_substitute_license_text(fp, line, copyright_regex, copyright_term)
print(
f"{file}: Changed License Header Copyright Year "
f"{copyright_match.modification_year} -> "
f"{year}"
)
else:
print(f"{file}: License Header is ok.")

else:
print(f"{file}: License Header is ok.")
except FileNotFoundError as e:
print(f"{file}: File is not existing.")
raise e
Expand All @@ -258,6 +263,25 @@ def update_file(
print(f"{file}: Cleaned up!")


def _substitute_license_text(
fp: io.TextIOWrapper,
line: str,
copyright_regex: re.Pattern,
copyright_term: str,
) -> None:
"""Substitute the old license text in file fp, starting on provided line, with the new one provided in copyright_term"""
new_line = re.sub(copyright_regex, copyright_term, line)
fp_write = fp.tell() - len(line) # save position to insert
rest_of_file = fp.read()
fp.seek(fp_write)
fp.write(new_line)
fp.write(rest_of_file)
# in some cases we replace "YYYY - YYYY" with "YYYY-YYYY"
# resulting in 2 characters left at the end of the file
# so we truncate the file, just in case!
fp.truncate()


def _get_exclude_list(
exclude_file: Path, directories: list[Path]
) -> list[Path]:
Expand Down
9 changes: 8 additions & 1 deletion tests/updateheader/test_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def test_update_header_in_file_single_year(self, mock_stdout):
year = "2021"
license_id = "AGPL-3.0-or-later"

header = HEADER.format(date="2020")
header = HEADER.format(date="2020-2021")
with temp_file(
content=header, name="test.py", change_into=True
) as test_file:
Expand All @@ -355,6 +355,13 @@ def test_update_header_in_file_single_year(self, mock_stdout):
single_year=True,
)

ret = mock_stdout.getvalue()
self.assertEqual(
ret,
f"{test_file}: Changed License Header Copyright Year format to single year "
"2020-2021 -> 2020\n",
)

self.assertIn(
"# SPDX-FileCopyrightText: 2020 Greenbone AG",
test_file.read_text(encoding="utf-8"),
Expand Down

0 comments on commit 3f37803

Please sign in to comment.