rix/cmd/
build_derivation.rs

1use 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}