diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..896e790 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Output bundles +dotfiles-*.tar.gz diff --git a/manager b/manager index 937b3be..8744b98 100755 --- a/manager +++ b/manager @@ -1,12 +1,70 @@ #!/usr/bin/env python3 import tomllib -from pathlib import Path import shutil +import tarfile +import tempfile +from datetime import datetime +from pathlib import Path from enum import Enum CONFIG_FILE = Path(__file__).parent / "config.toml" +def create_tool_bundle(bundle_name, entries): + """ + Create a tar.gz bundle for a single tool. + `entries` should be a list of entries for that tool only. + """ + tempdir = Path(tempfile.mkdtemp(prefix="dotfile_manager")) + + bundle_dir = Path(f"{tempdir}/dotfiles-{bundle_name}") + bundle_dir.mkdir() + + # Create extract.sh + extract_script = bundle_dir / "extract.sh" + with extract_script.open("w") as f: + f.write("#!/bin/sh\n") + f.write("set -e\n\n") + f.write("# Extract dotfiles for {}\n".format(bundle_name)) + + for entry in entries: + src = Path(entry["repo_path"]).name + dest = entry["system_path"].replace("$HOME", str(Path.home())) + backup = f"{dest}.old" + + f.write(f"echo 'Installing {entry['repo_path']} -> {dest}'\n") + f.write(f"if [ -e '{dest}' ]; then\n") + f.write(f" mv '{dest}' '{backup}'\n") + f.write("fi\n") + if entry["type"] == "dir": + f.write(f"cp -r '{src}' '{dest}'\n") + else: + f.write(f"mkdir -p $(dirname '{dest}')\n") + f.write(f"cp '{src}' '{dest}'\n") + f.write("\n") + + extract_script.chmod(0o755) + + # Copy files into bundle_dir + for entry in entries: + src_path = Path(entry["repo_path"]) + dest_path = bundle_dir / src_path.name + if src_path.is_dir(): + shutil.copytree(src_path, dest_path) + else: + dest_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(src_path, dest_path) + + # Create tar.gz + tar_path = Path(f"dotfiles-{bundle_name}.tar.gz") + with tarfile.open(tar_path, "w:gz") as tar: + tar.add(bundle_dir, arcname=bundle_dir.name) + + # Cleanup temp directory + shutil.rmtree(bundle_dir) + + print(f"Bundle created: {tar_path}") + class ToolType(str, Enum): FILE = "file" @@ -148,7 +206,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description="Manage dotfiles from TOML config") parser.add_argument( "action", - choices=["install", "store", "restore", "clean"], + choices=["install", "store", "restore", "clean", "bundle"], help="Action to perform" ) parser.add_argument( @@ -170,3 +228,5 @@ if __name__ == "__main__": restore(entries) elif args.action == "clean": clean(entries) + elif args.action == "bundle": + create_tool_bundle(datetime.now().strftime("%Y-%m-%d-%H-%M"), entries)