1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Shared "what index are we operating on?" helpers used by the project-scoped
//! CLI subcommands (`search`, `watch`, `add`, `remove`, `reindex`).
//!
//! Why: every project subcommand needs the same precedence rules: an explicit
//! `--index` flag wins, otherwise auto-detect from CWD; and the same user-facing
//! warning when we fall back to the bare directory name. Centralising removes
//! duplication and shrinks `main.rs`.
//! What: two thin helpers wrapping `crate::detect`.
//! Test: covered indirectly by `cargo run -- search foo` (explicit index path)
//! and `cargo run -- search foo` from inside this repo (auto-detect path).
use crate::detect::{detect_project, DetectionMethod};
use colored::Colorize;
/// Resolve the effective index ID: explicit `--index` flag wins, otherwise
/// auto-detect from CWD via `detect_project`.
///
/// Why: every project-scoped command needs the same precedence rules.
/// What: returns `(index_id, warned)` where `warned` is true when we fell back
/// to the CWD basename and should print a warning.
/// Test: With explicit Some("foo") → returns ("foo", false). With None inside
/// this repo → returns ("trusty-search", false) (detected via .git).
pub fn resolve_index(explicit: &Option<String>) -> (String, bool) {
if let Some(id) = explicit {
return (id.clone(), false);
}
let cwd = std::env::current_dir().unwrap_or_default();
let ctx = detect_project(&cwd);
let warned = matches!(ctx.detection_method, DetectionMethod::Fallback);
(ctx.index_id, warned)
}
/// Why: Make fallback detection visible so users know to run `init`.
/// What: Prints a one-line yellow warning to stderr if `warned` is true.
/// Test: Call with warned=true and capture stderr → contains "⚠".
pub fn print_index_header(index_id: &str, warned: bool) {
if warned {
eprintln!(
"{} No .git or .trusty-search found — using directory name '{}'. \
Run `trusty-search init` to register this project.",
"⚠".yellow(),
index_id
);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_index_explicit_wins() {
let explicit = Some("my-explicit-index".to_string());
let (id, warned) = resolve_index(&explicit);
assert_eq!(id, "my-explicit-index");
assert!(!warned, "explicit --index should never warn");
}
#[test]
fn resolve_index_explicit_empty_string_still_wins() {
// Even an empty string is preferred over auto-detect: callers are
// responsible for trimming/validating.
let explicit = Some(String::new());
let (id, warned) = resolve_index(&explicit);
assert_eq!(id, "");
assert!(!warned);
}
#[test]
fn resolve_index_none_falls_through_to_detection() {
// We can't assert the exact id (depends on CWD when test runs) but we
// can assert the contract: returns a non-empty index_id, doesn't panic.
let (id, _warned) = resolve_index(&None);
assert!(
!id.is_empty(),
"auto-detected index_id should never be empty"
);
}
#[test]
fn print_index_header_warned_false_is_silent() {
// When warned=false the function MUST NOT panic and should return cleanly.
// (stderr capture varies by test runner; we just smoke-test the call.)
print_index_header("any-id", false);
}
#[test]
fn print_index_header_warned_true_does_not_panic() {
// Smoke-test the warned branch — it formats a colored eprintln.
print_index_header("fallback-id", true);
}
}