from ..paths import get_templates_path from ..cli import CLI import shutil import os def find_template_conflicts(dest_dir: str) -> list[str]: templates_path = get_templates_path() / "project" if not os.path.exists(templates_path): raise RuntimeError(f"Project template path does not exist: {templates_path}") conflicts = [] for root, _, files in os.walk(templates_path): rel = os.path.relpath(root, templates_path) target_root = os.path.join(dest_dir, rel) if rel != "." else dest_dir for file in files: target_file = os.path.join(target_root, file) if os.path.exists(target_file): conflicts.append(target_file) return conflicts def copy_template_files(dest_dir: str, force: bool = False, checked: bool = False) -> None: templates_path = get_templates_path() / "project" if not os.path.exists(templates_path): raise RuntimeError(f"Project template path does not exist: {templates_path}") os.makedirs(dest_dir, exist_ok=True) if not checked: conflicts = find_template_conflicts(dest_dir) if conflicts and not force: raise FileExistsError( "Refusing to overwrite existing files:\n" + "\n".join(conflicts) ) shutil.copytree( templates_path, dest_dir, dirs_exist_ok=True ) def main(args, flags) -> int: dest_dir = args[0] force = flags["force"] conflicts = find_template_conflicts(dest_dir) if conflicts and not force: print("Some files already exist that would be overwritten:") for file in conflicts: print(f" {file}") print("Use --force to overwrite existing files.") return 1 copy_template_files(dest_dir, force=force, checked=True) return 0 def setup(cli: CLI): cli.command( "init", help="Create an empty chipnut workspace or reinitialize with --force", description=( "Initialize a chipnut development workspace by creating a Nutfile and default project files. " "If a Nutfile already exists, initialization should fail unless --force is used." ), ).flag( "force", "f", help="Reinitialize even when a Nutfile already exists", ).arg( "path", nargs="?", default=".", help="Directory to initialize (default: current directory)", ).handle(main)