Skip to content

Make file imports atomically non-overwriting #7

Description

@dremnik

Summary

The import path promises never to overwrite an existing file, but destination selection and copying are separate operations. Another process can create the selected destination between exists() and std::fs::copy, allowing the copy to overwrite it.

Evidence

  • src-tauri/src/workspace/import.rs:24-38 selects a name by polling Path::exists.
  • src-tauri/src/workspace/import.rs:18 subsequently calls std::fs::copy.
  • The workspace is intentionally shared with Finder and other applications, so concurrent creation is expected.

Proposed change

  1. Reserve the destination atomically with OpenOptions::create_new(true).
  2. Copy through the reserved handle rather than reopening the path.
  3. On collision, generate the next suffix and retry.
  4. Remove a partially copied destination on failure.
  5. Preserve source metadata only if the product specification requires it.

Acceptance criteria

  • Imports never truncate or overwrite an existing destination.
  • Concurrent imports of the same filename both complete with distinct names.
  • A failed copy leaves no partial destination.
  • Tests cover existing collisions, a simulated concurrent collision, and copy failure cleanup.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions