about summary refs log tree commit diff
path: root/tvix/glue/src/builtins/derivation.rs
diff options
context:
space:
mode:
authorRyan Lahfa <tvl@lahfa.xyz>2024-03-24T23·59+0100
committerraitobezarius <tvl@lahfa.xyz>2024-03-31T12·40+0000
commit94185f75604aca63c3d0e09a42503610f1dd822d (patch)
treebe63fb056deabc41d66f73f1533c43049ff1591a /tvix/glue/src/builtins/derivation.rs
parent45925ea93135f517bc47c97f5e551d233c3010cc (diff)
feat(tvix/eval): support `Derivation` context elements r/7805
Derivation that depends on `${d.drvPath}` generates a `NixContextElement::Derivation(drvPath)` context string.
In turn, this makes the dependent derivation depend on *ALL* outputs of that derivation.

Note that a dependency on `${d.drvPath}` generates an input source
dependency too.

This is a complete implementation of the context string system in Nix on
the "input population" side.

The test coverage of this change is taken care in cl/11264.

Change-Id: I97fe5f7c772a6b1cc4366bee071aa691a11fcde6
Signed-off-by: Ryan Lahfa <tvl@lahfa.xyz>
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11261
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/glue/src/builtins/derivation.rs')
-rw-r--r--tvix/glue/src/builtins/derivation.rs42
1 files changed, 34 insertions, 8 deletions
diff --git a/tvix/glue/src/builtins/derivation.rs b/tvix/glue/src/builtins/derivation.rs
index 4ea9611a946c..54bc7878bdd4 100644
--- a/tvix/glue/src/builtins/derivation.rs
+++ b/tvix/glue/src/builtins/derivation.rs
@@ -1,5 +1,6 @@
 //! Implements `builtins.derivation`, the core of what makes Nix build packages.
 use crate::builtins::DerivationError;
+use crate::known_paths::KnownPaths;
 use crate::tvix_store_io::TvixStoreIO;
 use bstr::BString;
 use nix_compat::derivation::{Derivation, Output};
@@ -19,7 +20,7 @@ const IGNORE_NULLS: &str = "__ignoreNulls";
 
 /// Populate the inputs of a derivation from the build references
 /// found when scanning the derivation's parameters and extracting their contexts.
-fn populate_inputs(drv: &mut Derivation, full_context: NixContext) {
+fn populate_inputs(drv: &mut Derivation, full_context: NixContext, known_paths: &KnownPaths) {
     for element in full_context.iter() {
         match element {
             NixContextElement::Plain(source) => {
@@ -57,12 +58,37 @@ fn populate_inputs(drv: &mut Derivation, full_context: NixContext) {
                 }
             }
 
-            NixContextElement::Derivation(_drv_path) => {
-                // This is a hard one, it means that
-                // we are depending on a drvPath of ourselves
-                // *or* another derivation's drvPath.
-                // What to do here?
-                panic!("please do not depend on drvPath, I have 2 hours of sleep in blood");
+            NixContextElement::Derivation(drv_path) => {
+                let (derivation, _rest) =
+                    StorePath::from_absolute_path_full(drv_path).expect("valid store path");
+
+                #[cfg(debug_assertions)]
+                assert!(
+                    _rest.iter().next().is_none(),
+                    "Extra path not empty for {}",
+                    drv_path
+                );
+
+                // We need to know all the outputs *names* of that derivation.
+                let output_names = known_paths
+                    .get_drv_by_drvpath(&derivation)
+                    .expect("no known derivation associated to that derivation path")
+                    .outputs
+                    .keys();
+
+                // FUTUREWORK(performance): ideally, we should be able to clone
+                // cheaply those outputs rather than duplicate them all around.
+                match drv.input_derivations.entry(derivation.clone()) {
+                    btree_map::Entry::Vacant(entry) => {
+                        entry.insert(output_names.cloned().collect());
+                    }
+
+                    btree_map::Entry::Occupied(mut entry) => {
+                        entry.get_mut().extend(output_names.cloned());
+                    }
+                }
+
+                drv.input_sources.insert(derivation);
             }
         }
     }
@@ -416,8 +442,8 @@ pub(crate) mod derivation_builtins {
             );
         }
 
-        populate_inputs(&mut drv, input_context);
         let mut known_paths = state.as_ref().known_paths.borrow_mut();
+        populate_inputs(&mut drv, input_context, &known_paths);
 
         // At this point, derivation fields are fully populated from
         // eval data structures.