diff --git a/gitignore_clean.py b/gitignore_clean.py new file mode 100644 index 0000000..100e830 --- /dev/null +++ b/gitignore_clean.py @@ -0,0 +1,80 @@ +#!/usr/bin/python3 + +from glob import glob +from os import remove as os_remove +from os.path import isdir as path_isdir, isfile as path_isfile, abspath, \ + basename +from pathlib import Path +from re import sub as re_sub +from shutil import rmtree + +DRY_RUN = False + +remove_comments = lambda s: re_sub(r"(? str: + with open(path, "r", encoding="utf-8-sig") as gitignore_file: + res = gitignore_file.read().splitlines() + return res + + +def delete(file_path: str) -> None: + is_dir = path_isdir(file_path) + is_file = path_isfile(file_path) + + if not (is_dir or is_file): + return + + display_file_path = abspath(file_path) + if DRY_RUN: + if is_dir: + print("Removing directory", display_file_path) + elif is_file: + print("Removing file", display_file_path) + + if DRY_RUN: + return + + if is_dir: + rmtree(file_path, ignore_errors=True) + elif is_file: + os_remove(file_path) + + +def extend_wildcards(patterns: list) -> list: + res = [] + for pattern in patterns: + processed_line = remove_comments(pattern).strip() + + if processed_line.startswith("!"): + exception_pattern = processed_line[1:] + exceptions = glob(exception_pattern, recursive=True) + res = [path for path in res if path not in exceptions] + else: + res.extend(glob(processed_line, recursive=True)) + + return res + + +def clean_gitignored_files(base_path: str = ".") -> None: + for gitignore_path in list(Path(base_path).rglob("*.gitignore")): + for file_path in extend_wildcards(read_gitignore(gitignore_path)): + delete(file_path) + + +if __name__ == "__main__": + from sys import argv + + if "-h" in argv or "--help" in argv: + print("Usage:", basename(argv[0]), "[options]") + print() + print("[ ]: Optional arguments") + print() + print("Options:") + print(" -h, --help: Display this help text") + print(" -d, --dry-run: Only list files") + else: + if (argc := len(argv)) == 2 and argv[1] in ["-d", "--dry-run"]: + DRY_RUN = True + clean_gitignored_files()