Finish file operations: copy, batch rename, duplicate detection #45

Merged
parkerhdavis merged 1 commit from file-ops-copy-batch-dup into main 2026-06-01 16:07:05 -06:00
parkerhdavis commented 2026-06-01 16:06:58 -06:00 (Migrated from github.com)

Completes the File operations roadmap item (Phase 1) — the remaining pieces on top of the existing rename/move/trash.

Copy

  • copy_asset command + Copy to… in the asset context menu (single and multi-select). The original is untouched; if the copy lands inside a library root the watcher indexes it. Undo trashes the copy by path via a new trash_file command.

Batch rename

  • Multi-select → Rename N items… opens a dialog with a token pattern and a live old→new preview. Tokens mirror the Automations Rename step: {name}, {ext}, {index} (default {name}.{ext}). Confirm is gated until the batch is collision-free.
  • Backed by a collision-safe rename_assets command: two-phase temp renames on disk and in the DB, so cyclic a↔b swaps and {index} renumbers don't trip the UNIQUE(root_id, relative_path) constraint. Two new Rust tests cover the swap and the rejected-collision cases.

Duplicate detection

  • find_duplicates groups byte-identical assets by content_hash (already stamped at index time, so no extra hashing pass), ordered by reclaimable space.
  • New dedicated Duplicates view: sidebar Library → Tools → Duplicates and Ctrl+K → "Duplicates". Each group shows copies × size each + total reclaimable; per-copy open / open-folder / trash, with a one-shot Undo for the last trash.

Also

  • Multi-select context menu gains Copy N / Trash N so selecting many stays coherent.

Verification

  • cargo check + clippy clean; 130 backend tests pass (incl. 2 new batch-rename tests)
  • tsc + biome clean
  • Boots cleanly via make dev
Completes the **File operations** roadmap item (Phase 1) — the remaining pieces on top of the existing rename/move/trash. ## Copy - `copy_asset` command + **Copy to…** in the asset context menu (single and multi-select). The original is untouched; if the copy lands inside a library root the watcher indexes it. Undo trashes the copy by path via a new `trash_file` command. ## Batch rename - Multi-select → **Rename N items…** opens a dialog with a token pattern and a **live old→new preview**. Tokens mirror the Automations Rename step: `{name}`, `{ext}`, `{index}` (default `{name}.{ext}`). Confirm is gated until the batch is collision-free. - Backed by a collision-safe `rename_assets` command: two-phase temp renames on disk **and** in the DB, so cyclic `a↔b` swaps and `{index}` renumbers don't trip the `UNIQUE(root_id, relative_path)` constraint. Two new Rust tests cover the swap and the rejected-collision cases. ## Duplicate detection - `find_duplicates` groups byte-identical assets by `content_hash` (already stamped at index time, so no extra hashing pass), ordered by reclaimable space. - New dedicated **Duplicates** view: sidebar **Library → Tools → Duplicates** and `Ctrl+K → "Duplicates"`. Each group shows copies × size each + total reclaimable; per-copy open / open-folder / trash, with a one-shot Undo for the last trash. ## Also - Multi-select context menu gains **Copy N** / **Trash N** so selecting many stays coherent. ## Verification - `cargo check` + `clippy` clean; **130 backend tests pass** (incl. 2 new batch-rename tests) - `tsc` + biome clean - Boots cleanly via `make dev`
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
parker/garnet!45
No description provided.