Backup old dotman.py script
This commit is contained in:
117
dotman.py
Executable file
117
dotman.py
Executable file
@@ -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()
|
||||
Reference in New Issue
Block a user