Skip to main content

wisp/session/
workspace_status.rs

1use std::path::{Path, PathBuf};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
4pub enum WorkspaceAccess {
5    #[default]
6    Local,
7    Remote,
8}
9
10impl WorkspaceAccess {
11    pub fn display_path(self, path: &Path) -> String {
12        match self {
13            Self::Local => home_relative_path(path),
14            Self::Remote => path.display().to_string(),
15        }
16    }
17}
18
19#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct WorkspaceStatus {
21    pub display_dir: String,
22    pub git_ref: Option<String>,
23}
24
25impl WorkspaceStatus {
26    pub fn new(display_dir: impl Into<String>, git_ref: Option<String>) -> Self {
27        Self { display_dir: display_dir.into(), git_ref }
28    }
29
30    pub fn remote(cwd: &Path) -> Self {
31        Self::new(format!("remote: {}", cwd.display()), None)
32    }
33
34    /// Creates the path portion of the status without touching the repository.
35    /// Git metadata is resolved by the runtime's `Command::ResolveWorkspace`
36    /// operation, keeping process execution outside session state.
37    pub fn initial(cwd: &Path) -> Self {
38        Self::new(home_relative_path(cwd), None)
39    }
40}
41
42pub fn home_relative_path(path: &Path) -> String {
43    home_dir().map_or_else(|| path.display().to_string(), |home| home_relative_path_with_home(path, &home))
44}
45
46fn home_dir() -> Option<PathBuf> {
47    std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE")).map(PathBuf::from)
48}
49
50fn home_relative_path_with_home(path: &Path, home: &Path) -> String {
51    if path == home {
52        return "~".to_string();
53    }
54    path.strip_prefix(home)
55        .ok()
56        .filter(|relative| !relative.as_os_str().is_empty())
57        .map_or_else(|| path.display().to_string(), |relative| format!("~/{}", relative.display()))
58}