upgr/src/config.rs

114 lines
2.9 KiB
Rust

use miette::{Context, Diagnostic, IntoDiagnostic};
use mlua::{prelude::*, Lua};
use std::{path::PathBuf, process::Command};
use thiserror::Error;
use serde::Deserialize;
pub struct Config<'lua> {
pub steps: Vec<Step<'lua>>,
pub shell: Vec<String>,
}
#[derive(Debug, Deserialize)]
pub struct Step<'lua> {
pub command: CfgCommand,
#[serde(default)]
pub interactive: bool,
pub unint_alt: Option<CfgCommand>,
pub workdir: Option<PathBuf>,
#[serde(skip)]
pub when: Option<LuaFunction<'lua>>,
}
#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum CfgCommand {
Shell(String),
Args(Vec<String>),
}
impl ToString for CfgCommand {
fn to_string(&self) -> String {
match self {
Self::Shell(cmd) => cmd.clone(),
Self::Args(args) => args.join(" "),
}
}
}
#[derive(Debug, Error, Diagnostic)]
#[diagnostic(code)]
pub enum IntoCommandError {
#[error("Command has empty args!")]
EmptyArgs,
#[error("Shell command is empty!")]
EmptyShell,
}
impl CfgCommand {
pub fn into_command(self, shell: &[String]) -> Result<Command, IntoCommandError> {
match self {
Self::Args(args) => {
let mut cmd = Command::new(args.first().ok_or(IntoCommandError::EmptyArgs)?);
cmd.args(&args[1..]);
Ok(cmd)
},
Self::Shell(shell_cmd) => {
let mut cmd = Command::new(shell.first().ok_or(IntoCommandError::EmptyShell)?);
cmd.args(&shell[1..]).arg(shell_cmd);
Ok(cmd)
},
}
}
}
pub fn run_config<'lua>(lua: &'lua Lua, content: &[u8]) -> miette::Result<Config<'lua>> {
lua.load(content)
.set_name("config")
.into_diagnostic()?
.exec()
.into_diagnostic()?;
let lua_conf = lua.globals();
let mut conf = Config {
steps: vec![],
shell: lua_conf
.get::<_, Option<_>>("shell")
.into_diagnostic()
.wrap_err("config must declare `shell` variable!")?
.unwrap_or_else(|| vec!["sh".to_string(), "-c".to_string()]),
};
for pair in lua_conf
.get::<_, LuaTable>("steps")
.into_diagnostic()
.wrap_err("config must declare `steps` variable!")?
.pairs::<LuaValue, LuaTable>()
{
let (_, step) = pair.into_diagnostic()?;
let when = step
.get::<_, Option<LuaFunction>>("when")
.into_diagnostic()
.wrap_err("Failed to get `when` from step")?;
let mut step = lua
.from_value_with::<Step>(
LuaValue::Table(step),
mlua::serde::de::Options::new().deny_unsupported_types(false),
)
.into_diagnostic()
.wrap_err("Failed to deserialize step")?;
step.when = when;
conf.steps.push(step);
}
Ok(conf)
}