feat(tvix/cli): add helper for populating drv output configuration
This threads through the fields that control whether a derivation is a fixed-output derivation or not. Change-Id: I49739de178fed9f258291174ca1a2c15a7cf5c2a Reviewed-on: https://cl.tvl.fyi/c/depot/+/7900 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
parent
fdca93d6ed
commit
dfc50c9ef5
2 changed files with 125 additions and 2 deletions
|
@ -1,8 +1,8 @@
|
|||
//! 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 tvix_derivation::{Derivation, Hash};
|
||||
use tvix_eval::{AddContext, CoercionKind, ErrorKind, NixList, Value, VM};
|
||||
|
||||
use crate::errors::Error;
|
||||
use crate::known_paths::{KnownPaths, PathType};
|
||||
|
@ -72,6 +72,65 @@ fn populate_inputs<I: IntoIterator<Item = String>>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Populate the output configuration of a derivation based on the
|
||||
/// parameters passed to the call, flipping the required
|
||||
/// parameters for a fixed-output derivation if necessary.
|
||||
///
|
||||
/// This function handles all possible combinations of the
|
||||
/// parameters, including invalid ones.
|
||||
fn populate_output_configuration(
|
||||
drv: &mut Derivation,
|
||||
vm: &mut VM,
|
||||
hash: Option<&Value>, // in nix: outputHash
|
||||
hash_algo: Option<&Value>, // in nix: outputHashAlgo
|
||||
hash_mode: Option<&Value>, // in nix: outputHashmode
|
||||
) -> Result<(), ErrorKind> {
|
||||
match (hash, hash_algo, hash_mode) {
|
||||
(Some(hash), Some(algo), hash_mode) => match drv.outputs.get_mut("out") {
|
||||
None => return Err(Error::ConflictingOutputTypes.into()),
|
||||
Some(out) => {
|
||||
let algo = algo
|
||||
.force(vm)?
|
||||
.coerce_to_string(CoercionKind::Strong, vm)?
|
||||
.as_str()
|
||||
.to_string();
|
||||
|
||||
let hash_mode = match hash_mode {
|
||||
None => None,
|
||||
Some(mode) => Some(
|
||||
mode.force(vm)?
|
||||
.coerce_to_string(CoercionKind::Strong, vm)?
|
||||
.as_str()
|
||||
.to_string(),
|
||||
),
|
||||
};
|
||||
|
||||
let algo = match hash_mode.as_deref() {
|
||||
None | Some("flat") => algo,
|
||||
Some("recursive") => format!("r:{}", algo),
|
||||
Some(other) => {
|
||||
return Err(Error::InvalidOutputHashMode(other.to_string()).into())
|
||||
}
|
||||
};
|
||||
|
||||
out.hash = Some(Hash {
|
||||
algo,
|
||||
|
||||
digest: hash
|
||||
.force(vm)?
|
||||
.coerce_to_string(CoercionKind::Strong, vm)?
|
||||
.as_str()
|
||||
.to_string(),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -174,4 +233,62 @@ mod tests {
|
|||
.input_derivations
|
||||
.contains_key("/nix/store/aqffiyqx602lbam7n1zsaz3yrh6v08pc-bar.drv"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn populate_output_config_std() {
|
||||
let mut vm = fake_vm();
|
||||
let mut drv = Derivation::default();
|
||||
|
||||
populate_output_configuration(&mut drv, &mut vm, None, None, None)
|
||||
.expect("populate_output_configuration() should succeed");
|
||||
|
||||
assert_eq!(drv, Derivation::default(), "derivation should be unchanged");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn populate_output_config_fod() {
|
||||
let mut vm = fake_vm();
|
||||
let mut drv = Derivation::default();
|
||||
drv.outputs.insert("out".to_string(), Default::default());
|
||||
|
||||
let hash = Value::String(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000".into(),
|
||||
);
|
||||
|
||||
let algo = Value::String("sha256".into());
|
||||
|
||||
populate_output_configuration(&mut drv, &mut vm, Some(&hash), Some(&algo), None)
|
||||
.expect("populate_output_configuration() should succeed");
|
||||
|
||||
let expected = Hash {
|
||||
algo: "sha256".into(),
|
||||
digest: "0000000000000000000000000000000000000000000000000000000000000000".into(),
|
||||
};
|
||||
|
||||
assert_eq!(drv.outputs["out"].hash, Some(expected));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn populate_output_config_fod_recursive() {
|
||||
let mut vm = fake_vm();
|
||||
let mut drv = Derivation::default();
|
||||
drv.outputs.insert("out".to_string(), Default::default());
|
||||
|
||||
let hash = Value::String(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000".into(),
|
||||
);
|
||||
|
||||
let algo = Value::String("sha256".into());
|
||||
let mode = Value::String("recursive".into());
|
||||
|
||||
populate_output_configuration(&mut drv, &mut vm, Some(&hash), Some(&algo), Some(&mode))
|
||||
.expect("populate_output_configuration() should succeed");
|
||||
|
||||
let expected = Hash {
|
||||
algo: "r:sha256".into(),
|
||||
digest: "0000000000000000000000000000000000000000000000000000000000000000".into(),
|
||||
};
|
||||
|
||||
assert_eq!(drv.outputs["out"].hash, Some(expected));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ pub enum Error {
|
|||
DuplicateEnvVar(String),
|
||||
ShadowedOutput(String),
|
||||
InvalidDerivation(DerivationError),
|
||||
InvalidOutputHashMode(String),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
|
@ -32,6 +33,11 @@ impl Display for Error {
|
|||
"the environment variable '{name}' shadows the name of an output"
|
||||
),
|
||||
Error::InvalidDerivation(error) => write!(f, "invalid derivation parameters: {error}"),
|
||||
|
||||
Error::InvalidOutputHashMode(mode) => write!(
|
||||
f,
|
||||
"invalid output hash mode: '{mode}', only 'recursive' and 'flat` are supported"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue