fix(editor): stop a save racing a rename from recreating the old file

Merged
GN
2d ago
+223-40

Summary

  • A save could race a rename or move of its file. When the write reached the host after the rename, it recreated the file at the old path, next to the renamed copy. The user then had two copies, and the saved edits were in the wrong one. The race went both ways. A save already in flight could finish after the rename. An autosave or Ctrl+S during the rename could write to the old path. Desktop writeTextFile and the web server's unchecked write both create a missing file. On web, a checked write fails as an external conflict instead.
  • A rename now waits for the saves already in flight to the open files it moves. A save requested during the rename waits for it to finish, then saves at the new path. The editor store owns this through the same per-path save lock it already uses, so the fix covers the desktop and web filesystem adapters the same way.

Related Issue

Closes #1310

Item 1 of the issue landed in #1326. This PR fixes item 2, the in-flight save race that #1326 deferred.

Type of Change

  • fix: bug fix
  • test: adds or updates tests

What Changed

  • renameBetweenSaves in src/renderer/stores/editor-store.ts runs a rename after the saves in flight to the moved files finish. It holds new saves to those files until the rename ends. saveFile sends a held save to the file's new path.
  • renamePathWithOpenEditors in src/renderer/lib/editor-tab-rename.ts replaces moveOpenEditorTabs. It renames on disk and moves open tabs inside that hold. Explorer rename, mobile explorer rename and cut-and-paste all call it.
  • Two tests in file-explorer-store.paste-move.test.ts cover a save in flight before a move and a save requested during a move.

How It Was Tested

  • bun run typecheck
  • Manual verification completed
  • Not applicable

The new tests fail on origin/dev (2 failed, 4 passed). Both end with two files on disk, /project/lib/a.ts with on disk and /project/src/a.ts with saved edit. With the fix, they end with one file, /project/lib/a.ts with saved edit. The explorer, mobile explorer, file-explorer store and editor-store save and rename suites pass (17 files, 434 tests). Biome reports no issues on the changed files.

Screenshots or Recordings

Not a visual change.

CI & Review Gate

  • All CI checks pass (PR Validation, Rust Checks, Build Verification, Security Scans)
  • Code review comments from CodeRabbit / Claude have been addressed or resolved
  • No unresolved review findings remain

Checklist

  • My PR title follows the conventional commit format used by this repo
  • I linked the related issue or explained why none exists
  • I updated docs when needed
  • I added or updated tests when needed
  • I verified the change does not introduce unrelated modifications
  • I read AGENTS.md and followed the contributor guidelines
  • A human reviewed the complete diff before submission

Summary by cubic

Fixes a race where a save could recreate a file at its old path after a rename or move, leaving the user with two copies and the saved edits in the wrong one.

A rename now waits for in-flight saves at or under the path it moves, and saves requested during the rename wait for it to finish before writing at the new path. Open tabs are moved inside the same hold, so files opened while the rename runs also end up at the new path. The fix lives in the editor store's existing save lock, so it covers desktop and web. Closes #1310.