Skip to content

Commit b3d2bf6

Browse files
authored
Add: Improve UpdateHeader to remove old header lines, that are not required anymore (#912)
1 parent c32c192 commit b3d2bf6

File tree

3 files changed

+126
-8
lines changed

3 files changed

+126
-8
lines changed

pontos/updateheader/updateheader.py

+80-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2019-2022 Greenbone AG
1+
# SPDX-FileCopyrightText: 2019-2023 Greenbone AG
22
#
33
# SPDX-License-Identifier: GPL-3.0-or-later
44
#
@@ -26,7 +26,7 @@
2626
from datetime import datetime
2727
from pathlib import Path
2828
from subprocess import CalledProcessError, run
29-
from typing import Dict, List, Tuple, Union
29+
from typing import Dict, List, Optional, Tuple, Union
3030

3131
from pontos.terminal import Terminal
3232
from pontos.terminal.null import NullTerminal
@@ -53,6 +53,29 @@
5353
"GPL-2.0-or-later",
5454
"GPL-3.0-or-later",
5555
]
56+
OLD_LINES = [
57+
"# \-\*\- coding: utf\-8 \-\*\-",
58+
"This program is free software: you can redistribute it and/or modify",
59+
"it under the terms of the GNU Affero General Public License as",
60+
"published by the Free Software Foundation, either version 3 of the",
61+
"License, or \(at your option\) any later version.",
62+
"This program is free software; you can redistribute it and/or",
63+
"modify it under the terms of the GNU General Public License",
64+
"version 2 as published by the Free Software Foundation.",
65+
"This program is free software: you can redistribute it and/or modify",
66+
"it under the terms of the GNU General Public License as published by",
67+
"the Free Software Foundation, either version 3 of the License, or",
68+
"\(at your option\) any later version.",
69+
"This program is distributed in the hope that it will be useful,",
70+
"but WITHOUT ANY WARRANTY; without even the implied warranty of",
71+
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
72+
"GNU Affero General Public License for more details.",
73+
"GNU General Public License for more details.",
74+
"You should have received a copy of the GNU Affero General Public License",
75+
"along with this program. If not, see <http://www.gnu.org/licenses/>.",
76+
"along with this program; if not, write to the Free Software",
77+
"Foundation, Inc\., 51 Franklin St, Fifth Floor, Boston, MA 02110\-1301 USA\.", # noqa: E501
78+
]
5679

5780

