Skip to main content

kaizen/shell/
scope.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2//! Workspace scope helpers for repo-local vs machine-wide reads.
3
4use anyhow::Result;
5use std::path::{Path, PathBuf};
6
7/// How the active workspace was selected for a command invocation.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum ScopeOrigin {
10    /// Derived from the process current working directory.
11    Cwd,
12    /// Explicit `--workspace <path>` flag.
13    ExplicitWorkspace,
14    /// Explicit `--project <name>` flag, resolved to a path.
15    ExplicitProject(String),
16}
17
18pub fn resolve(workspace: Option<&Path>, all_workspaces: bool) -> Result<Vec<PathBuf>> {
19    let primary = crate::core::workspace::resolve(workspace)?;
20    if all_workspaces {
21        return crate::core::workspace::machine_workspaces(Some(&primary));
22    }
23    Ok(vec![primary])
24}
25
26pub fn label(roots: &[PathBuf]) -> String {
27    if roots.len() == 1 {
28        return roots[0].to_string_lossy().to_string();
29    }
30    format!("machine:{} workspaces", roots.len())
31}
32
33pub fn decorate_path(workspace: &Path, path: &str) -> String {
34    format!("{}:{}", workspace.to_string_lossy(), path)
35}
36
37/// Returns a scope annotation when the workspace selection might surprise the user.
38///
39/// Prints when an explicit flag was used, or when cwd maps to an unregistered path.
40pub fn scope_header(ws: &Path, origin: &ScopeOrigin) -> Option<String> {
41    match origin {
42        ScopeOrigin::ExplicitWorkspace | ScopeOrigin::ExplicitProject(_) => {
43            let name = ws.file_name().and_then(|n| n.to_str()).unwrap_or("?");
44            Some(format!("scope: {} ({})", name, ws.display()))
45        }
46        ScopeOrigin::Cwd => {
47            let registered = crate::core::machine_registry::list_paths()
48                .unwrap_or_default()
49                .into_iter()
50                .any(|p| p == ws);
51            if registered {
52                None
53            } else {
54                Some(format!("scope: {} ({})", ws.display(), "unregistered cwd"))
55            }
56        }
57    }
58}