From 94185f75604aca63c3d0e09a42503610f1dd822d Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Mon, 25 Mar 2024 00:59:41 +0100 Subject: feat(tvix/eval): support `Derivation` context elements 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 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11261 Reviewed-by: flokli Tested-by: BuildkiteCI --- tvix/glue/src/builtins/derivation.rs | 42 +++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) (limited to 'tvix/glue/src') 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. -- cgit 1.4.1