Skip to main content

canic_host/release_set/paths/
artifacts.rs

1use std::path::{Path, PathBuf};
2use thiserror::Error as ThisError;
3
4/// Failure to locate the exact artifact root for a selected artifact environment.
5#[derive(Debug, Eq, PartialEq, ThisError)]
6pub enum ArtifactRootError {
7    #[error("missing built ICP artifacts under {artifact_root}")]
8    Missing { artifact_root: PathBuf },
9
10    #[error("built ICP artifact root escapes the canonical ICP project root: {artifact_root}")]
11    OutsideProject { artifact_root: PathBuf },
12}
13
14/// Resolve the built artifact directory for the selected artifact environment.
15pub fn resolve_artifact_root(
16    icp_root: &Path,
17    artifact_environment: &str,
18) -> Result<PathBuf, ArtifactRootError> {
19    let artifact_root = artifact_root_path(icp_root, artifact_environment);
20    resolve_artifact_root_path(icp_root, &artifact_root)
21}
22
23/// Resolve one exact built artifact directory confined to the canonical project root.
24pub fn resolve_artifact_root_path(
25    icp_root: &Path,
26    artifact_root: &Path,
27) -> Result<PathBuf, ArtifactRootError> {
28    if !artifact_root.is_dir() {
29        return Err(ArtifactRootError::Missing {
30            artifact_root: artifact_root.to_path_buf(),
31        });
32    }
33
34    let canonical_project = icp_root
35        .canonicalize()
36        .map_err(|_| ArtifactRootError::Missing {
37            artifact_root: icp_root.to_path_buf(),
38        })?;
39    let canonical_artifact =
40        artifact_root
41            .canonicalize()
42            .map_err(|_| ArtifactRootError::Missing {
43                artifact_root: artifact_root.to_path_buf(),
44            })?;
45    if !canonical_artifact.starts_with(&canonical_project) {
46        return Err(ArtifactRootError::OutsideProject {
47            artifact_root: artifact_root.to_path_buf(),
48        });
49    }
50
51    Ok(canonical_artifact)
52}
53
54/// Return the canonical artifact directory for one artifact environment.
55#[must_use]
56pub fn artifact_root_path(icp_root: &Path, artifact_environment: &str) -> PathBuf {
57    icp_root
58        .join(".icp")
59        .join(artifact_environment)
60        .join("canisters")
61}