fix: vault rename data integrity, manual order persistence, name validation#55
Merged
Merged
Conversation
Obsidian emits a single rename event for the folder itself when a folder is renamed or moved, not for each child file. The previous handler only updated tree-expansion and selection state, leaving the file index with stale child records and the manual order with stale paths that the next manual-mode render would prune — silently losing the user's sort for the entire moved folder. Add FileIndex.renameFolder to rewrite every record at or under the old path to its new location (path + parentPath), and rewrite matching manualOrder entries via the existing renameNestedPath helper. Added tests covering nested files, record-count preservation, no-op, and shared-name-prefix guards.
Three data-safety improvements bundled (same file): 1. onClose now flushes a pending manual-order save instead of just clearing the debounce timer. Previously a reorder followed by quickly closing the leaf within the 500ms window dropped the save, losing the user's most recent sort on next load. 2. The create handler no longer appends new files to manualOrder inline. That append contradicted initializeManualOrder's reconcile, which places missing files at their seed-sorted position — so ordering depended on whether files were created before or after the last manual session. Reconcile now owns new-file placement consistently. 3. Inline create/rename rejects names containing '/', '\', or '..'. A typed or pasted name with path separators previously created files at unintended nested locations or escaped the target folder.
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.
Pre-release hardening found during a code audit. Four data-integrity fixes; no user-facing behavior changes beyond closing these gaps.
1. Folder rename/move lost child records and manual order (data loss)
Obsidian fires a single
renameevent for the folder itself when a folder is renamed or moved — not one per child file. The old handler only updated tree-expansion/selection state, so:manualOrderentries under the old path became stale and were pruned on the next manual-mode render, silently discarding the user's sort for the whole moved folder.Fix:
FileIndex.renameFolder()rewrites every record at or under the old path (path + parentPath); matchingmanualOrderentries are rewritten via the existingrenameNestedPathhelper. Added 4 tests (nested files, count preservation, no-op, shared-name-prefix guard).2. Pending manual-order save dropped on close
scheduleSaveOrderdebounces the save by 500ms, butonCloseonly cleared the timer — it never flushed. Reordering then closing the leaf within 500ms lost the change on next load.Fix:
onCloseflushes the pending save synchronously before the view is torn down.3. Inconsistent new-file placement in manual order
The
createhandler appended new files tomanualOrderinline, which contradictedinitializeManualOrder's reconcile (which places missing files at their seed-sorted position). The resulting order depended on whether files were created before or after the last manual session.Fix: removed the inline append; reconcile now owns new-file placement consistently with its design.
4. Names with path separators /
..created files at unintended locationsInline create/rename only stripped leading/trailing slashes, so a name like
a/b/corfoo/../barsilently created deeply nested paths or escaped the target folder.Fix: reject names containing
/,\, or..with aNotice.Verification
npm run build✅npm run lint✅npm test— 116 tests / 18 suites ✅ (added 4FileIndex.renameFoldertests)Known follow-ups (not in this PR, low frequency)
These are pre-existing and rare; safe to address separately.