use std::collections::BTreeMap;
use std::fmt::Display;
use std::process::ExitStatus;
use bon::Builder;
use indexmap::IndexMap;
use nonempty::NonEmpty;
#[derive(Debug)]
pub struct NoImageError;
impl Display for NoImageError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "no image specified")
}
}
impl std::error::Error for NoImageError {}
#[derive(Builder, Clone, Debug)]
#[builder(builder_type = Builder)]
pub struct Execution {
#[builder(with = |iter: impl IntoIterator<Item = impl Into<String>>| -> Result<_, NoImageError> {
NonEmpty::collect(iter.into_iter().map(Into::into)).ok_or(NoImageError)
})]
pub(crate) images: NonEmpty<String>,
#[builder(into)]
pub(crate) program: String,
#[builder(into, default)]
pub(crate) args: Vec<String>,
#[builder(into)]
pub(crate) work_dir: Option<String>,
#[builder(into)]
pub(crate) stdin: Option<String>,
#[builder(into)]
pub(crate) stdout: Option<String>,
#[builder(into)]
pub(crate) stderr: Option<String>,
#[builder(into, default)]
pub(crate) env: IndexMap<String, String>,
}
impl Execution {
pub fn images(&self) -> &NonEmpty<String> {
&self.images
}
pub fn program(&self) -> &str {
&self.program
}
pub fn args(&self) -> &[String] {
&self.args
}
pub fn work_dir(&self) -> Option<&str> {
self.work_dir.as_deref()
}
pub fn stdin(&self) -> Option<&str> {
self.stdin.as_deref()
}
pub fn stdout(&self) -> Option<&str> {
self.stdout.as_deref()
}
pub fn stderr(&self) -> Option<&str> {
self.stderr.as_deref()
}
pub fn env(&self) -> &IndexMap<String, String> {
&self.env
}
}
impl From<Execution> for tes::v1::types::task::Executor {
fn from(execution: Execution) -> Self {
let env = execution
.env
.into_iter()
.collect::<BTreeMap<String, String>>();
let env = if env.is_empty() { None } else { Some(env) };
let mut command = Vec::with_capacity(execution.args.len() + 1);
command.push(execution.program);
command.extend(execution.args);
tes::v1::types::task::Executor {
image: execution.images.first().into(),
command,
workdir: execution.work_dir,
stdin: execution.stdin,
stdout: execution.stdout,
stderr: execution.stderr,
env,
ignore_error: Some(true),
}
}
}
#[derive(Clone, Debug)]
pub struct ExecutionResult {
pub image: Option<String>,
pub status: ExitStatus,
}