tatara_lisp_script/stdlib/
sops.rs1use std::process::Command;
10use std::sync::Arc;
11
12use tatara_lisp_eval::{Arity, EvalError, Interpreter, Value};
13
14use crate::script_ctx::ScriptCtx;
15use crate::stdlib::env::str_arg;
16
17pub fn install(interp: &mut Interpreter<ScriptCtx>) {
18 interp.register_fn(
19 "sops-extract",
20 Arity::Exact(2),
21 |args: &[Value], _ctx: &mut ScriptCtx, sp| {
22 let path = str_arg(&args[0], "sops-extract", sp)?;
23 let expr = str_arg(&args[1], "sops-extract", sp)?;
24
25 let sops = which::which("sops").map_err(|e| {
27 EvalError::native_fn("sops-extract", format!("sops not found on PATH: {e}"), sp)
28 })?;
29
30 let out = Command::new(&sops)
31 .args(["-d", "--extract", &expr, &path])
32 .output()
33 .map_err(|e| EvalError::native_fn("sops-extract", e.to_string(), sp))?;
34
35 if !out.status.success() {
36 let stderr = String::from_utf8_lossy(&out.stderr);
37 return Err(EvalError::native_fn(
38 "sops-extract",
39 format!("sops failed ({}): {stderr}", out.status),
40 sp,
41 ));
42 }
43
44 let body = String::from_utf8(out.stdout).map_err(|e| {
45 EvalError::native_fn("sops-extract", format!("non-utf8 output: {e}"), sp)
46 })?;
47 Ok(Value::Str(Arc::from(body.trim_end_matches('\n'))))
49 },
50 );
51}