From b3e5c57f24d37c6aad981a3e7772ae9f08e1baa0 Mon Sep 17 00:00:00 2001 From: gustav-fff <286169375+gustav-fff@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:17:51 -0700 Subject: [PATCH] fix(core): emit compile_error for --no-default-features (#659) `fff-search` supports two mutually exclusive backend features (`ripgrep` default, or `zlob`) but internal cfg gates keyed off `cfg(not(feature = "zlob"))`, meaning the ripgrep code compiled even when the `ripgrep` feature (and its `ignore`/`globset` deps) was off. Building with `--no-default-features` produced a wall of "unresolved crate" errors. Tighten the gates to `all(not(feature = "zlob"), feature = "ripgrep")` and add a top-level `compile_error!` when neither backend is enabled, so the failure is a single actionable message instead of 15 cascading errors. Refs #659 --- crates/fff-core/src/constraints.rs | 8 ++++---- crates/fff-core/src/ignore.rs | 2 +- crates/fff-core/src/lib.rs | 6 ++++++ crates/fff-core/src/walk/mod.rs | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/fff-core/src/constraints.rs b/crates/fff-core/src/constraints.rs index 68ac06d1..6a11abe4 100644 --- a/crates/fff-core/src/constraints.rs +++ b/crates/fff-core/src/constraints.rs @@ -169,7 +169,7 @@ pub(crate) fn apply_constraints<'a, T: Constrainable + Sync>( #[cfg(feature = "zlob")] type GlobPattern = zlob::ZlobPattern; -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] type GlobPattern = globset::GlobMatcher; /// How `Constraint::Glob` is evaluated for each item. @@ -440,7 +440,7 @@ fn compiled_matches(p: &GlobPattern, path: &str) -> bool { } #[inline] -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] fn compiled_matches(p: &GlobPattern, path: &str) -> bool { p.is_match(path) } @@ -553,7 +553,7 @@ fn compile_one(pattern: &str) -> Option { zlob::ZlobPattern::compile(pattern, zlob::ZlobFlags::RECOMMENDED).ok() } -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] fn compile_one(pattern: &str) -> Option { globset::Glob::new(pattern) .ok() @@ -577,7 +577,7 @@ fn match_glob_pattern(pattern: &str, paths: &[&str]) -> Vec { mask } -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] fn match_glob_pattern(pattern: &str, paths: &[&str]) -> Vec { let mut mask = vec![false; paths.len()]; let Ok(glob) = globset::Glob::new(pattern) else { diff --git a/crates/fff-core/src/ignore.rs b/crates/fff-core/src/ignore.rs index 961e0085..ac29f523 100644 --- a/crates/fff-core/src/ignore.rs +++ b/crates/fff-core/src/ignore.rs @@ -39,7 +39,7 @@ pub(crate) const IGNORED_DIRS: &[&str] = &[ "AppData/Roaming", ]; -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] pub(crate) fn non_git_repo_overrides(base_path: &Path) -> Option { use ignore::overrides::OverrideBuilder; diff --git a/crates/fff-core/src/lib.rs b/crates/fff-core/src/lib.rs index b4e390a5..e9a78dba 100644 --- a/crates/fff-core/src/lib.rs +++ b/crates/fff-core/src/lib.rs @@ -94,6 +94,12 @@ //! # Ok::<(), Box>(()) //! ``` +#[cfg(not(any(feature = "ripgrep", feature = "zlob")))] +compile_error!( + "fff-search requires either the `ripgrep` (default) or `zlob` feature. \ + Enable one, e.g. `--features ripgrep` or `--features zlob`." +); + mod background_watcher; mod git_status_worker; pub(crate) mod parallelism; diff --git a/crates/fff-core/src/walk/mod.rs b/crates/fff-core/src/walk/mod.rs index 2c2768fe..a533f0bb 100644 --- a/crates/fff-core/src/walk/mod.rs +++ b/crates/fff-core/src/walk/mod.rs @@ -13,9 +13,9 @@ mod zlob; #[cfg(feature = "zlob")] pub(crate) use zlob::walk_collect_files; -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] mod ripgrep; -#[cfg(not(feature = "zlob"))] +#[cfg(all(not(feature = "zlob"), feature = "ripgrep"))] pub(crate) use ripgrep::walk_collect_files; pub(crate) struct WalkOutput {