diff --git a/ofborg/src/evalchecker.rs b/ofborg/src/evalchecker.rs index f485d77..096d188 100644 --- a/ofborg/src/evalchecker.rs +++ b/ofborg/src/evalchecker.rs @@ -7,16 +7,16 @@ use ofborg::nix; pub struct EvalChecker { name: String, - cmd: String, + op: nix::Operation, args: Vec, nix: nix::Nix, } impl EvalChecker { - pub fn new(name: &str, cmd: &str, args: Vec, nix: nix::Nix) -> EvalChecker { + pub fn new(name: &str, op: nix::Operation, args: Vec, nix: nix::Nix) -> EvalChecker { EvalChecker { name: name.to_owned(), - cmd: cmd.to_owned(), + op: op, args: args, nix: nix, } @@ -27,11 +27,11 @@ impl EvalChecker { } pub fn execute(&self, path: &Path) -> Result { - self.nix.safely(&self.cmd, path, self.args.clone(), false) + self.nix.safely(self.op.clone(), path, self.args.clone(), false) } pub fn cli_cmd(&self) -> String { - let mut cli = vec![self.cmd.clone()]; + let mut cli = vec![self.op.to_string()]; cli.append(&mut self.args.clone()); return cli.join(" "); } diff --git a/ofborg/src/nix.rs b/ofborg/src/nix.rs index 6183c47..207320a 100644 --- a/ofborg/src/nix.rs +++ b/ofborg/src/nix.rs @@ -1,5 +1,5 @@ use std::env; -use std::ffi::OsString; +use std::fmt; use std::fs::File; use std::io::Seek; use std::io::SeekFrom; @@ -7,6 +7,58 @@ use std::path::Path; use std::process::{Command, Stdio}; use tempfile::tempfile; +#[derive(Clone, Debug)] +pub enum Operation { + Instantiate, + Build, + QueryPackagesJSON, + QueryPackagesOutputs, + NoOp { operation: Box }, + Unknown { program: String }, +} + +impl Operation { + fn command(&self) -> Command { + match *self { + Operation::Instantiate => Command::new("nix-instantiate"), + Operation::Build => Command::new("nix-build"), + Operation::QueryPackagesJSON => Command::new("nix-env"), + Operation::QueryPackagesOutputs => Command::new("nix-env"), + Operation::NoOp { operation: _ } => Command::new("echo"), + Operation::Unknown { ref program } => Command::new(program), + } + } + + fn args(&self, command: &mut Command) { + match *self { + Operation::Build => { + command.args(&["--no-out-link", "--keep-going"]); + }, + Operation::QueryPackagesJSON => { + command.args(&["--query", "--available", "--json"]); + }, + Operation::QueryPackagesOutputs => { + command.args(&["--query", "--available", "--no-name", "--attr-path", "--out-path"]); + }, + Operation::NoOp { ref operation } => { operation.args(command); }, + _ => (), + }; + } +} + +impl fmt::Display for Operation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Operation::Build => write!(f, "{}", "nix-build"), + Operation::Instantiate => write!(f, "{}", "nix-instantiate"), + Operation::QueryPackagesJSON => write!(f, "{}", "nix-env -qa --json"), + Operation::QueryPackagesOutputs => write!(f, "{}", "nix-env -qaP --no-name --out-path"), + Operation::NoOp { ref operation } => operation.fmt(f), + Operation::Unknown { ref program } => write!(f, "{}", program), + } + } +} + #[derive(Clone, Debug, PartialEq)] pub struct Nix { system: String, @@ -64,24 +116,22 @@ impl Nix { ) -> Command { let mut attrargs: Vec = Vec::with_capacity(3 + (attrs.len() * 2)); attrargs.push(file.to_owned()); - attrargs.push(String::from("--no-out-link")); - attrargs.push(String::from("--keep-going")); for attr in attrs { attrargs.push(String::from("-A")); attrargs.push(attr); } - return self.safe_command("nix-build", nixpkgs, attrargs); + return self.safe_command(Operation::Build, nixpkgs, attrargs); } pub fn safely( &self, - cmd: &str, + op: Operation, nixpkgs: &Path, args: Vec, keep_stdout: bool, ) -> Result { - return self.run(self.safe_command(cmd, nixpkgs, args), keep_stdout); + return self.run(self.safe_command(op, nixpkgs, args), keep_stdout); } pub fn run(&self, mut cmd: Command, keep_stdout: bool) -> Result { @@ -113,12 +163,12 @@ impl Nix { } } - pub fn safe_command(&self, cmd: &str, nixpkgs: &Path, args: Vec) -> Command { - let mut nixpath = OsString::new(); - nixpath.push("nixpkgs="); - nixpath.push(nixpkgs.as_os_str()); + pub fn safe_command(&self, op: Operation, nixpkgs: &Path, args: Vec) -> Command { + let nixpath = format!("nixpkgs={}", nixpkgs.display()); + + let mut command = op.command(); + op.args(&mut command); - let mut command = Command::new(cmd); command.env_clear(); command.current_dir(nixpkgs); command.env("HOME", "/homeless-shelter"); @@ -165,6 +215,14 @@ mod tests { Nix::new("x86_64-linux".to_owned(), "daemon".to_owned(), 1800, None) } + fn noop(operation: Operation) -> Operation { + Operation::NoOp { operation: Box::new(operation) } + } + + fn env_noop() -> Operation { + Operation::Unknown { program: "./environment.sh".to_owned() } + } + fn build_path() -> PathBuf { let mut cwd = env::current_dir().unwrap(); cwd.push(Path::new("./test-srcs/build")); @@ -270,13 +328,92 @@ mod tests { use std::path::PathBuf; use std::env; + #[test] + fn test_build_operations() { + let nix = nix(); + let op = noop(Operation::Build); + assert_eq!(op.to_string(), "nix-build"); + + let ret: Result = + nix.run( + nix.safe_command(op, build_path().as_path(), vec![String::from("--version")]), + true, + ); + + assert_run( + ret, + Expect::Pass, + vec!["--no-out-link --keep-going", "--version"], + ); + } + + #[test] + fn test_instantiate_operation() { + let nix = nix(); + let op = noop(Operation::Instantiate); + assert_eq!(op.to_string(), "nix-instantiate"); + + let ret: Result = + nix.run( + nix.safe_command(op, build_path().as_path(), vec![String::from("--version")]), + true, + ); + + assert_run( + ret, + Expect::Pass, + vec!["--version"], + ); + } + + #[test] + fn test_query_packages_json() { + let nix = nix(); + let op = noop(Operation::QueryPackagesJSON); + assert_eq!(op.to_string(), "nix-env -qa --json"); + + let ret: Result = + nix.run( + nix.safe_command(op, build_path().as_path(), vec![String::from("--version")]), + true, + ); + + assert_run( + ret, + Expect::Pass, + vec!["--query --available --json", "--version"], + ); + } + + #[test] + fn test_query_packages_outputs() { + let nix = nix(); + let op = noop(Operation::QueryPackagesOutputs); + assert_eq!(op.to_string(), "nix-env -qaP --no-name --out-path"); + + let ret: Result = + nix.run( + nix.safe_command(op, build_path().as_path(), vec![String::from("--version")]), + true, + ); + + assert_run( + ret, + Expect::Pass, + vec![ + "--query --available --no-name --attr-path --out-path", + "--version" + ], + ); + } + #[test] fn safe_command_environment() { let nix = nix(); let ret: Result = nix.run( - nix.safe_command("./environment.sh", build_path().as_path(), vec![]), + nix.safe_command(env_noop(), build_path().as_path(), vec![]), true, ); @@ -298,7 +435,7 @@ mod tests { let ret: Result = nix.run( - nix.safe_command("./environment.sh", build_path().as_path(), vec![]), + nix.safe_command(env_noop(), build_path().as_path(), vec![]), true, ); @@ -318,9 +455,10 @@ mod tests { #[test] fn safe_command_options() { let nix = nix(); + let op = noop(Operation::Build); let ret: Result = nix.run( - nix.safe_command("echo", build_path().as_path(), vec![]), + nix.safe_command(op, build_path().as_path(), vec![]), true, ); @@ -389,11 +527,10 @@ mod tests { ); } - #[test] fn instantiation() { let ret: Result = nix().safely( - "nix-instantiate", + Operation::Instantiate, passing_eval_path().as_path(), vec![], true, diff --git a/ofborg/src/outpathdiff.rs b/ofborg/src/outpathdiff.rs index f3e56c7..2f7ce9e 100644 --- a/ofborg/src/outpathdiff.rs +++ b/ofborg/src/outpathdiff.rs @@ -170,14 +170,11 @@ impl OutPaths { } self.nix.safely( - "nix-env", + nix::Operation::QueryPackagesOutputs, &self.path, vec![ String::from("-f"), String::from(".gc-of-borg-outpaths.nix"), - String::from("-qaP"), - String::from("--no-name"), - String::from("--out-path"), String::from("--arg"), String::from("checkMeta"), check_meta, diff --git a/ofborg/src/tasks/massrebuilder.rs b/ofborg/src/tasks/massrebuilder.rs index 1d7a990..cae6164 100644 --- a/ofborg/src/tasks/massrebuilder.rs +++ b/ofborg/src/tasks/massrebuilder.rs @@ -10,8 +10,8 @@ use std::path::Path; use std::path::PathBuf; use ofborg::checkout; use ofborg::message::{massrebuildjob, buildjob}; -use ofborg::nix::Nix; use std::time::Instant; +use ofborg::nix; use ofborg::acl::ACL; use ofborg::stats; use ofborg::stats::Event; @@ -26,7 +26,7 @@ use hubcaps; pub struct MassRebuildWorker { cloner: checkout::CachedCloner, - nix: Nix, + nix: nix::Nix, github: hubcaps::Github, acl: ACL, identity: String, @@ -37,7 +37,7 @@ pub struct MassRebuildWorker { impl MassRebuildWorker { pub fn new( cloner: checkout::CachedCloner, - nix: Nix, + nix: nix::Nix, github: hubcaps::Github, acl: ACL, identity: String, @@ -306,20 +306,17 @@ impl worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker, @@ -570,7 +567,7 @@ struct Stdenvs { } impl Stdenvs { - fn new(nix: Nix, co: PathBuf) -> Stdenvs { + fn new(nix: nix::Nix, co: PathBuf) -> Stdenvs { return Stdenvs { nix: nix, co: co, @@ -632,7 +629,7 @@ impl Stdenvs { fn evalstdenv(&self, system: &str) -> Option { let result = self.nix.with_system(system.to_owned()).safely( - "nix-instantiate", + nix::Operation::Instantiate, &self.co, vec![ String::from("."), @@ -785,8 +782,7 @@ mod tests { let nixpkgs = String::from_utf8(output.stdout) .expect("nixpkgs required"); - let nix = Nix::new(String::from("x86_64-linux"), String::from("daemon"), 1200, None); - + let nix = nix::Nix::new(String::from("x86_64-linux"), String::from("daemon"), 1200, None); let mut stdenv = Stdenvs::new( nix.clone(),