1use anyhow::Result;
5use std::path::{Path, PathBuf};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum ScopeOrigin {
10 Cwd,
12 ExplicitWorkspace,
14 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
37pub 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}