use crate::{
canister_build::{CanisterBuildProfile, WorkspaceBuildContext},
icp::{self, LocalReplicaTarget},
icp_config::resolve_icp_build_environment_from_root,
replica_query,
};
use std::path::Path;
pub(super) fn resolve_install_build_context(
workspace_root: &Path,
icp_root: &Path,
config_path: &Path,
network: &str,
role: &str,
build_profile: Option<CanisterBuildProfile>,
) -> Result<WorkspaceBuildContext, Box<dyn std::error::Error>> {
let profile = build_profile.unwrap_or_else(CanisterBuildProfile::current);
let requested_profile = build_profile.map_or_else(
|| std::env::var("CANIC_WASM_PROFILE").unwrap_or_else(|_| "unset".to_string()),
|profile| profile.target_dir_name().to_string(),
);
let build_network = resolve_icp_build_environment_from_root(icp_root, network)?;
Ok(WorkspaceBuildContext {
role: role.to_string(),
profile,
requested_profile,
environment: network.to_string(),
build_network: build_network.as_str().to_string(),
workspace_root: workspace_root.to_path_buf(),
icp_root: icp_root.to_path_buf(),
config_path: config_path.to_path_buf(),
local_replica: local_replica_icp_target(network, icp_root),
})
}
pub(super) fn local_replica_icp_target(
network: &str,
icp_root: &Path,
) -> Option<LocalReplicaTarget> {
if !replica_query::should_use_local_replica_query(Some(network)) {
return None;
}
if icp_ping(icp_root, network).unwrap_or(false) {
return None;
}
let root_key = replica_query::local_replica_root_key_from_root(Some(network), icp_root)
.ok()
.flatten()?;
Some(LocalReplicaTarget {
url: replica_query::local_replica_endpoint_from_root(Some(network), icp_root),
root_key,
})
}
pub(super) fn ensure_icp_environment_ready(
icp_root: &Path,
network: &str,
) -> Result<(), Box<dyn std::error::Error>> {
if icp_ping(icp_root, network)? {
return Ok(());
}
if replica_query::should_use_local_replica_query(Some(network))
&& replica_query::local_replica_status_reachable_from_root(Some(network), icp_root)
{
println!(
"Replica reachable via HTTP status endpoint even though ICP CLI reports network '{network}' stopped; continuing from ICP root {}.",
icp_root.display()
);
return Ok(());
}
Err(format!(
"icp environment is not running for network '{network}'\nStart the target replica in another terminal with `canic replica start` and rerun."
)
.into())
}
fn icp_ping(icp_root: &Path, network: &str) -> Result<bool, Box<dyn std::error::Error>> {
let mut command = icp::default_command_in(icp_root);
command.args(["network", "ping", network]);
Ok(icp::run_success(&mut command)?)
}