use anyhow::{Context, Result};
use serde_json::Value;
use std::fs;
use std::io::Read;
use std::path::PathBuf;
use std::process::Command;
pub fn run(
manifest_path: &Option<PathBuf>,
input_path: Option<PathBuf>,
parallel: bool,
example: Option<String>,
bin: Option<String>,
) -> Result<()> {
let input_value: Value = match input_path {
Some(ref path) => {
let data = fs::read_to_string(path).context("failed to read input file")?;
serde_json::from_str(&data).context("input is not valid JSON")?
}
None => {
let mut buffer = String::new();
let stdin_available = std::io::stdin().read_to_string(&mut buffer).is_ok();
if stdin_available && !buffer.is_empty() {
serde_json::from_str(&buffer).context("stdin input is not valid JSON")?
} else {
Value::Object(serde_json::Map::new())
}
}
};
let mut cmd = Command::new("cargo");
cmd.arg("run");
if let Some(ref path) = manifest_path {
cmd.arg("--manifest-path").arg(path);
}
if let Some(example_name) = example {
cmd.arg("--example").arg(example_name);
} else if let Some(bin_name) = bin {
cmd.arg("--bin").arg(bin_name);
}
cmd.env("TUPA_INPUT", serde_json::to_string(&input_value)?);
cmd.env("TUPA_PARALLEL", if parallel { "1" } else { "0" });
let status = cmd
.status()
.context("failed to execute `cargo run` — is the project built?")?;
if !status.success() {
anyhow::bail!(
"pipeline execution failed with exit code: {}",
status.code().unwrap_or(-1)
);
}
Ok(())
}