rix/cmd/
build_derivation.rs1use crate::building::{build_derivation_sandboxed, BuildConfig};
2use crate::cmd::{to_cmd_err, RixSubCommand};
3use crate::derivations;
4use clap::{Arg, ArgAction, ArgMatches};
5use std::fs::File;
6use std::path::PathBuf;
7use tempfile::tempdir;
8
9pub fn cmd() -> RixSubCommand {
10 return RixSubCommand {
11 name: "build-derivation",
12 handler: |args| to_cmd_err(handle_cmd(args)),
13 cmd: |subcommand| {
14 subcommand
15 .about("builds the derivation assuming all dependencies are present in the store and won't be GC'd")
16 .arg(Arg::new("DERIVATION").required(true).help(
17 "The path of the derivation to build.",
18 ))
19 .arg(Arg::new("build-dir").long("build-dir").action(ArgAction::Set).help("The directory in which to run the build process."))
20 .arg(Arg::new("stdout").long("stdout").action(ArgAction::Set).help("The file to which to redirect the standard output of the build"))
21 .arg(Arg::new("stderr").long("stderr").action(ArgAction::Set).help("The file to which to redirect the error output of the build"))
22 },
23 };
24}
25
26pub fn handle_cmd(parsed_args: &ArgMatches) -> Result<(), String> {
27 let derivation_path = parsed_args
28 .get_one::<String>("DERIVATION")
29 .ok_or("You must specify a derivation.")?;
30 let build_dir = parsed_args
31 .get_one::<String>("build-dir")
32 .map_or_else(create_build_dir, |str| Ok(PathBuf::from(str)))?;
33 let stdout_file = parsed_args
34 .get_one::<String>("stdout")
35 .map(File::create)
36 .transpose()
37 .map_err(|err| format!("Could not create the stdout file. Error: {}", err))?;
38 let stderr_file = parsed_args
39 .get_one::<String>("stderr")
40 .map(File::create)
41 .transpose()
42 .map_err(|err| format!("Could not create the stderr file. Error: {}", err))?;
43 let derivation = derivations::load_derivation(derivation_path)?;
44 let mut build_config = BuildConfig::new(&derivation, &build_dir);
45 if let Some(stdout_file) = stdout_file.as_ref() {
46 build_config.stdout_to_file(stdout_file);
47 }
48 if let Some(stderr_file) = stderr_file.as_ref() {
49 build_config.stderr_to_file(stderr_file);
50 }
51 let result_code = build_derivation_sandboxed(&build_config)?;
52 println!("{}", build_dir.to_str().unwrap());
53 std::process::exit(result_code);
54}
55
56fn create_build_dir() -> Result<PathBuf, String> {
57 tempdir()
58 .map_err(|err| format!("Could not create the build directory. Error: {}", err))
59 .map(|tmp_dir| tmp_dir.into_path())
60}