summary refs log tree commit diff
path: root/maintainers/scripts/remove-old-aliases.py
diff options
context:
space:
mode:
Diffstat (limited to 'maintainers/scripts/remove-old-aliases.py')
-rwxr-xr-xmaintainers/scripts/remove-old-aliases.py202
1 files changed, 202 insertions, 0 deletions
diff --git a/maintainers/scripts/remove-old-aliases.py b/maintainers/scripts/remove-old-aliases.py
new file mode 100755
index 00000000000..5d9398feaa2
--- /dev/null
+++ b/maintainers/scripts/remove-old-aliases.py
@@ -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()