Skip to main content

canic_host/release_set/paths/
workspace.rs

1use crate::workspace_discovery::{
2    discover_icp_root_from, discover_workspace_root_from, normalize_workspace_path,
3};
4use std::path::{Path, PathBuf};
5
6use super::super::{CANISTERS_ROOT_RELATIVE, ROOT_CONFIG_FILE, WORKSPACE_MANIFEST_RELATIVE};
7
8// Resolve the downstream Cargo workspace root from the current directory,
9// config hints, or an explicit override.
10pub fn workspace_root() -> Result<PathBuf, Box<dyn std::error::Error>> {
11    if let Ok(path) = std::env::var("CANIC_WORKSPACE_ROOT") {
12        return Ok(PathBuf::from(path).canonicalize()?);
13    }
14
15    if let Some(root) = std::env::var_os("CANIC_WORKSPACE_MANIFEST_PATH")
16        .map(PathBuf::from)
17        .and_then(|path| discover_workspace_root_from(&path))
18    {
19        return Ok(root);
20    }
21
22    if let Some(root) = std::env::var_os("CANIC_CONFIG_PATH")
23        .map(PathBuf::from)
24        .and_then(|path| discover_workspace_root_from(&path))
25    {
26        return Ok(root);
27    }
28
29    if let Some(root) = discover_workspace_root_from(&std::env::current_dir()?) {
30        return Ok(root);
31    }
32
33    Ok(std::env::current_dir()?.canonicalize()?)
34}
35
36// Resolve the downstream ICP CLI/project root from the current directory or an
37// explicit override.
38pub fn icp_root() -> Result<PathBuf, Box<dyn std::error::Error>> {
39    if let Ok(path) = std::env::var("CANIC_ICP_ROOT") {
40        return Ok(PathBuf::from(path).canonicalize()?);
41    }
42
43    let current_dir = std::env::current_dir()?.canonicalize()?;
44    if let Some(root) = discover_icp_root_from(&current_dir) {
45        return Ok(root);
46    }
47
48    if let Ok(path) = std::env::var("CANIC_WORKSPACE_ROOT") {
49        let workspace_root = PathBuf::from(path).canonicalize()?;
50        if let Some(root) = discover_icp_root_from(&workspace_root) {
51            return Ok(root);
52        }
53        return Ok(workspace_root);
54    }
55
56    Ok(current_dir)
57}
58
59// Resolve the downstream Canic config path.
60#[must_use]
61pub fn config_path(workspace_root: &Path) -> PathBuf {
62    std::env::var_os("CANIC_CONFIG_PATH").map_or_else(
63        || canisters_root(workspace_root).join(ROOT_CONFIG_FILE),
64        |path| normalize_workspace_path(workspace_root, PathBuf::from(path)),
65    )
66}
67
68// Resolve the downstream canister-manifest root.
69#[must_use]
70pub fn canisters_root(workspace_root: &Path) -> PathBuf {
71    if let Some(path) = std::env::var_os("CANIC_CANISTERS_ROOT") {
72        return normalize_workspace_path(workspace_root, PathBuf::from(path));
73    }
74
75    if let Some(path) = std::env::var_os("CANIC_CONFIG_PATH") {
76        let config_path = normalize_workspace_path(workspace_root, PathBuf::from(path));
77        if let Some(parent) = config_path.parent() {
78            return parent.to_path_buf();
79        }
80    }
81
82    workspace_root.join(CANISTERS_ROOT_RELATIVE)
83}
84
85// Resolve the downstream workspace manifest path.
86#[must_use]
87pub fn workspace_manifest_path(workspace_root: &Path) -> PathBuf {
88    std::env::var_os("CANIC_WORKSPACE_MANIFEST_PATH").map_or_else(
89        || workspace_root.join(WORKSPACE_MANIFEST_RELATIVE),
90        |path| normalize_workspace_path(workspace_root, PathBuf::from(path)),
91    )
92}
93
94// Render a path relative to the workspace root when possible.
95#[must_use]
96pub fn display_workspace_path(workspace_root: &Path, path: &Path) -> String {
97    path.strip_prefix(workspace_root)
98        .unwrap_or(path)
99        .display()
100        .to_string()
101}