From fdca93d6edc88a5979c536bf26553bdfc1f037b5 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 23 Jan 2023 01:12:59 +0300 Subject: feat(tvix/cli): add helper for populating derivation inputs This adds a helper function which takes the output of the reference scanner used on derivation inputs and populates the `input_sources` and `input_derivations` field of the derivation accordingly. Note that we have a divergence from C++ Nix here, as we do not populate the entire FS closure of a literally referred derivation (and our standing theory is that this is unnecessary for nixpkgs). Change-Id: Id0f605dd8c0a82973c56605c2b8f478fc17777d6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7899 Tested-by: BuildkiteCI Reviewed-by: flokli --- tvix/cli/src/derivation.rs | 89 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'tvix/cli/src/derivation.rs') diff --git a/tvix/cli/src/derivation.rs b/tvix/cli/src/derivation.rs index ad8fec226b..2d951f7ae6 100644 --- a/tvix/cli/src/derivation.rs +++ b/tvix/cli/src/derivation.rs @@ -1,9 +1,11 @@ //! Implements `builtins.derivation`, the core of what makes Nix build packages. +use std::collections::{btree_map, BTreeSet}; use tvix_derivation::Derivation; use tvix_eval::{AddContext, ErrorKind, NixList, VM}; use crate::errors::Error; +use crate::known_paths::{KnownPaths, PathType}; /// Helper function for populating the `drv.outputs` field from a /// manually specified set of outputs, instead of the default @@ -30,6 +32,46 @@ fn populate_outputs(vm: &mut VM, drv: &mut Derivation, outputs: NixList) -> Resu Ok(()) } +/// Populate the inputs of a derivation from the build references +/// found when scanning the derivation's parameters. +fn populate_inputs>( + drv: &mut Derivation, + known_paths: &KnownPaths, + references: I, +) { + for reference in references.into_iter() { + match &known_paths[&reference] { + PathType::Plain => { + drv.input_sources.insert(reference.to_string()); + } + + PathType::Output { name, derivation } => { + match drv.input_derivations.entry(derivation.clone()) { + btree_map::Entry::Vacant(entry) => { + entry.insert(BTreeSet::from([name.clone()])); + } + + btree_map::Entry::Occupied(mut entry) => { + entry.get_mut().insert(name.clone()); + } + } + } + + PathType::Derivation { output_names } => { + match drv.input_derivations.entry(reference.to_string()) { + btree_map::Entry::Vacant(entry) => { + entry.insert(output_names.clone()); + } + + btree_map::Entry::Occupied(mut entry) => { + entry.get_mut().extend(output_names.clone().into_iter()); + } + } + } + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -85,4 +127,51 @@ mod tests { populate_outputs(&mut vm, &mut drv, outputs) .expect_err("supplying duplicate outputs should fail"); } + + #[test] + fn populate_inputs_empty() { + let mut drv = Derivation::default(); + let paths = KnownPaths::default(); + let inputs = vec![]; + + populate_inputs(&mut drv, &paths, inputs); + + assert!(drv.input_sources.is_empty()); + assert!(drv.input_derivations.is_empty()); + } + + #[test] + fn populate_inputs_all() { + let mut drv = Derivation::default(); + + let mut paths = KnownPaths::default(); + paths.plain("/nix/store/fn7zvafq26f0c8b17brs7s95s10ibfzs-foo"); + paths.drv( + "/nix/store/aqffiyqx602lbam7n1zsaz3yrh6v08pc-bar.drv", + &["out"], + ); + paths.output( + "/nix/store/zvpskvjwi72fjxg0vzq822sfvq20mq4l-bar", + "out", + "/nix/store/aqffiyqx602lbam7n1zsaz3yrh6v08pc-bar.drv", + ); + + let inputs: Vec = vec![ + "/nix/store/fn7zvafq26f0c8b17brs7s95s10ibfzs-foo".into(), + "/nix/store/aqffiyqx602lbam7n1zsaz3yrh6v08pc-bar.drv".into(), + "/nix/store/zvpskvjwi72fjxg0vzq822sfvq20mq4l-bar".into(), + ]; + + populate_inputs(&mut drv, &paths, inputs); + + assert_eq!(drv.input_sources.len(), 1); + assert!(drv + .input_sources + .contains("/nix/store/fn7zvafq26f0c8b17brs7s95s10ibfzs-foo")); + + assert_eq!(drv.input_derivations.len(), 1); + assert!(drv + .input_derivations + .contains_key("/nix/store/aqffiyqx602lbam7n1zsaz3yrh6v08pc-bar.drv")); + } } -- cgit 1.4.1