ic_host_tools/icp/mod.rs
1//! ICP CLI command syntax and installation facts, without process execution.
2//!
3//! Callers select executables, credentials, environments, output formats and
4//! capture limits. No command is dispatched and no tool version is admitted here.
5
6mod status;
7#[cfg(test)]
8mod tests;
9
10use std::{ffi::OsStr, path::Path, process::Command};
11
12pub use status::{InstallationStatusError, decode_installation_status};
13
14/// The already-selected query or update operation; this does not authorize it.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub enum CallMode {
17 /// Append ICP CLI's query switch.
18 Query,
19 /// Use ICP CLI's default update operation.
20 Update,
21}
22
23/// The caller-owned Candid argument representation.
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum CallArguments<'a> {
26 /// Pass a textual Candid argument verbatim as one native argument.
27 Text(&'a OsStr),
28 /// Pass a file containing binary Candid; the caller owns its custody.
29 BinaryFile(&'a Path),
30}
31
32/// The caller-selected status output contract.
33#[derive(Clone, Copy, Debug, Eq, PartialEq)]
34pub enum StatusOutput {
35 /// Leave ICP CLI's output selection unchanged.
36 Text,
37 /// Request structured JSON.
38 Json,
39 /// Request only the canister id.
40 IdOnly,
41}
42
43/// Extend a caller-configured executable with an ICP canister call.
44///
45/// The base must not already contain the `canister` subcommand. Executable,
46/// native arguments, environment, working directory and standard I/O are retained.
47/// Callers append Candid interface, response format and target selection themselves.
48#[must_use]
49pub fn call_command(
50 mut command: Command,
51 canister: &OsStr,
52 method: &OsStr,
53 arguments: CallArguments<'_>,
54 mode: CallMode,
55) -> Command {
56 command.args([OsStr::new("canister"), OsStr::new("call"), canister, method]);
57 match arguments {
58 CallArguments::Text(argument) => {
59 command.arg(argument);
60 }
61 CallArguments::BinaryFile(path) => {
62 command
63 .arg("--args-file")
64 .arg(path)
65 .args(["--args-format", "bin"]);
66 }
67 }
68 if mode == CallMode::Query {
69 command.arg("--query");
70 }
71 command
72}
73
74/// Extend a caller-configured executable with an ICP canister status request.
75///
76/// The base must not already contain the `canister` subcommand. Target selection,
77/// capture, execution, failure interpretation and installation policy stay local.
78#[must_use]
79pub fn status_command(mut command: Command, canister: &OsStr, output: StatusOutput) -> Command {
80 command.args([OsStr::new("canister"), OsStr::new("status"), canister]);
81 match output {
82 StatusOutput::Text => {}
83 StatusOutput::Json => {
84 command.arg("--json");
85 }
86 StatusOutput::IdOnly => {
87 command.arg("--id-only");
88 }
89 }
90 command
91}