Skip to content

Only prune stored profiles this manager loaded or saved - #139

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/prune-only-deleted-profiles-124
Sep 27, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/prune-only-deleted-profiles-124

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #124

What was wrong

Since the #106 fix, KeybindingManager.SaveAsync deleted every stored profile that wasn't in memory. On a manager that never called InitializeAsync, that was every profile on disk. In the three-manager scenario from the issue, saving from manager B permanently deleted default and vim.

Change

KeybindingManager now records the ids of the stored profiles it has seen: the ones InitializeAsync loaded and the ones SaveAsync wrote. SaveAsync deletes only ids from that set that are no longer in memory, then updates the set.

  • Profiles on disk that this manager never loaded or saved are left alone.
  • Deleting a profile that was loaded, or saved earlier by the same manager, still persists. This keeps the Deleted profiles come back after SaveAsync + restart, because deletion is never persisted #106 behaviour and its existing test.
  • IProfileManager is unchanged. Tracking calls to DeleteProfile directly would have meant adding an interface member, because callers delete through manager.Profiles, which is an injected IProfileManager. Tracking the ids the manager has seen gives the same result without that change.
  • A Lock guards the set. Lock comes from Polyfill on net8, and the library builds for net8.0, net9.0 and net10.0.

Tests

SaveWithoutInitializeTests covers:

  • the three-manager regression from the issue
  • deleting a profile that was created and saved by the same uninitialized manager
  • deleting a profile and then recreating it

With the fix reverted, the regression test fails: the reload shows only other, not default,other,vim. Full suite: 105/105 pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X65VbCUfvG15D4o8afrvpk


Generated by Claude Code

SaveAsync treated every stored profile missing from memory as deleted, so
a manager that never called InitializeAsync deleted every profile on disk
when it saved. The manager now records the ids of the profiles it loaded
or saved, and SaveAsync deletes only those that are no longer in memory.
Profiles it never saw are left alone, and deleting a loaded or previously
saved profile still sticks as #106 requires.

Fixes #124

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X65VbCUfvG15D4o8afrvpk
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SaveAsync on a manager that never called InitializeAsync deletes every stored profile

1 participant