use futures::Stream;
use crate::Result;
use crate::bindings::oino::extension::process as wp;
pub use crate::bindings::oino::extension::process::{
ExecResult, ExitStatus, OutputTarget, ProcStats, Signal, SpawnSpec, StdioMode,
};
pub async fn exec(
command: &str,
args: &[&str],
cwd: Option<&str>,
timeout_ms: Option<u64>,
) -> Result<ExecResult> {
exec_env(command, args, cwd, &[], timeout_ms).await
}
pub async fn exec_env(
command: &str,
args: &[&str],
cwd: Option<&str>,
env: &[(String, String)],
timeout_ms: Option<u64>,
) -> Result<ExecResult> {
let options = wp::ExecOptions {
cwd: cwd.map(ToOwned::to_owned),
timeout_ms,
env: env.to_vec(),
};
Ok(wp::exec(
command.to_owned(),
args.iter().map(ToString::to_string).collect(),
options,
)
.await?)
}
#[must_use]
pub fn spec(command: &str, args: &[&str]) -> SpawnSpec {
SpawnSpec {
command: command.to_owned(),
args: args.iter().map(ToString::to_string).collect(),
cwd: None,
env: Vec::new(),
clear_env: false,
stdin: StdioMode::Pipe,
stdout: OutputTarget::Pipe,
stderr: OutputTarget::Pipe,
new_process_group: true,
detached: false,
timeout_ms: None,
}
}
pub struct Child(wp::Child);
impl Child {
pub fn spawn(spec: &SpawnSpec) -> Result<Self> {
Ok(Self(wp::Child::spawn(spec)?))
}
#[must_use]
pub fn pid(&self) -> u32 {
self.0.pid()
}
pub async fn write_stdin(&self, data: &[u8]) -> Result<()> {
Ok(self.0.write_stdin(data.to_vec()).await?)
}
pub fn close_stdin(&self) {
self.0.close_stdin();
}
pub fn stdout(&self) -> Option<impl Stream<Item = u8> + use<>> {
self.0
.stdout()
.map(wit_bindgen::rt::async_support::StreamReader::into_stream)
}
pub fn stderr(&self) -> Option<impl Stream<Item = u8> + use<>> {
self.0
.stderr()
.map(wit_bindgen::rt::async_support::StreamReader::into_stream)
}
pub async fn read_stdout(&self) -> String {
match self.0.stdout() {
Some(r) => String::from_utf8_lossy(&r.collect().await).into_owned(),
None => String::new(),
}
}
pub async fn wait(&self) -> ExitStatus {
self.0.wait().await
}
#[must_use]
pub fn try_wait(&self) -> Option<ExitStatus> {
self.0.try_wait()
}
pub fn signal(&self, sig: Signal, group: bool) -> Result<()> {
Ok(self.0.signal(sig, group)?)
}
}
pub fn tree(pid: u32) -> Result<Vec<u32>> {
Ok(wp::process_tree(pid)?)
}
pub fn stats(pid: u32) -> Result<ProcStats> {
Ok(wp::process_stats(pid)?)
}
pub use wp::self_pid;