feat(tvix/cli): add helper for handling special drv parameters

Adds a helper function which handles special parameters to
`builtins.derivation` that are not just blindly passed through to the
builder environment, but populate other specific fields of the
derivation (outside of the ones handled by other, more complex helpers
from previous commits).

Change-Id: I82d1edf9af714fc4591e9071c0b83ece83be7eee
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7901
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
This commit is contained in:
Vincent Ambo 2023-01-23 01:38:36 +03:00 committed by tazjin
parent dfc50c9ef5
commit 3d7c371e22

View file

@ -7,6 +7,9 @@ use tvix_eval::{AddContext, CoercionKind, ErrorKind, NixList, Value, VM};
use crate::errors::Error;
use crate::known_paths::{KnownPaths, PathType};
// Constants used for strangely named fields in derivation inputs.
const IGNORE_NULLS: &str = "__ignoreNulls";
/// Helper function for populating the `drv.outputs` field from a
/// manually specified set of outputs, instead of the default
/// `outputs`.
@ -131,6 +134,60 @@ fn populate_output_configuration(
Ok(())
}
/// Handles derivation parameters which are not just forwarded to
/// the environment. The return value indicates whether the
/// parameter should be included in the environment.
fn handle_derivation_parameters(
drv: &mut Derivation,
vm: &mut VM,
name: &str,
value: &Value,
val_str: &str,
) -> Result<bool, ErrorKind> {
match name {
IGNORE_NULLS => return Ok(false),
// Command line arguments to the builder.
"args" => {
let args = value.to_list()?;
for arg in args {
drv.arguments.push(
arg.force(vm)?
.coerce_to_string(CoercionKind::Strong, vm)
.context("handling command-line builder arguments")?
.as_str()
.to_string(),
);
}
// The arguments do not appear in the environment.
return Ok(false);
}
// Explicitly specified drv outputs (instead of default [ "out" ])
"outputs" => {
let outputs = value
.to_list()
.context("looking at the `outputs` parameter of the derivation")?;
drv.outputs.clear();
populate_outputs(vm, drv, outputs)?;
}
"builder" => {
drv.builder = val_str.to_string();
}
"system" => {
drv.system = val_str.to_string();
}
_ => {}
}
Ok(true)
}
#[cfg(test)]
mod tests {
use super::*;
@ -291,4 +348,53 @@ mod tests {
assert_eq!(drv.outputs["out"].hash, Some(expected));
}
#[test]
fn handle_outputs_parameter() {
let mut vm = fake_vm();
let mut drv = Derivation::default();
drv.outputs.insert("out".to_string(), Default::default());
let outputs = Value::List(NixList::construct(
2,
vec![Value::String("foo".into()), Value::String("bar".into())],
));
let outputs_str = outputs
.coerce_to_string(CoercionKind::Strong, &mut vm)
.unwrap();
handle_derivation_parameters(&mut drv, &mut vm, "outputs", &outputs, outputs_str.as_str())
.expect("handling 'outputs' parameter should succeed");
assert_eq!(drv.outputs.len(), 2);
assert!(drv.outputs.contains_key("bar"));
assert!(drv.outputs.contains_key("foo"));
}
#[test]
fn handle_args_parameter() {
let mut vm = fake_vm();
let mut drv = Derivation::default();
let args = Value::List(NixList::construct(
3,
vec![
Value::String("--foo".into()),
Value::String("42".into()),
Value::String("--bar".into()),
],
));
let args_str = args
.coerce_to_string(CoercionKind::Strong, &mut vm)
.unwrap();
handle_derivation_parameters(&mut drv, &mut vm, "args", &args, args_str.as_str())
.expect("handling 'args' parameter should succeed");
assert_eq!(
drv.arguments,
vec!["--foo".to_string(), "42".to_string(), "--bar".to_string()]
);
}
}