use std::io::Write;
use std::path::Path;
use serde_json::Value;
fn append_line(file: &str, line: &str, append: bool) {
let mut handle = std::fs::OpenOptions::new()
.create(true)
.append(append)
.truncate(!append)
.write(true)
.open(file)
.expect("open record file");
writeln!(handle, "{line}").expect("write record file");
}
fn main() -> std::process::ExitCode {
let args = std::env::args().skip(1).collect::<Vec<_>>().join(" ");
let spec_path = match std::env::var("STK_FAKE_SPEC") {
Ok(path) => path,
Err(_) => {
eprintln!("fake-provider: STK_FAKE_SPEC is not set");
return std::process::ExitCode::FAILURE;
}
};
let spec = std::fs::read_to_string(&spec_path).expect("read fake spec");
let spec: Value = serde_json::from_str(&spec).expect("parse fake spec");
if let Some(log) = spec["log"].as_str() {
append_line(log, &args, true);
}
let rules = spec["rules"].as_array().expect("spec rules array");
for rule in rules {
let needle = rule["contains"].as_str().unwrap_or("");
if !args.contains(needle) {
continue;
}
if let Some(marker) = rule["if_file"].as_str()
&& !Path::new(marker).exists()
{
continue;
}
if let Some(file) = rule["record"].as_str() {
append_line(file, &args, rule["append"].as_bool().unwrap_or(false));
}
if let Some(out) = rule["stdout"].as_str()
&& !out.is_empty()
{
print!("{out}");
if !out.ends_with('\n') {
println!();
}
}
if let Some(err) = rule["stderr"].as_str()
&& !err.is_empty()
{
eprintln!("{err}");
}
let code = rule["exit"].as_i64().unwrap_or(0) as u8;
return std::process::ExitCode::from(code);
}
eprintln!("fake-provider: no rule matched args: {args}");
std::process::ExitCode::FAILURE
}