import os import shutil import sys RED = "\033[1;31m" GREEN = "\033[1;32m" YELLOW = "\033[1;33m" CYAN = "\033[1;36m" RESET = "\033[0m" def log_info(msg): print(f"{CYAN}[*]{RESET} {msg}") def log_success(msg): print(f"{GREEN}[✓]{RESET} {msg}") def log_warn(msg): print(f"{YELLOW}[!]{RESET} {msg}") def log_error(msg): print(f"{RED}[✗]{RESET} {msg}") def ask_override(path): resp = input(f"{YELLOW}'{path}' already exists. Override? (Y/N): {RESET}").strip().lower() return resp == 'y' def choice_files(src_root, dst_root, choices_map, override_all=False): for final_name, options in choices_map.items(): existing_options = [ f for f in options if os.path.exists(os.path.join(src_root, f.lstrip('/'))) ] if not existing_options: log_warn(f"No source file found among options for {final_name}. Skipping.") continue if len(existing_options) == 1: chosen = existing_options[0] else: log_info(f"Choose which file to copy as '{final_name}':") for idx, opt in enumerate(existing_options, 1): print(f"{idx}: {opt}") while True: try: choice_idx = int(input(f"{CYAN}Enter number (1-{len(existing_options)}): {RESET}")) if 1 <= choice_idx <= len(existing_options): chosen = existing_options[choice_idx - 1] break except ValueError: pass log_warn("Invalid choice, try again.") src_file = os.path.join(src_root, chosen.lstrip('/')) dst_file = os.path.join(dst_root, final_name.lstrip('/')) if os.path.exists(dst_file): if not override_all and not ask_override(dst_file): log_warn(f"Skipped overriding {dst_file}") continue shutil.copy2(src_file, dst_file) log_success(f"Copied {chosen} -> {final_name}") def copy_with_structure(src_root, dst_root, override_all=False): for root, dirs, files in os.walk(src_root): rel_path = os.path.relpath(root, src_root) target_dir = os.path.join(dst_root, rel_path) if rel_path != '.' else dst_root os.makedirs(target_dir, exist_ok=True) for file in files: src_file = os.path.join(root, file) dst_file = os.path.join(target_dir, file) if os.path.exists(dst_file): if not override_all and not ask_override(dst_file): log_warn(f"Skipped overriding {dst_file}") continue shutil.copy2(src_file, dst_file) log_success(f"Copied: {src_file} -> {dst_file}") def require_root(): if os.geteuid() != 0: log_error("This script must be run as root (sudo). Exiting.") sys.exit(1)