about summary refs log tree commit diff
path: root/tvix/cli/src/derivation.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2023-01-22T22·38+0300
committertazjin <tazjin@tvl.su>2023-01-27T12·21+0000
commit3d7c371e2208c6171a70c0b0485fcd7e6ea6d47b (patch)
tree2cc56cb29ec4d5754b65df512c515c56c3d8b49b /tvix/cli/src/derivation.rs
parentdfc50c9ef53155a1e2b40d4bb203e43aa06dc428 (diff)
feat(tvix/cli): add helper for handling special drv parameters r/5767
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
Diffstat (limited to 'tvix/cli/src/derivation.rs')
-rw-r--r--tvix/cli/src/derivation.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/tvix/cli/src/derivation.rs b/tvix/cli/src/derivation.rs
index 5b696ec18ef6..60471179911c 100644
--- a/tvix/cli/src/derivation.rs
+++ b/tvix/cli/src/derivation.rs
@@ -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()]
+        );
+    }
 }