From ae0ecce6ffd25864d7c3a9051e2c6e842feaa413 Mon Sep 17 00:00:00 2001 From: seajee Date: Sat, 21 Dec 2024 13:25:57 +0100 Subject: [PATCH] Backup old dotman.py script --- dotman.py | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100755 dotman.py diff --git a/dotman.py b/dotman.py new file mode 100755 index 0000000..1b9830d --- /dev/null +++ b/dotman.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +import argparse +import difflib +import filecmp +import os +import shutil + +SOURCE_DIR = "./home/" +TARGET_DIR = os.environ["HOME"] + + +def list_files(path: str = ".") -> list[str]: + paths = [] + for root, dirs, files in os.walk(path): + for file in files: + paths.append(os.path.join(root, file)) + return paths + + +def map_colored(string: str) -> str: + if string.startswith("-"): + return f"\033[38;2;255;0;0m{string}\033[0m" # Red + elif string.startswith("+"): + return f"\033[38;2;0;255;0m{string}\033[0m" # Green + else: + return string + + +def print_diff(from_file: str, to_file: str) -> None: + with open(from_file, "r") as f1, open(to_file, "r") as f2: + diff = list(difflib.unified_diff( + f1.readlines(), + f2.readlines(), + fromfile=from_file, + tofile=to_file)) + colored_diff = list(map(map_colored, diff)) + + for line in diff[:2]: + print(line, end="") + + for line in colored_diff[2:]: + print(line, end="") + + +def copy_with_dirs(source: str, target: str) -> None: + os.makedirs(os.path.dirname(target), exist_ok=True) + shutil.copy(source, target) + + +def deploy(source_dir: str, target_dir: str) -> None: + source_files = list_files(source_dir) + target_files = list(map(lambda f: os.path.join( + target_dir, f[len(source_dir):]), source_files.copy())) + + deploy_map = {} + for i, source_file in enumerate(source_files): + deploy_map[source_file] = target_files[i] + + for source, target in deploy_map.items(): + if os.path.isfile(target): + if not filecmp.cmp(source, target): # TODO: Consider shallow=False + answer = input(target + " conflicts. Overwrite? [y/N] ") + if answer.lower().startswith("y"): + copy_with_dirs(source, target) + else: + copy_with_dirs(source, target) + + +def pull(source_dir: str, target_dir: str) -> None: + target_files = list_files(target_dir) + source_files = list(map(lambda f: os.path.join( + source_dir, f[len(target_dir):]), target_files.copy())) + + pull_map = {} + for i, source_file in enumerate(source_files): + pull_map[source_file] = target_files[i] + + for source, target in pull_map.items(): + try: + shutil.copy(source, target) + except FileNotFoundError: + pass + + +def diff(source_dir: str, target_dir: str) -> None: + target_files = list_files(target_dir) + source_files = list(map(lambda f: os.path.join( + source_dir, f[len(target_dir):]), target_files.copy())) + + file_map = {} + for i, file in enumerate(source_files): + file_map[file] = target_files[i] + + for source, target in file_map.items(): + print_diff(source, target) + + +def main(): + parser = argparse.ArgumentParser( + prog="dotman", + description="Dotfiles manager") + parser.add_argument("command", choices=["deploy", "pull", "diff"], + help="deploy or pull dotfiles") + + args = parser.parse_args() + + if args.command == "deploy": + deploy(SOURCE_DIR, TARGET_DIR) + elif args.command == "pull": + pull(TARGET_DIR, SOURCE_DIR) + elif args.command == "diff": + diff(TARGET_DIR, SOURCE_DIR) + + +if __name__ == "__main__": + main()