Skip to content

fix(mv): resolve self-reference removal when source path shape mismatches#7

Merged
StudentWeis merged 1 commit into
mainfrom
fix/6-mv-self-reference-relative-path
Apr 25, 2026
Merged

fix(mv): resolve self-reference removal when source path shape mismatches#7
StudentWeis merged 1 commit into
mainfrom
fix/6-mv-self-reference-relative-path

Conversation

@StudentWeis
Copy link
Copy Markdown
Owner

Summary

Fix mv failing with IO error reading '<./source>' when the source file contains a self-reference and the caller passes a bare relative source path alongside root=".". The move now succeeds and rewrites the self-reference, matching the behaviour users already get for canonical or ./-prefixed sources.

Linked Issue

Closes #6

Changes

  • src/core/mv.rs: add canonical_plan_key + find_matching_plan_key helpers and funnel every ReplacementPlan lookup (remove, contains_key, inequality checks) through them. The plan's stored keys keep their original textual shape so dry-run JSON output is unaffected.
  • tests/lib_mv_tests.rs: two regression tests that reproduce the bug from a TempDir cwd — one for the self-reference path (previously failed with IoRead), and one locking in the external-reference rewrite under the same bare-relative-source shape.

Testing

  • scripts/precheck.sh passes locally (cargo clippy: No issues found, cargo test: 274 passed, 1 ignored across 9 suites)
  • New regression tests cover both the self-reference and external-reference rewrite paths
  • Manual CLI repro on examples/main.md now succeeds where it previously failed

…ches

ReplacementPlan keys originated from three different path shapes (user
argument, WalkBuilder output, and canonicalized destinations) but were
compared by literal PathBuf equality. When a user passed a bare relative
source such as `examples/main.md` alongside `root="."`, WalkBuilder
produced `./examples/main.md`, so the self-reference entry could never
be removed; after `fs::rename` moved the source away, `apply_replacements`
then tried to read the stale pre-move path and failed with `IoRead`, with
rollback masking the effect.

Fix by funnelling plan-key lookups (`remove`, `contains_key`, inequality
checks) through `find_matching_plan_key`, which compares keys via
`canonical_plan_key` (`canonicalize` → `resolve_path` fallback). The plan's
stored keys keep their original textual form so dry-run JSON output is
unaffected.

Regression tests cover the bare-relative-source + self-reference and
external-reference scenarios.

Refs #6
@StudentWeis StudentWeis merged commit 1b868a5 into main Apr 25, 2026
8 checks passed
@StudentWeis StudentWeis deleted the fix/6-mv-self-reference-relative-path branch April 25, 2026 11:37
StudentWeis added a commit that referenced this pull request Apr 25, 2026
… prefix (#9)

collect_markdown_files now strips the leading './' that WalkBuilder produces
when root is '.', so every returned path matches the shape a user would type
on the command line.

With this normalisation in place the transient canonical_plan_key /
find_matching_plan_key workaround from #7 is redundant — all ReplacementPlan
key operations revert to plain HashMap lookups, honouring KISS.

The two regression tests from #6 continue to pass, confirming the source-level
fix is sufficient. A new test locks in the 'no ./ prefix' invariant.

Refs #8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(mv): mv fails when source has a self-reference and path shape differs from WalkBuilder output

1 participant