From 0410fed68c4ff845250d0a3b7598f62ac8908f71 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Wed, 17 Jun 2026 23:17:08 +1000 Subject: [PATCH] fix: remove untracked files from state --- src/caelestia/subcommands/update.py | 2 +- src/caelestia/utils/dots/diff.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/caelestia/subcommands/update.py b/src/caelestia/subcommands/update.py index ad01a3b..1daea7d 100644 --- a/src/caelestia/subcommands/update.py +++ b/src/caelestia/subcommands/update.py @@ -44,7 +44,7 @@ class Command: # Persist file changes immediately so a later failure can't lose track of them deployed = dict(state.deployed_files) - for dest in (*changeset.deletes, *changeset.stale): + for dest in (*changeset.deletes, *changeset.stale, *changeset.untracked): deployed.pop(str(dest), None) deployed.update(placed) state.deployed_files = deployed diff --git a/src/caelestia/utils/dots/diff.py b/src/caelestia/utils/dots/diff.py index b93d763..bc0a4ac 100644 --- a/src/caelestia/utils/dots/diff.py +++ b/src/caelestia/utils/dots/diff.py @@ -17,6 +17,7 @@ class Changeset: deletes: list[Path] = field(default_factory=list) # We placed it, upstream removed it, unmodified stale: list[Path] = field(default_factory=list) # Upstream removed it but user modified it deleted_changed: list[tuple[str, Path]] = field(default_factory=list) # User deleted it, upstream changed -> .new + untracked: list[Path] = field(default_factory=list) # Gone + no longer managed; drop from state def is_empty(self) -> bool: return not (self.place or self.conflicts or self.deletes or self.stale or self.deleted_changed) @@ -44,6 +45,7 @@ class Changeset: deletes: list[Path] = [] stale: list[Path] = [] deleted_changed: list[tuple[str, Path]] = [] + untracked: list[Path] = [] # Collect all files to deploy (entry sources can be dirs so we recurse into them) to_deploy: dict[Path, str] = {} @@ -70,6 +72,8 @@ class Changeset: try: if dest_path not in files_to_deploy: # No longer managed by any entry if not dest_path.exists(): + # Gone from disk and no entry manages it + untracked.append(dest_path) continue if has_base and try_read(applied_rev, src) == dest_path.read_bytes(): @@ -117,5 +121,10 @@ class Changeset: conflicts.append((src, dest)) return Changeset( - place=place, conflicts=conflicts, deletes=deletes, stale=stale, deleted_changed=deleted_changed + place=place, + conflicts=conflicts, + deletes=deletes, + stale=stale, + deleted_changed=deleted_changed, + untracked=untracked, )