Skip to main content

callisto_cli/
workspace.rs

1use callisto_graph::infer::SeverityInference;
2use callisto_graph::locate::{find_workspace_root, IgnoreWalkLocator};
3use callisto_graph::resolver::ManifestWalkResolver;
4use callisto_graph::Workspace;
5
6use crate::cli::GlobalArgs;
7use crate::error::CliError;
8use crate::runner::CliCommandRunner;
9
10pub fn load_workspace<'a>(
11    global: &GlobalArgs,
12    runner: &'a CliCommandRunner,
13) -> Result<Workspace<'a, CliCommandRunner, ManifestWalkResolver>, CliError> {
14    let start = dunce::canonicalize(&global.cwd).map_err(|source| CliError::Io {
15        source,
16        path: Some(global.cwd.clone()),
17    })?;
18    let root = find_workspace_root(&start)?;
19    let locator = IgnoreWalkLocator::new(&root);
20    Ok(Workspace::load(root, &locator, runner)?)
21}
22
23/// Selects the concrete `SeverityInference` impl at compile time, milestone-gated by the
24/// `inference` Cargo feature (§17, §G.14): `NoInference` when the feature is off,
25/// `CommitInference` (a real git-backed adapter, §G.6.4) when it's on. `CommitInference`
26/// needs no workspace/runner context of its own -- `SeverityInference::infer` receives the
27/// caller's `GitAccess` per call -- so this needs no parameters and no lifetime.
28#[cfg(not(feature = "inference"))]
29pub fn select_inference() -> impl SeverityInference {
30    callisto_graph::infer::NoInference
31}
32
33#[cfg(feature = "inference")]
34pub fn select_inference() -> impl SeverityInference {
35    callisto_graph::infer::CommitInference
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn load_workspace_reports_io_error_for_a_nonexistent_cwd() {
44        let global = GlobalArgs {
45            format: crate::cli::OutputFormat::Text,
46            cwd: std::path::PathBuf::from("/nonexistent/definitely-not-a-real-path-abc123"),
47            dry_run: false,
48        };
49        let runner = CliCommandRunner;
50
51        match load_workspace(&global, &runner) {
52            Err(CliError::Io { path, .. }) => {
53                assert_eq!(path, Some(global.cwd.clone()));
54            }
55            Err(other) => panic!("expected CliError::Io, got a different CliError: {other:?}"),
56            Ok(_) => panic!("expected an error for a nonexistent cwd, got Ok"),
57        }
58    }
59}