diff --git a/crates/fff-core/src/file_picker.rs b/crates/fff-core/src/file_picker.rs index 0d6a6d624..d25158cf9 100644 --- a/crates/fff-core/src/file_picker.rs +++ b/crates/fff-core/src/file_picker.rs @@ -894,9 +894,8 @@ impl FilePicker { error!("Refusing to index filesystem root: {}", path.display()); return Err(Error::FilesystemRoot(path)); } - if !options.enable_home_dir_scanning - && Some(path.as_os_str()) == dirs::home_dir().as_ref().map(|p| p.as_os_str()) - { + // Path equality compares components, so "~/" (as git root discovery returns it) matches too. + if !options.enable_home_dir_scanning && dirs::home_dir().is_some_and(|home| path == home) { error!("Refusing to index home directory: {}", path.display()); return Err(Error::FilesystemRoot(path)); } @@ -2474,6 +2473,23 @@ pub(crate) fn hint_allocator_collect() { mod tests { use super::*; + #[test] + fn refuses_home_dir_with_trailing_separator() { + let Some(home) = dirs::home_dir() else { return }; + for base in [home.clone(), home.join("")] { + let result = FilePicker::new(FilePickerOptions { + base_path: base.to_string_lossy().into_owned(), + watch: false, + ..Default::default() + }); + assert!( + matches!(result, Err(Error::FilesystemRoot(_))), + "home dir accepted as {}", + base.display() + ); + } + } + /// The watcher must watch every ancestor directory up to `base_path`, /// not just the immediate parents of indexed files. The dir table is /// built from the walker's visited dirs, so pure ancestors (dirs that