Skip to main content

git_same/commands/
workspace.rs

1//! Workspace management command handler.
2
3use crate::cli::{WorkspaceArgs, WorkspaceCommand};
4use crate::config::{Config, WorkspaceManager};
5use crate::errors::Result;
6use crate::output::Output;
7
8/// Run the workspace command.
9pub fn run(args: &WorkspaceArgs, config: &Config, output: &Output) -> Result<()> {
10    match &args.command {
11        WorkspaceCommand::List => list(config, output),
12        WorkspaceCommand::Default(default_args) => {
13            if default_args.clear {
14                clear_default(output)
15            } else if let Some(ref selector) = default_args.name {
16                set_default(selector, config, output)
17            } else {
18                show_default(config, output)
19            }
20        }
21    }
22}
23
24fn list(config: &Config, output: &Output) -> Result<()> {
25    let workspaces = WorkspaceManager::list()?;
26
27    if workspaces.is_empty() {
28        output.info("No workspaces configured. Run 'gisa setup' to create one.");
29        return Ok(());
30    }
31
32    let default_path = config.default_workspace.as_deref().unwrap_or("");
33
34    for ws in &workspaces {
35        let ws_path = crate::config::workspace::tilde_collapse_path(&ws.root_path);
36        let marker = if ws_path == default_path { "*" } else { " " };
37        let last_synced = ws.last_synced.as_deref().unwrap_or("never");
38        let org_info = if ws.orgs.is_empty() {
39            "all orgs".to_string()
40        } else {
41            format!("{} orgs", ws.orgs.len())
42        };
43        let provider_label = ws.provider.kind.display_name();
44
45        output.plain(&format!(
46            "  {} {}  ({}, {}, last synced: {})",
47            marker, ws_path, provider_label, org_info, last_synced
48        ));
49    }
50
51    if !default_path.is_empty() {
52        let expanded = shellexpand::tilde(default_path);
53        let root = std::path::Path::new(expanded.as_ref());
54        if let Ok(default_ws) = WorkspaceManager::load(root) {
55            output.plain("");
56            output.info(&format!("Default: {}", default_ws.display_label()));
57        }
58    }
59
60    Ok(())
61}
62
63fn show_default(config: &Config, output: &Output) -> Result<()> {
64    match &config.default_workspace {
65        Some(path_str) => {
66            let expanded = shellexpand::tilde(path_str);
67            let root = std::path::Path::new(expanded.as_ref());
68            if let Ok(ws) = WorkspaceManager::load(root) {
69                output.info(&format!("Default workspace: {}", ws.display_label()));
70            } else {
71                output.info(&format!("Default workspace: {} (not found)", path_str));
72            }
73        }
74        None => output.info("No default workspace set. Use 'gisa workspace default <path|name>'."),
75    }
76    Ok(())
77}
78
79fn set_default(selector: &str, config: &Config, output: &Output) -> Result<()> {
80    let ws = WorkspaceManager::resolve(Some(selector), config)?;
81
82    let tilde_path = crate::config::workspace::tilde_collapse_path(&ws.root_path);
83    Config::save_default_workspace(Some(&tilde_path))?;
84    output.success(&format!(
85        "Default workspace set to '{}'",
86        ws.display_label()
87    ));
88    Ok(())
89}
90
91fn clear_default(output: &Output) -> Result<()> {
92    Config::save_default_workspace(None)?;
93    output.success("Default workspace cleared");
94    Ok(())
95}
96
97#[cfg(test)]
98#[path = "workspace_tests.rs"]
99mod tests;