Skip to content

fix(locations): register watcher on location add, canonicalize paths#3043

Open
slvnlrt wants to merge 2 commits intospacedriveapp:mainfrom
slvnlrt:fix-location-watcher
Open

fix(locations): register watcher on location add, canonicalize paths#3043
slvnlrt wants to merge 2 commits intospacedriveapp:mainfrom
slvnlrt:fix-location-watcher

Conversation

@slvnlrt
Copy link
Contributor

@slvnlrt slvnlrt commented Mar 24, 2026

Summary

Locations added at runtime are never registered with the FsWatcherService. The watcher only discovers locations at startup via load_library_locations(). This means no filesystem events (creates, deletes, renames) are detected for any location added through the UI until the app is restarted.

Additionally, LocationManager::add_location() stores paths without canonicalization, so relative paths (from cwd-dependent contexts) break the watcher, volume manager, and indexer.

Changes

1. Register watcher on location add (locations/add/action.rs)

After LocationManager::add_location() succeeds, call fs_watcher.watch_location(meta) to start OS-level filesystem monitoring immediately. This mirrors what load_library_locations() does at startup.

  • Only registers local physical paths (remote/cloud skipped)
  • Graceful fallback if watcher not available (warns, doesn't fail)
  • Uses canonical path to match DB storage

2. Canonicalize paths before storing (location/manager.rs)

Call tokio::fs::canonicalize() on local physical paths before storing in DB.

  • Converts relative paths to absolute
  • Resolves symlinks and .. components
  • Strips \?\ UNC prefix on Windows (same pattern as volume/manager.rs)
  • Only for local device paths — remote paths pass through unchanged

Test plan

  • Add a location via the UI, then copy/delete/rename a file inside it — changes should appear in the UI immediately without restart
  • Verify the watcher log shows Watching location <id> at <path> after adding
  • macOS/Linux: verify no regression (location add + file operations)
  • Remote locations (if testable): verify no canonicalization attempted on remote paths

Related

Two upstream bugs fixed: 1. LocationManager::add_location() stored paths as-is without canonicalization. Relative paths (e.g. from cwd-dependent contexts) broke the watcher, volume manager, and indexer pipelines. Now calls tokio::fs::canonicalize() on local physical paths before storing, with UNC prefix stripping on Windows. 2. LocationAddAction::execute() never registered new locations with the FsWatcherService. The watcher only discovered locations at startup via load_library_locations(). Any location added at runtime had no filesystem monitoring — creates, deletes, and renames went undetected. Now calls fs_watcher.watch_location() after successful creation.
@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

Walkthrough

Adds async normalization of local physical SD paths (including Windows \?\ prefix stripping) when adding locations, and registers newly added locations with the filesystem watcher; watcher registration failures are logged and do not change the action result.

Changes

Cohort / File(s) Summary
Path canonicalization
core/src/location/manager.rs
When sd_path is a local physical path, asynchronously canonicalizes the filesystem path; converts canonicalization errors into LocationError::InvalidPath. On Windows, strips \\?\/\\?\UNC\... prefixes from canonicalized paths before constructing SdPath::Physical. Non-local sd_path values are unchanged.
Filesystem watcher registration
core/src/ops/locations/add/action.rs
After LocationManager::add_location(...) returns, attempts to derive a local path, canonicalizes it (falls back to original path on failure), applies Windows prefix normalization, builds LocationMeta (id, library_id, root_path, default rule toggles), and calls fs_watcher.watch_location(meta).await. Watcher errors are warned via tracing::warn! and do not affect the returned LocationAddOutput.

Sequence Diagram

sequenceDiagram actor User participant Action as LocationAddAction participant Manager as LocationManager participant FS as Filesystem participant Watcher as FileSystemWatcher User->>Action: execute(add location) Action->>Manager: add_location(sd_path) alt sd_path is local physical Manager->>FS: tokio::fs::canonicalize(path) FS-->>Manager: canonical_path / error opt canonical_path (Windows) Manager->>Manager: strip "\\?\" / "\\?\\UNC\\" prefixes end end Manager-->>Action: location_id opt action has local path Action->>FS: tokio::fs::canonicalize(local_path) FS-->>Action: canonical_path / error opt canonical_path (Windows) Action->>Action: strip "\\?\" / "\\?\\UNC\\" prefixes end Action->>Watcher: watch_location(LocationMeta{id, library_id, root_path, rule_toggles}) alt watch success Watcher-->>Action: ok else watch error Watcher-->>Action: error (logged, non-fatal) end end Action-->>User: LocationAddOutput 
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Paths hop through the canonical gate tonight,

Windows prefixes tucked out of sight,
Watchers awake to keep watch and cheer,
New roots arrive, tidy and clear,
I nibble bugs — all safe, all right.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes both main changes: path canonicalization and filesystem watcher registration upon location addition.
Description check ✅ Passed The pull request description is comprehensive and well-structured. It includes a clear summary of the problem, detailed explanation of changes in both files, a test plan with checkboxes, and relevant issue references.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@slvnlrt slvnlrt marked this pull request as ready for review March 24, 2026 16:38
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed. Inline comments: In `@core/src/location/manager.rs`: - Around line 61-71: The Windows UNC handling in the cfg(windows) block around the canonical variable must recognize the UNC form "\\?\UNC\server\share\..." and reconstruct it as a valid UNC path "\\server\share\..." before falling back to stripping a local-drive "\\?\" prefix; update the logic in the canonical normalization (the block that currently uses canonical.to_string_lossy() and strip_prefix(r"\\?\")) to first check strip_prefix(r"\\?\UNC\") and if present create a PathBuf from "\\" + stripped, otherwise strip r"\\?\" for local drives, else return canonical; mirror the approach used in core/src/volume/fs/refs.rs to ensure starts_with("\\\\") checks in classification.rs work correctly. In `@core/src/ops/locations/add/action.rs`: - Around line 108-126: The watcher is being registered with a canonicalized path that still may contain the Windows extended prefix, causing mismatches with the persisted path; update the block that builds root_path (inside the if let Some(local_path) ... and before creating LocationMeta and calling fs_watcher.watch_location) to apply the same Windows path normalization used by location_manager.add_location() — i.e., strip the Windows "\\?\" extended prefix (or otherwise normalize to the exact form saved to the DB) after tokio::fs::canonicalize returns and before constructing LocationMeta, so that LocationMeta.root_path matches the normalized DB path used by the persistent handler. 

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 386339bf-614c-4c9f-8672-fbf9d51dbaa0

📥 Commits

Reviewing files that changed from the base of the PR and between 4d87617 and 2e778e9.

📒 Files selected for processing (2)
  • core/src/location/manager.rs
  • core/src/ops/locations/add/action.rs
canonicalize() on Windows can produce \?\UNC\server\share\... for network paths. The previous strip_prefix(r"\?\") would produce UNC\server\share\... which is invalid. Now handles both forms: - \?\UNC\server\share\... → \server\share\... (network UNC) - \?\C:\... → C:\... (local drive) Applied in both manager.rs (add_location) and add/action.rs (watcher registration) to ensure consistency. Same normalization as volume/fs/refs.rs:contains_path(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant