Skip to content

Commit 8a80b45

Browse files
authored
refactor: extract _has_keep_config_marker helper and document empty-content choice
Assisted-by: GitHub Copilot (model: claude-sonnet-4.5, autonomous)
1 parent dece98d commit 8a80b45

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

src/specify_cli/extensions/__init__.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,18 @@ def _rescue_staging_dir(self, extension_id: str) -> Path:
760760
digest = hashlib.sha256(extension_id.encode("utf-8")).hexdigest()[:16]
761761
return self.extensions_dir / f".rescue-staging-{digest}"
762762

763+
@staticmethod
764+
def _has_keep_config_marker(directory: Path) -> bool:
765+
"""Return True when *directory* contains a valid ``.keep-config`` marker.
766+
767+
The marker is a regular (non-symlink) file written by
768+
``remove(..., keep_config=True)`` to record explicit provenance. Its
769+
content is intentionally empty — only presence matters, not content.
770+
The symlink guard prevents a crafted symlink from fooling the check.
771+
"""
772+
marker = directory / ".keep-config"
773+
return marker.is_file() and not marker.is_symlink()
774+
763775
@staticmethod
764776
def _collect_manifest_command_names(manifest: ExtensionManifest) -> Dict[str, str]:
765777
"""Collect command and alias names declared by a manifest.
@@ -1635,8 +1647,7 @@ def _recognized_config_names(
16351647
elif (
16361648
dest_dir.exists()
16371649
and not self.registry.is_installed(manifest.id)
1638-
and (dest_dir / ".keep-config").is_file()
1639-
and not (dest_dir / ".keep-config").is_symlink()
1650+
and self._has_keep_config_marker(dest_dir)
16401651
):
16411652
for cfg_file in (
16421653
list(dest_dir.glob("*-config.yml"))
@@ -2024,6 +2035,7 @@ def remove(self, extension_id: str, keep_config: bool = False) -> bool:
20242035
# distinguish this --keep-config leftover from a directory left
20252036
# by a partially-failed install (which must not have its
20262037
# packaged default configs treated as user-preserved data).
2038+
# Content is intentionally empty — only presence matters.
20272039
(extension_dir / ".keep-config").write_text("")
20282040
else:
20292041
# Backup config files before deleting

0 commit comments

Comments
 (0)