mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
fix(integrations): don't abort uninstall when the manifest can't be deleted (#3805)
`IntegrationManifest.uninstall()` guards every tracked-file `path.unlink()` with `except OSError: skipped.append(path)`, but the manifest's own `manifest.unlink()` is bare. The manifest is deleted *last*, so an undeletable manifest (read-only file, a directory left at the path, a Windows lock) raises after the tracked files are already gone. The caller loses the `(removed, skipped)` result and never runs its post-uninstall bookkeeping — reassigning the default integration, rewriting/removing `integration.json`, clearing init options — leaving a removed integration still recorded as installed. Report it in `skipped` like any other file we could not remove, mirroring the `path.unlink()` guard above and the same `except OSError: skipped.append(...)` pattern in kimi's legacy-directory cleanup. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -400,7 +400,19 @@ class IntegrationManifest:
|
||||
# Remove the manifest file itself
|
||||
manifest = root / ".specify" / "integrations" / f"{self.key}.manifest.json"
|
||||
if remove_manifest and manifest.exists():
|
||||
manifest.unlink()
|
||||
try:
|
||||
manifest.unlink()
|
||||
except OSError:
|
||||
# An undeletable manifest (read-only file, a directory left at
|
||||
# the path, a Windows lock) must not abort the uninstall after
|
||||
# the tracked files were already removed: the caller would lose
|
||||
# the (removed, skipped) result and never run its post-uninstall
|
||||
# bookkeeping. Report it like any other file we could not
|
||||
# remove, mirroring the path.unlink() guard above. The
|
||||
# empty-parent cleanup below is left unconditional: with the
|
||||
# manifest still on disk its parent is non-empty, so the first
|
||||
# rmdir() raises and breaks immediately.
|
||||
skipped.append(manifest)
|
||||
parent = manifest.parent
|
||||
while parent != root:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user