use std::{
io,
process::{Child, Command, Output},
thread,
time::Duration,
};
const EXECUTABLE_BUSY_RETRY_ATTEMPTS: usize = 8;
const EXECUTABLE_BUSY_RETRY_DELAY: Duration = Duration::from_millis(10);
mod artifact_io;
pub mod binaryen;
mod bootstrap_candid;
mod bootstrap_coordinator;
mod bootstrap_store;
mod build_profile;
pub mod build_provenance;
pub mod build_toolchain;
pub mod candid_endpoints;
pub mod canic_metadata;
pub mod canister_build;
mod canister_protocol;
mod canonical_root;
mod fleet_package;
pub use canister_protocol::{
CanisterProtocolError, call_with_arg as call_canister_with_arg,
query_with_arg as query_canister_with_arg,
};
pub mod canister_ready;
mod cargo_metadata;
pub mod component_operation;
pub mod component_topology;
pub mod config_discovery;
pub mod diagnostics;
pub mod durable_io;
mod entropy;
pub mod evidence_envelope;
pub mod fleet_ensure;
pub mod format;
pub mod frontend;
pub mod ic_wasm;
pub mod icp;
pub mod icp_config;
#[cfg(feature = "local-fleet")]
pub mod local_fleet;
pub mod network;
pub mod observability;
pub mod observatory;
pub mod policy_gate;
pub mod protocol_binding;
pub mod registry;
pub mod release_build;
pub mod release_set;
pub mod replica_query;
pub mod role_contract;
pub mod state_manifest;
pub mod subnet_catalog;
pub mod table;
pub mod terminal;
#[cfg(test)]
mod test_support;
mod workspace_discovery;
pub(crate) fn cargo_command() -> Command {
let cargo = std::env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
let mut command = Command::new(cargo);
if let Some(toolchain) = std::env::var_os("RUSTUP_TOOLCHAIN") {
command.env("RUSTUP_TOOLCHAIN", toolchain);
}
command
}
fn with_executable_busy_retry<T>(mut launch: impl FnMut() -> io::Result<T>) -> io::Result<T> {
for attempt in 0..EXECUTABLE_BUSY_RETRY_ATTEMPTS {
match launch() {
Err(error)
if error.kind() == io::ErrorKind::ExecutableFileBusy
&& attempt + 1 < EXECUTABLE_BUSY_RETRY_ATTEMPTS =>
{
thread::sleep(EXECUTABLE_BUSY_RETRY_DELAY);
}
result => return result,
}
}
unreachable!("bounded executable-busy retry always returns on its final attempt")
}
pub(crate) fn output_with_executable_busy_retry(command: &mut Command) -> io::Result<Output> {
with_executable_busy_retry(|| command.output())
}
pub(crate) fn spawn_with_executable_busy_retry(command: &mut Command) -> io::Result<Child> {
with_executable_busy_retry(|| command.spawn())
}
pub(crate) fn should_embed_candid_metadata(build_network: canic_core::ids::BuildNetwork) -> bool {
build_network == canic_core::ids::BuildNetwork::Local
}
#[cfg(test)]
mod tests;