fix(moves): organize moves into a subfolder of the source no longer fail as overlapping#761
Draft
kevinheneveld wants to merge 1 commit into
Draft
Conversation
…scend moves)
Naming templates that append subfolders (narrator, edition) produce
moves like '.../Elevation' -> '.../Elevation/Stephen King': a target
inside its own source. The copy-walk mover can't do that shape — it
would recurse into its own output, then the source cleanup would delete
the result — so the overlap guard rejected the whole class ('Source and
target paths overlap'). A live library hit this on 97 consecutive
organize jobs.
Such moves now run as two same-volume atomic renames: rename the source
aside (same parent), recreate the vacated path, rename into place —
with best-effort rollback on failure. The inverse shape (flattening a
folder up into its populated ancestor) stays blocked. Logic lives in a
MoveJobProcessor.DescendMove partial to respect the 500-line rule; the
processor gains only the branch points.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Naming templates that append subfolders (narrator, edition, …) make organize request moves like:
— a target inside its own source. The copy-walk mover can't execute that shape (the recursive copy would descend into its own output, and the post-copy
Directory.Delete(source, true)would delete the result), so the overlap guard failed the whole class with "Source and target paths overlap".On my live library this hit 97 consecutive organize jobs — every book whose folder didn't yet contain the template's narrator subfolder.
The fix
Descend-shaped moves don't need to copy anything: two same-volume atomic renames do it safely —
Elevation→Elevation.moving-<jobId>mkdir ElevationElevation.moving-<jobId>→Elevation/Stephen Kingwith best-effort rollback if step 2/3 fails (the recreated skeleton is empty by construction, so it's dropped and the aside-rename is reversed). The inverse shape — flattening a folder up into its populated ancestor — stays blocked exactly as before.
Implementation notes:
MoveJobProcessor.DescendMovepartial; the processor itself gains only the branch points (it was 1 line under the 500-line architecture rule).Testing
ProcessJobAsyncdirectly: the descend shape completes with files physically renamed into the child folder and aMovedhistory entry; the upward-overlap shape still fails with the original error and leaves files untouched.Heads-up: #717 also works in the moves area — happy to rebase this on top of it if that lands first; the footprint here is deliberately small.
🤖 Generated with Claude Code