nix: teach it to evaluate strings passed over the cli

This commit is contained in:
Graham Christensen 2019-01-01 15:24:48 -05:00
parent 8333409bd0
commit a7de0792fc
No known key found for this signature in database
GPG key ID: ACA1C1D120C83D5C

View file

@ -1,5 +1,6 @@
use ofborg::asynccmd::{AsyncCmd, SpawnedAsyncCmd}; use ofborg::asynccmd::{AsyncCmd, SpawnedAsyncCmd};
use ofborg::partition_result; use ofborg::partition_result;
use std::collections::HashMap;
use std::env; use std::env;
use std::fmt; use std::fmt;
use std::fs::File; use std::fs::File;
@ -13,6 +14,7 @@ use tempfile::tempfile;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Operation { pub enum Operation {
Evaluate,
Instantiate, Instantiate,
Build, Build,
QueryPackagesJSON, QueryPackagesJSON,
@ -24,6 +26,7 @@ pub enum Operation {
impl Operation { impl Operation {
fn command(&self) -> Command { fn command(&self) -> Command {
match *self { match *self {
Operation::Evaluate => Command::new("nix-instantiate"),
Operation::Instantiate => Command::new("nix-instantiate"), Operation::Instantiate => Command::new("nix-instantiate"),
Operation::Build => Command::new("nix-build"), Operation::Build => Command::new("nix-build"),
Operation::QueryPackagesJSON => Command::new("nix-env"), Operation::QueryPackagesJSON => Command::new("nix-env"),
@ -53,6 +56,9 @@ impl Operation {
Operation::NoOp { ref operation } => { Operation::NoOp { ref operation } => {
operation.args(command); operation.args(command);
} }
Operation::Evaluate => {
command.args(&["--eval", "--strict", "--json"]);
}
_ => (), _ => (),
}; };
} }
@ -67,6 +73,7 @@ impl fmt::Display for Operation {
Operation::QueryPackagesOutputs => write!(f, "nix-env -qaP --no-name --out-path"), Operation::QueryPackagesOutputs => write!(f, "nix-env -qaP --no-name --out-path"),
Operation::NoOp { ref operation } => operation.fmt(f), Operation::NoOp { ref operation } => operation.fmt(f),
Operation::Unknown { ref program } => write!(f, "{}", program), Operation::Unknown { ref program } => write!(f, "{}", program),
Operation::Evaluate => write!(f, "nix-instantiate --strict --json ..."),
} }
} }
} }
@ -160,6 +167,24 @@ impl Nix {
self.safe_command(&Operation::Instantiate, nixpkgs, attrargs) self.safe_command(&Operation::Instantiate, nixpkgs, attrargs)
} }
pub fn safely_evaluate_expr_cmd(
&self,
nixpkgs: &Path,
expr: &str,
argstrs: HashMap<&str, &str>,
) -> Command {
let mut attrargs: Vec<String> = Vec::with_capacity(2 + (argstrs.len() * 3));
attrargs.push("--expr".to_owned());
attrargs.push(expr.to_owned());
for (argname, argstr) in argstrs {
attrargs.push(String::from("--argstr"));
attrargs.push(argname.to_owned());
attrargs.push(argstr.to_owned());
}
self.safe_command(&Operation::Evaluate, nixpkgs, attrargs)
}
pub fn safely_build_attrs( pub fn safely_build_attrs(
&self, &self,
nixpkgs: &Path, nixpkgs: &Path,
@ -646,6 +671,22 @@ mod tests {
assert_run(ret, Expect::Pass, vec!["-passes-instantiation.drv"]); assert_run(ret, Expect::Pass, vec!["-passes-instantiation.drv"]);
} }
#[test]
fn safely_evaluate_expr_success() {
let nix = nix();
let ret: Result<File, File> = nix.run(
nix.safely_evaluate_expr_cmd(
individual_eval_path().as_path(),
r#"{ foo ? "bar" }: "The magic value is ${foo}""#,
[("foo", "tux")].iter().cloned().collect(),
),
true,
);
assert_run(ret, Expect::Pass, vec!["The magic value is tux"]);
}
#[test] #[test]
fn strict_sandboxing() { fn strict_sandboxing() {
let ret: Result<File, File> = nix().safely_build_attrs( let ret: Result<File, File> = nix().safely_build_attrs(