use std::path::PathBuf;
#[derive(Debug)]
pub(super) struct ColocatedDiscovery {
pub id: String,
pub root_path: PathBuf,
}
pub(super) fn scan_one_root(root: &std::path::Path) -> Vec<ColocatedDiscovery> {
use crate::service::fs_discovery::{scan_roots_for_colocated_indexes, DEFAULT_SCAN_DEPTH};
match std::fs::metadata(root) {
Ok(_) => {}
Err(e) => {
let kind = e.kind();
if kind == std::io::ErrorKind::PermissionDenied {
tracing::error!(
"warm-boot: PERMISSION DENIED accessing root {} during colocated scan: {e}. \
Under launchd, this is typically a TCC denial on an external or protected \
volume. Grant Full Disk Access to the launchd agent in \
System Settings → Privacy & Security → Full Disk Access. (issue #718)",
root.display()
);
} else if kind == std::io::ErrorKind::NotFound {
tracing::debug!(
"warm-boot: root {} not found — skipping colocated scan",
root.display()
);
} else {
tracing::warn!(
"warm-boot: cannot access root {} for colocated scan: {e} — skipping",
root.display()
);
}
return Vec::new();
}
}
let entries = scan_roots_for_colocated_indexes(
std::slice::from_ref(&root.to_path_buf()),
DEFAULT_SCAN_DEPTH,
);
entries
.into_iter()
.map(|e| ColocatedDiscovery {
id: e.id,
root_path: e.root_path,
})
.collect()
}
pub(super) fn is_likely_external_volume(path: &std::path::Path) -> bool {
if path.starts_with("/Volumes") {
return true;
}
if let Ok(canonical) = std::fs::canonicalize(path) {
if canonical.starts_with("/Volumes") {
return true;
}
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_likely_external_volume_detection() {
assert!(
is_likely_external_volume(std::path::Path::new("/Volumes/SSD1/Projects")),
"/Volumes/ prefix must be detected as external"
);
assert!(
is_likely_external_volume(std::path::Path::new("/Volumes")),
"/Volumes itself must be detected as external"
);
assert!(
!is_likely_external_volume(std::path::Path::new(
"/Library/Application Support/trusty-search"
)),
"/Library/... must not be detected as external"
);
assert!(
!is_likely_external_volume(std::path::Path::new(
"/private/tmp/trusty-718-test-not-external"
)),
"/private/tmp/... must not be detected as external"
);
}
#[test]
fn scan_one_root_nonexistent_returns_empty() {
let nonexistent = std::path::Path::new("/tmp/trusty-718-definitely-not-here-xyz9999");
let result = scan_one_root(nonexistent);
assert!(
result.is_empty(),
"nonexistent root must produce no discoveries; got: {result:?}"
);
}
#[test]
fn scan_one_root_finds_colocated_index() {
let tmp = tempfile::tempdir().unwrap();
let root = tmp.path();
let ts_dir = root.join(".trusty-search");
std::fs::create_dir_all(&ts_dir).unwrap();
let results = scan_one_root(root);
assert_eq!(
results.len(),
1,
"one .trusty-search dir must yield one discovery; got: {results:?}"
);
let canonical_root = root.canonicalize().unwrap();
assert_eq!(
results[0].root_path, canonical_root,
"root_path must be the canonical parent of .trusty-search"
);
}
}