feat(tvix/cli): implement builtins.placeholder

This doesn't require any other corresponding handling *yet*, as the
actual replacements happen in the builder logic (which we delegate to
cppnix at the moment).

Change-Id: I034147c933f05ae427c7a8794647132d108d0ede
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7972
Autosubmit: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
Vincent Ambo 2023-01-31 19:43:33 +03:00 committed by clbot
parent 3caa4c4aa4
commit 759f9dbf39
2 changed files with 44 additions and 0 deletions

View file

@ -2,6 +2,7 @@
use data_encoding::BASE64;
use nix_compat::derivation::{Derivation, Hash};
use nix_compat::hash_placeholder;
use std::cell::RefCell;
use std::collections::{btree_map, BTreeSet};
use std::rc::Rc;
@ -250,6 +251,18 @@ fn strong_coerce_to_string(vm: &mut VM, val: &Value, ctx: &str) -> Result<String
mod derivation_builtins {
use super::*;
#[builtin("placeholder")]
fn builtin_placeholder(_: &mut VM, input: Value) -> Result<Value, ErrorKind> {
let placeholder = hash_placeholder(
input
.to_str()
.context("looking at output name in builtins.placeholder")?
.as_str(),
);
Ok(placeholder.into())
}
/// Strictly construct a Nix derivation from the supplied arguments.
///
/// This is considered an internal function, users usually want to
@ -677,4 +690,17 @@ mod tests {
vec!["--foo".to_string(), "42".to_string(), "--bar".to_string()]
);
}
#[test]
fn builtins_placeholder_hashes() {
assert_eq!(
hash_placeholder("out").as_str(),
"/1rz4g4znpzjwh1xymhjpm42vipw92pr73vdgl6xs1hycac8kf2n9"
);
assert_eq!(
hash_placeholder("").as_str(),
"/171rf4jhx57xqz3p7swniwkig249cif71pa08p80mgaf0mqz5bmr"
);
}
}

View file

@ -1,4 +1,22 @@
use sha2::{Digest, Sha256};
pub mod derivation;
pub mod nar;
pub mod nixbase32;
pub mod store_path;
/// Nix placeholders (i.e. values returned by `builtins.placeholder`)
/// are used to populate outputs with paths that must be
/// string-replaced with the actual placeholders later, at runtime.
///
/// The actual placeholder is basically just a SHA256 hash encoded in
/// cppnix format.
pub fn hash_placeholder(name: &str) -> String {
let digest = {
let mut hasher = Sha256::new();
hasher.update(format!("nix-output:{}", name));
hasher.finalize()
};
format!("/{}", nixbase32::encode(&digest))
}