5881
def _get_modified_year(f: Path) -> str:
@@ -112,11 +135,32 @@ def _add_header(
112135
raise ValueError
113136

114137

138+
def _remove_outdated(
139+
content: str, cleanup_regexes: List[re.Pattern]
140+
) -> Optional[str]:
141+
"""Remove lines that contain outdated copyright header ..."""
142+
changed = False
143+
splitted_lines = content.splitlines()
144+
i = 0
145+
for line in splitted_lines[:20]:
146+
for regex in cleanup_regexes:
147+
if regex.match(line):
148+
changed = True
149+
splitted_lines.pop(i)
150+
i = i - 1
151+
break
152+
i = i + 1
153+
if changed:
154+
return "\n".join(splitted_lines)
155+
return None
156+
157+
115158
def _update_file(
116159
file: Path,
117160
regex: re.Pattern,
118161
parsed_args: Namespace,
119162
term: Terminal,
163+
cleanup_regexes: Optional[List[re.Pattern]] = None,
120164
) -> int:
121165
"""Function to update the given file.
122166
Checks if header exists. If not it adds an
@@ -173,6 +217,15 @@ def _update_file(
173217
"is not existing."
174218
)
175219
return 1
220+
# old header existing - cleanup?
221+
if cleanup_regexes:
222+
old_content = file.read_text(encoding="utf-8")
223+
new_content = _remove_outdated(
224+
content=old_content, cleanup_regexes=cleanup_regexes
225+
)
226+
if new_content:
227+
file.write_text(new_content, encoding="utf-8")
228+
print(f"{file}: Cleaned up!")
176229
# replace found header and write it to file
177230
if copyright_match and (
178231
not copyright_match["modification_year"]
@@ -201,10 +254,9 @@ def _update_file(
201254
f"{parsed_args.year}"
202255
)
203256

204-
return 0
205257
else:
206258
print(f"{file}: License Header is ok.")
207-
return 0
259+
return 0
208260
except FileNotFoundError as e:
209261
print(f"{file}: File is not existing.")
210262
raise e
@@ -335,9 +387,24 @@ def _parse_args(args=None):
335387
type=FileType("r"),
336388
)
337389

390+
parser.add_argument(
391+
"--cleanup",
392+
action="store_true",
393+
default=False,
394+
help="Do a cleanup: Remove lines from outdated header format",
395+
)
396+
338397
return parser.parse_args(args)
339398

340399

400+
def _compile_outdated_regex() -> List[re.Pattern]:
401+
"""prepare regex patterns to remove old copyright lines"""
402+
regexes: List[re.Pattern] = []
403+
for line in OLD_LINES:
404+
regexes.append(re.compile(rf"^(([#*]|//) ?)?{line}"))
405+
return regexes
406+
407+
341408
def main() -> None:
342409
parsed_args = _parse_args()
343410
exclude_list = []
@@ -376,18 +443,25 @@ def main() -> None:
376443
term.error("Specify files to update!")
377444
sys.exit(1)
378445

379-
regex = re.compile(
446+
regex: re.Pattern = re.compile(
380447
"(SPDX-FileCopyrightText:|[Cc]opyright).*?(19[0-9]{2}|20[0-9]{2}) "
381448
f"?-? ?(19[0-9]{{2}}|20[0-9]{{2}})? ({parsed_args.company})"
382449
)
450+
cleanup_regexes: Optional[List[re.Pattern]] = None
451+
if parsed_args.cleanup:
452+
cleanup_regexes = _compile_outdated_regex()
383453

384454
for file in files:
385455
try:
386456
if file.absolute() in exclude_list:
387457
term.warning(f"{file}: Ignoring file from exclusion list.")
388458
else:
389459
_update_file(
390-
file=file, regex=regex, parsed_args=parsed_args, term=term
460+
file=file,
461+
regex=regex,
462+
parsed_args=parsed_args,
463+
term=term,
464+
cleanup_regexes=cleanup_regexes,
391465
)
392466
except (FileNotFoundError, UnicodeDecodeError, ValueError):
393467
continue

tests/updateheader/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2020-2022 Greenbone AG
1+
# SPDX-FileCopyrightText: 2020-2023 Greenbone AG
22
#
33
# SPDX-License-Identifier: GPL-3.0-or-later
44
#

tests/updateheader/test_header.py

+45-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2020-2022 Greenbone AG
1+
# SPDX-FileCopyrightText: 2020-2023 Greenbone AG
22
#
33
# SPDX-License-Identifier: GPL-3.0-or-later
44
#
@@ -28,6 +28,9 @@
2828

2929
from pontos.terminal.terminal import ConsoleTerminal
3030
from pontos.updateheader.updateheader import _add_header as add_header
31+
from pontos.updateheader.updateheader import (
32+
_compile_outdated_regex as compile_outdated_regex,
33+
)
3134
from pontos.updateheader.updateheader import _find_copyright as find_copyright
3235
from pontos.updateheader.updateheader import (
3336
_get_exclude_list as get_exclude_list,
@@ -36,6 +39,7 @@
3639
_get_modified_year as get_modified_year,
3740
)
3841
from pontos.updateheader.updateheader import _parse_args as parse_args
42+
from pontos.updateheader.updateheader import _remove_outdated as remove_outdated
3943
from pontos.updateheader.updateheader import _update_file as update_file
4044
from pontos.updateheader.updateheader import main
4145

@@ -467,6 +471,7 @@ def test_main(self, argparser_mock):
467471
self.args.verbose = 0
468472
self.args.log_file = None
469473
self.args.quiet = False
474+
self.args.cleanup = False
470475

471476
argparser_mock.return_value = self.args
472477

@@ -487,6 +492,7 @@ def test_main_never_happen(self, argparser_mock, mock_stdout):
487492
self.args.verbose = 0
488493
self.args.log_file = None
489494
self.args.quiet = False
495+
self.args.cleanup = False
490496

491497
argparser_mock.return_value = self.args
492498

@@ -499,3 +505,41 @@ def test_main_never_happen(self, argparser_mock, mock_stdout):
499505
"Specify files to update!",
500506
ret,
501507
)
508+
509+
def test_remove_outdated(self):
510+
test_content = """* This program is free software: you can redistribute it and/or modify
511+
*it under the terms of the GNU Affero General Public License as
512+
// published by the Free Software Foundation, either version 3 of the
513+
//License, or (at your option) any later version.
514+
# This program is distributed in the hope that it will be useful,
515+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
516+
# modify it under the terms of the GNU General Public License
517+
# This program is free software; you can redistribute it and/or
518+
# version 2 as published by the Free Software Foundation.
519+
This program is free software: you can redistribute it and/or modify""" # noqa: E501
520+
521+
compiled_regexes = compile_outdated_regex()
522+
523+
new_content = remove_outdated(
524+
content=test_content, cleanup_regexes=compiled_regexes
525+
)
526+
self.assertEqual(new_content, "")
527+
528+
def test_remove_outdated2(self):
529+
test_content = """the Free Software Foundation, either version 3 of the License, or
530+
(at your option) any later version.
531+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
532+
GNU Affero General Public License for more details.
533+
* GNU General Public License for more details.
534+
You should have received a copy of the GNU Affero General Public License
535+
along with this program. If not, see <http://www.gnu.org/licenses/>.
536+
# -*- coding: utf-8 -*-
537+
along with this program; if not, write to the Free Software
538+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.""" # noqa: E501
539+
540+
compiled_regexes = compile_outdated_regex()
541+
542+
new_content = remove_outdated(
543+
content=test_content, cleanup_regexes=compiled_regexes
544+
)
545+
self.assertEqual(new_content, "")

0 commit comments

Comments
 (0)