Add conflict policy options: Skip / Auto-number / Override
New ConflictPolicy enum in rename/ (Skip = original/default behavior,
AutoNumber = save as "Name (1).ext" counting up to the first free slot,
Override = replace the conflicting file outright), threaded through
execute_renames/rename_one alongside RenameAction. Override never deletes
a conflicting directory (falls back to Skip for that case); AutoNumber
sidesteps directories the same way by just trying the next number.
execute_rename now takes a conflict argument; undo/history are
deliberately NOT conflict-aware and always use their own fixed
skip-on-conflict policy regardless of what the original rename used.
Frontend: a second segmented selector in the rename confirmation modal
("On conflict: Skip / Auto-number / Override"), with Override styled in
red and its warning copy calling out that it can't be undone.
This commit is contained in:
@@ -9,14 +9,19 @@ native file/folder loading and drag-and-drop, local filename-based season/episod
|
||||
movie title/year* detection ("Match") is working, real online metadata lookups against
|
||||
TMDB ("Fetch Data") are working for both TV episodes and movies — including fuzzy
|
||||
title disambiguation, so a search that returns several similarly-named results doesn't
|
||||
just take TMDB's top-ranked hit — and the actual on-disk operation is wired up
|
||||
(skip-on-conflict, with a confirmation step showing the full old-path/new-path plan
|
||||
before anything touches disk, a per-row ✕ to drop an individual file from that plan at
|
||||
the last step, and a Move/Copy/Symlink selector for what to actually do at each
|
||||
target). It can also organize files into subfolders — including ones that don't exist
|
||||
yet — when the naming scheme includes a `/`. Every completed batch is logged to a
|
||||
history panel that can undo it (moving files back for Move, or just removing what was
|
||||
created for Copy/Symlink). A single loaded batch can freely mix TV episodes and movies
|
||||
just take TMDB's top-ranked hit — and the actual on-disk operation is wired up (with a
|
||||
confirmation step showing the full old-path/new-path plan before anything touches disk,
|
||||
a per-row ✕ to drop an individual file from that plan at the last step, a Move/Copy/
|
||||
Symlink selector for what to actually do at each target, and — independently — a Skip/
|
||||
Auto-number/Override selector for what happens when the computed name already exists:
|
||||
leave it alone (the original, and still default, behavior), save alongside it as
|
||||
"Name (1).ext", or replace it outright). It can also organize files into subfolders —
|
||||
including ones that don't exist yet — when the naming scheme includes a `/`. Every
|
||||
completed batch is logged to a history panel that can undo it (moving files back for
|
||||
Move, or just removing what was created for Copy/Symlink — undoing always uses its own
|
||||
skip-on-conflict policy regardless of what the original rename used, so an undo can
|
||||
never overwrite something else as a side effect). A single loaded batch can freely mix
|
||||
TV episodes and movies
|
||||
— each file only fills in the fields that apply to it. "Match" also parses release-tag
|
||||
text straight out of the filename — resolution, source (BluRay/HDTV/WEB-DL/…),
|
||||
video/audio codec, release group — so naming schemes can reference
|
||||
@@ -110,9 +115,10 @@ to the source file's parent directory, never as an absolute path, and every path
|
||||
component is validated (`validate_relative_target`) to reject empty segments (a
|
||||
leading, trailing, or doubled `/` — which also catches an absolute-looking
|
||||
`/etc/passwd`-style path), `.`/`..` segments, and backslashes (Renamr always uses `/`
|
||||
for the naming scheme's folder separator regardless of OS). Conflict policy is
|
||||
unchanged: if the resolved target already exists and isn't the same underlying file,
|
||||
that item is skipped rather than overwritten.
|
||||
for the naming scheme's folder separator regardless of OS). If the resolved target
|
||||
already exists and isn't the same underlying file, what happens next is up to the
|
||||
chosen conflict policy — Skip (default), Auto-number, or Override; see item 6 of the
|
||||
porting roadmap below for the full behavior of each.
|
||||
|
||||
## Project layout
|
||||
|
||||
@@ -127,8 +133,9 @@ crates/renamr-core/ Pure Rust core: naming-expression engine (ported), local
|
||||
search + episode lookup
|
||||
and movie search + lookup, both disambiguated via `similarity/`,
|
||||
tested against a mocked HTTP server via `mockito`), the on-disk
|
||||
rename engine (`rename/` — skip-on-conflict, Move/Copy/Symlink
|
||||
actions, can also organize into (auto-created) subfolders when
|
||||
rename engine (`rename/` — Move/Copy/Symlink actions,
|
||||
Skip/Auto-number/Override conflict policies, can also organize
|
||||
into (auto-created) subfolders when
|
||||
the naming scheme includes `/`) — and a rename history/undo log
|
||||
(`history/`, a partial `HistoryDialog` port, undo-aware of which
|
||||
action produced each batch). Not yet ported: full media metadata
|
||||
@@ -244,17 +251,22 @@ ported from, for anyone picking this up:
|
||||
6. **Rename engine + CLI** — `net.filebot.cli.CmdlineOperations` (1235 lines) and
|
||||
`ArgumentBean` (415 lines, the full flag surface: `-rename`, `--db`, `--format`,
|
||||
`--action`, `--conflict`, `-get-subtitles`, `-script`, etc.). The rename operation is
|
||||
done (`crates/renamr-core/src/rename`, fixed skip-on-conflict policy, wired to the
|
||||
UI's Rename button behind a confirmation step) including the `move`-into-subfolder
|
||||
`--action` variant — a naming scheme like `{n}/{s00e00}` organizes files into
|
||||
subfolders, creating any missing folders automatically, always scoped to the file's
|
||||
own directory tree. The `copy`/`symlink` `--action` variants are done too — an action
|
||||
selector in the confirmation modal picks Move/Copy/Symlink for the whole batch; Copy
|
||||
and Symlink both leave the source file untouched and produce a new file/link at the
|
||||
computed target, and both are undoable from the History panel the same as Move (undo
|
||||
for Copy/Symlink just removes what was created, since there's nothing to move back).
|
||||
Not yet done: the `--conflict` variants beyond skip (auto-number, override), and the
|
||||
CLI flag surface itself.
|
||||
done (`crates/renamr-core/src/rename`, wired to the UI's Rename button behind a
|
||||
confirmation step) including the `move`-into-subfolder `--action` variant — a naming
|
||||
scheme like `{n}/{s00e00}` organizes files into subfolders, creating any missing
|
||||
folders automatically, always scoped to the file's own directory tree. The
|
||||
`copy`/`symlink` `--action` variants are done too — an action selector in the
|
||||
confirmation modal picks Move/Copy/Symlink for the whole batch; Copy and Symlink both
|
||||
leave the source file untouched and produce a new file/link at the computed target,
|
||||
and both are undoable from the History panel the same as Move (undo for Copy/Symlink
|
||||
just removes what was created, since there's nothing to move back). The `--conflict`
|
||||
variants are done too — a second selector in the same modal picks Skip (default,
|
||||
leaves the conflicting file alone), Auto-number (`"Name (1).ext"`, counting up to the
|
||||
first free slot), or Override (replaces the conflicting file outright — the one
|
||||
irreversible option, called out with red styling in the UI; undoing that batch later
|
||||
restores the *source*, never what got overwritten, since undo always uses its own
|
||||
fixed skip-on-conflict policy no matter which policy the original rename used). Not
|
||||
yet done: the CLI flag surface itself.
|
||||
7. **The rest of the UI** — the Rename panel (file loading, drag-drop, live preview,
|
||||
local TV/movie matching, confirmed rename with per-item exclude, rename history/undo,
|
||||
Align Up/Down reordering, naming-scheme Presets with `1`-`9` hotkeys) is built; the
|
||||
|
||||
Reference in New Issue
Block a user