diff --git a/src/caelestia/subcommands/install.py b/src/caelestia/subcommands/install.py index 036a526..de53607 100644 --- a/src/caelestia/subcommands/install.py +++ b/src/caelestia/subcommands/install.py @@ -38,7 +38,7 @@ class Command: self.create_backup() source, tip, manifest = self.fetch_manifest() - self.deploy_configs(source, manifest) + deployed = self.deploy_configs(source, manifest) helper, packages, local_packages = self.install_packages(source, manifest) self.run_hooks(manifest) @@ -48,6 +48,7 @@ class Command: enabled_components=manifest.enabled_components, packages=packages, local_packages=local_packages, + deployed_files=deployed, ).save() self.print_done() @@ -175,7 +176,7 @@ class Command: manifest.resolve_components(enable=enabled) return - def deploy_configs(self, source: DotsSource, manifest: Manifest) -> None: + def deploy_configs(self, source: DotsSource, manifest: Manifest) -> dict[str, str]: print() log("Installing configs...") deployer = Deployer() @@ -194,6 +195,8 @@ class Command: deployer.place(src, Path(dest)) info(f"{entry.src} -> {dest}") + return deployer.deployed_files + def install_packages(self, source: DotsSource, manifest: Manifest) -> tuple[str, list[str], dict[str, list[str]]]: installer = PackageInstaller.get(self.args.aur_helper, self.args.noconfirm) diff --git a/src/caelestia/utils/dots/deployer.py b/src/caelestia/utils/dots/deployer.py index e8f766b..12d80e8 100644 --- a/src/caelestia/utils/dots/deployer.py +++ b/src/caelestia/utils/dots/deployer.py @@ -2,10 +2,15 @@ import shutil import tempfile from pathlib import Path +from caelestia.utils.paths import dots_dir + class Deployer: """Places files from the dots clone into their destinations.""" + def __init__(self): + self.deployed_files: dict[str, str] = {} + def place(self, src: Path, dest: Path) -> None: """Place a whole entry (file or directory tree), replacing any existing dest.""" @@ -27,7 +32,7 @@ class Deployer: elif path.is_dir(): (dest / path.relative_to(src)).mkdir(parents=True, exist_ok=True) - def place_file(self, src: Path, dest: Path) -> None: + def place_file(self, src: Path, dest: Path, record: bool = True) -> None: """Atomically place a single file, replacing any existing dest.""" if dest.is_dir() and not dest.is_symlink(): @@ -44,11 +49,15 @@ class Deployer: Path(f.name).unlink() raise + if record: + # Keep relative to dots dir + self.deployed_files[str(dest)] = str(src.relative_to(dots_dir)) + def write_new(self, src: Path, dest: Path) -> Path: """Write the upstream version alongside dest as .new and return that path.""" new_path = dest.parent / f"{dest.name}.new" - self.place_file(src, new_path) + self.place_file(src, new_path, record=False) return new_path def remove(self, path: Path) -> None: diff --git a/src/caelestia/utils/dots/state.py b/src/caelestia/utils/dots/state.py index d47f3c9..8a9aabc 100644 --- a/src/caelestia/utils/dots/state.py +++ b/src/caelestia/utils/dots/state.py @@ -21,6 +21,10 @@ class DotsState: packages: list[str] = field(default_factory=list) local_packages: dict[str, list[str]] = field(default_factory=dict) + # Files placed by the last deploy. Only files, not directories + # Maps dest -> src + deployed_files: dict[str, str] = field(default_factory=dict) + @staticmethod def load() -> "DotsState": try: @@ -37,6 +41,7 @@ class DotsState: enabled_components=data.get("enabled_components", []), packages=data.get("packages", []), local_packages=data.get("local_packages", {}), + deployed_files=data.get("deployed_files", {}), ) def save(self) -> None: @@ -48,5 +53,6 @@ class DotsState: "enabled_components": self.enabled_components, "packages": self.packages, "local_packages": self.local_packages, + "deployed_files": self.deployed_files, }, )