usage './maintainers/scripts/remove-old-aliases.py --year 2018 --file ./pkgs/top-level/aliases.nix' first the matched lines are converted to throws with the comment 'Converted to throw $CURRENT_DATE' then the throws older than the passed date are removed.main
parent
2be13a1e8b
commit
0db4ecb8af
@ -0,0 +1,202 @@ |
||||
#!/usr/bin/env nix-shell |
||||
#!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ ])" nix |
||||
""" |
||||
A program to remove old aliases or convert old aliases to throws |
||||
Example usage: |
||||
./maintainers/scripts/remove-old-aliases.py --year 2018 --file ./pkgs/top-level/aliases.nix |
||||
|
||||
Check this file with mypy after every change! |
||||
$ mypy --strict maintainers/scripts/remove-old-aliases.py |
||||
""" |
||||
import argparse |
||||
import shutil |
||||
import subprocess |
||||
from datetime import date as datetimedate |
||||
from datetime import datetime |
||||
from pathlib import Path |
||||
|
||||
|
||||
def process_args() -> argparse.Namespace: |
||||
"""process args""" |
||||
arg_parser = argparse.ArgumentParser() |
||||
arg_parser.add_argument( |
||||
"--year", required=True, type=int, help="operate on aliases older than $year" |
||||
) |
||||
arg_parser.add_argument( |
||||
"--month", |
||||
type=int, |
||||
default=1, |
||||
help="operate on aliases older than $year-$month", |
||||
) |
||||
arg_parser.add_argument("--file", required=True, type=Path, help="alias file") |
||||
arg_parser.add_argument( |
||||
"--dry-run", action="store_true", help="don't modify files, only print results" |
||||
) |
||||
return arg_parser.parse_args() |
||||
|
||||
|
||||
def get_date_lists( |
||||
txt: list[str], cutoffdate: datetimedate |
||||
) -> tuple[list[str], list[str], list[str]]: |
||||
"""get a list of lines in which the date is older than $cutoffdate""" |
||||
date_older_list: list[str] = [] |
||||
date_older_throw_list: list[str] = [] |
||||
date_sep_line_list: list[str] = [] |
||||
|
||||
for lineno, line in enumerate(txt, start=1): |
||||
line = line.rstrip() |
||||
my_date = None |
||||
for string in line.split(): |
||||
string = string.strip(":") |
||||
try: |
||||
# strip ':' incase there is a string like 2019-11-01: |
||||
my_date = datetime.strptime(string, "%Y-%m-%d").date() |
||||
except ValueError: |
||||
try: |
||||
my_date = datetime.strptime(string, "%Y-%m").date() |
||||
except ValueError: |
||||
continue |
||||
|
||||
if my_date is None or my_date > cutoffdate: |
||||
continue |
||||
|
||||
if "=" not in line: |
||||
date_sep_line_list.append(f"{lineno} {line}") |
||||
# 'if' lines could be complicated |
||||
elif "if " in line and "if =" not in line: |
||||
print(f"RESOLVE MANUALLY {line}") |
||||
elif "throw" in line: |
||||
date_older_throw_list.append(line) |
||||
else: |
||||
date_older_list.append(line) |
||||
|
||||
return ( |
||||
date_older_list, |
||||
date_sep_line_list, |
||||
date_older_throw_list, |
||||
) |
||||
|
||||
|
||||
def convert_to_throw(date_older_list: list[str]) -> list[tuple[str, str]]: |
||||
"""convert a list of lines to throws""" |
||||
converted_list = [] |
||||
for line in date_older_list.copy(): |
||||
indent: str = " " * (len(line) - len(line.lstrip())) |
||||
before_equal = "" |
||||
after_equal = "" |
||||
try: |
||||
before_equal, after_equal = (x.strip() for x in line.split("=", maxsplit=2)) |
||||
except ValueError as err: |
||||
print(err, line, "\n") |
||||
date_older_list.remove(line) |
||||
continue |
||||
|
||||
alias = before_equal.strip() |
||||
after_equal_list = [x.strip(";:") for x in after_equal.split()] |
||||
|
||||
converted = ( |
||||
f"{indent}{alias} = throw \"'{alias}' has been renamed to/replaced by" |
||||
f" '{after_equal_list.pop(0)}'\";" |
||||
f' # Converted to throw {datetime.today().strftime("%Y-%m-%d")}' |
||||
) |
||||
converted_list.append((line, converted)) |
||||
|
||||
return converted_list |
||||
|
||||
|
||||
def generate_text_to_write( |
||||
txt: list[str], |
||||
date_older_list: list[str], |
||||
converted_to_throw: list[tuple[str, str]], |
||||
date_older_throw_list: list[str], |
||||
) -> list[str]: |
||||
"""generate a list of text to be written to the aliasfile""" |
||||
text_to_write: list[str] = [] |
||||
for line in txt: |
||||
text_to_append: str = "" |
||||
if converted_to_throw: |
||||
for tupl in converted_to_throw: |
||||
if line == tupl[0]: |
||||
text_to_append = f"{tupl[1]}\n" |
||||
if line not in date_older_list and line not in date_older_throw_list: |
||||
text_to_append = f"{line}\n" |
||||
if text_to_append: |
||||
text_to_write.append(text_to_append) |
||||
|
||||
return text_to_write |
||||
|
||||
|
||||
def write_file( |
||||
aliasfile: Path, |
||||
text_to_write: list[str], |
||||
) -> None: |
||||
"""write file""" |
||||
temp_aliasfile = Path(f"{aliasfile}.raliases") |
||||
with open(temp_aliasfile, "w", encoding="utf-8") as far: |
||||
for line in text_to_write: |
||||
far.write(line) |
||||
print("\nChecking the syntax of the new aliasfile") |
||||
try: |
||||
subprocess.run( |
||||
["nix-instantiate", "--eval", temp_aliasfile], |
||||
check=True, |
||||
stdout=subprocess.DEVNULL, |
||||
) |
||||
except subprocess.CalledProcessError: |
||||
print( |
||||
"\nSyntax check failed,", |
||||
"there may have been a line which only has\n" |
||||
'aliasname = "reason why";\n' |
||||
"when it should have been\n" |
||||
'aliasname = throw "reason why";', |
||||
) |
||||
temp_aliasfile.unlink() |
||||
return |
||||
shutil.move(f"{aliasfile}.raliases", aliasfile) |
||||
print(f"{aliasfile} modified! please verify with 'git diff'.") |
||||
|
||||
|
||||
def main() -> None: |
||||
"""main""" |
||||
args = process_args() |
||||
|
||||
aliasfile = Path(args.file).absolute() |
||||
cutoffdate = (datetime.strptime(f"{args.year}-{args.month}-01", "%Y-%m-%d")).date() |
||||
|
||||
txt: list[str] = (aliasfile.read_text(encoding="utf-8")).splitlines() |
||||
|
||||
date_older_list: list[str] = [] |
||||
date_sep_line_list: list[str] = [] |
||||
date_older_throw_list: list[str] = [] |
||||
|
||||
date_older_list, date_sep_line_list, date_older_throw_list = get_date_lists( |
||||
txt, cutoffdate |
||||
) |
||||
|
||||
converted_to_throw: list[tuple[str, str]] = [] |
||||
converted_to_throw = convert_to_throw(date_older_list) |
||||
|
||||
if date_older_list: |
||||
print(" Will be converted to throws. ".center(100, "-")) |
||||
for l_n in date_older_list: |
||||
print(l_n) |
||||
|
||||
if date_older_throw_list: |
||||
print(" Will be removed. ".center(100, "-")) |
||||
for l_n in date_older_throw_list: |
||||
print(l_n) |
||||
|
||||
if date_sep_line_list: |
||||
print(" On separate line, resolve manually. ".center(100, "-")) |
||||
for l_n in date_sep_line_list: |
||||
print(l_n) |
||||
|
||||
if not args.dry_run: |
||||
text_to_write = generate_text_to_write( |
||||
txt, date_older_list, converted_to_throw, date_older_throw_list |
||||
) |
||||
write_file(aliasfile, text_to_write) |
||||
|
||||
|
||||
if __name__ == "__main__": |
||||
main() |
Loading…
Reference in new issue