Add clear script environment cache command (PEP 723 PR 13/16) - #1724
Conversation
|
🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR. |
Rich Chiodo (rchiodo)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
8fb0a8b to
edb3281
Compare
| } | ||
|
|
||
| function getResolvedPythonProjectSettings( | ||
| workspaceFolder: WorkspaceFolder, |
There was a problem hiding this comment.
Info · Optional note
Workspace-name and relative-path resolution is duplicated between these helpers, creating a maintainability risk if project-setting identity rules evolve. Consolidate this behind one canonical resolver.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3cb82ae9-7424-40a4-9156-8c54ac6e0895
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3cb82ae9-7424-40a4-9156-8c54ac6e0895
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3cb82ae9-7424-40a4-9156-8c54ac6e0895
Coordinate per-entry deletion locks, keep partial failures consistent, and clean inline project settings safely. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
Claim exact stale or retained lock markers before inline cache cleanup. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
Handle user-scope project cleanup independently of open workspace folders. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 6b12d843-8011-4bfc-9ba9-f75761eadee2
4826e87
826fdd8 to
4826e87
Compare
Heejae Chang (heejaechang)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
fa47921
into
microsoft:main
Eleanor Boyd (eleanorjboyd)
left a comment
There was a problem hiding this comment.
Post-merge review: three concurrency/project-model findings from the clear-cache implementation.
| return undefined; | ||
| } | ||
| if ( | ||
| normalizePath(currentPhysicalCacheRootPath) !== normalizePath(originalPhysicalCacheRootPath) |
There was a problem hiding this comment.
High — guard against same-path cache-root replacement\n\nThis revalidation compares only canonical path strings. If another process removes and recreates the cache root at the same pathname after the initial enumeration, the comparison still succeeds, and cleanup can lock and delete an entry from the replacement root generation. Path containment protects where deletion happens, but not which filesystem generation owns that path. Please coordinate cleanup and creation with a root-generation lock/identity token and revalidate that identity immediately before recursive deletion.
| `.reclaim-${process.pid}-${crypto.randomBytes(16).toString('hex')}-${snapshot.marker}`, | ||
| ); | ||
| try { | ||
| await fsapi.rename(path.join(lockPath, snapshot.marker), claimedMarker); |
There was a problem hiding this comment.
Medium — make interrupted reclaim markers recoverable\n\nAfter this rename, a crash—or an error during the following unlink/rmdir—can leave .reclaim-* behind. inspectFileLockSnapshot() treats that name as unknown, so every later inspection reports malformed and the cache entry can no longer be reclaimed automatically. Please either model reclaim markers as a recognized generation with PID/liveness recovery, or restore the original observed marker when reclamation does not complete.
| existingSettings.some((projectSetting) => matchesProjectSettingEdit(projectSetting, edit, workspaceFolder)) && | ||
| !hasProjectSetting(remainingSettings, edit.project, workspaceFolder), | ||
| ).forEach((edit) => { | ||
| removedProjects.set(edit.project.uri.toString(), edit.project); |
There was a problem hiding this comment.
Medium — do not remove an intrinsic workspace-root project\n\nAn inline-script override such as { path: ".", envManager: "ms-python.python:inline-script" } resolves to the workspace root. Once the override is removed, this code adds that URI to removedProjects; the command then calls wm.remove(), even though workspace roots are intrinsic projects created independently of settings. This temporarily drops the workspace root from the in-memory project model until a later refresh. Please exclude workspace-folder roots from loadedProjectsToRemove (or recompute removal from the effective project set after edits).
Roadmap context
This is PR 13 of 16 in the PEP 723 inline-script roadmap. It adds the explicit, user-confirmed cache lifecycle operation that the later TTL work will reuse.
get/set+ Memento)Why this PR
The extension can create extension-owned inline-script environments and persist script associations, but it has no complete way to remove that state. Clearing only the files would leave Memento associations and
pythonProjectsentries pointing at deleted interpreters; clearing only settings would leave disk usage behind.This PR adds one coordinated lifecycle operation covering:
Because this is destructive and the cache is shared by extension-host processes, the implementation is intentionally fail-closed around path ownership and locks.
What this PR does
Adds an internal, confirmation-gated clear command
python-envs.clearScriptEnvCacheonly while the hidden inline-script feature flag is enabled.package.jsonor the Command Palette before rollout.Keeps generic cache clearing behavior safe
python-envs.clearCachecommand continues to clear existing non-inline managers.Serializes in-process maintenance
create(),get(), andset()cannot observe or mutate half-cleared state.Coordinates deletion across extension hosts
retainedmarkers remain recognizable but are conservatively not reclaimed.Validates every destructive path
Before deleting an entry, cleanup verifies that:
script-envs-v1are normal directories rather than symlinks/junctions;realpathcontainment matches the expected ownership boundary;The entry lock is acquired first, then root and entry ownership are revalidated immediately before removal.
Keeps state consistent through partial failures
onDidChangeEnvironmentonly for selections actually invalidated.Removes generated inline project settings safely
pythonProjectsentries independently from global, workspace, and workspace-folder sources.Cleanup semantics
Example
Tests
Coverage includes:
Validation on the rebased branch:
npm run compile-testsnpm run compilenpm run lintThe full Windows unit run reaches 1638 passing and 5 pending; the existing concurrent
writeMetaJsonrename test can still intermittently fail withEPERMon Windows. That writer is unchanged by this PR and the same failure is reproducible onmain.Performance
User impact
No default-path user impact. The manager and command remain behind the undeclared, default-off
python-envs.inlineScripts.enabledflag, and the command is not publicly contributed.When the internal flag is manually enabled, the existing generic cache command still behaves as before for non-inline managers. Inline cleanup is available only through the dedicated confirmed lifecycle.
Scope and follow-up
This PR intentionally does not implement:
PR 14 will reuse this safety and state-cleanup foundation to remove entries whose
lastUsedAtexceeds the planned 14-day TTL.