feat(tvix/nix-compat): input_sources as StorePath

https: //b.tvl.fyi/issues/264
Change-Id: I7a235734dc1f8e93e387a04ba369f3b702c6d5b6
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10992
Autosubmit: Peter Kolloch <info@eigenvalue.net>
Reviewed-by: flokli <flokli@flokli.de>
Reviewed-by: Peter Kolloch <info@eigenvalue.net>
Tested-by: BuildkiteCI
This commit is contained in:
Peter Kolloch 2024-02-21 14:07:37 +07:00 committed by clbot
parent c06fb01b3b
commit 035f617b7f
6 changed files with 53 additions and 31 deletions

View file

@ -4,7 +4,7 @@ use crate::tvix_store_io::TvixStoreIO;
use bstr::BString;
use nix_compat::derivation::{Derivation, Output};
use nix_compat::nixhash;
use nix_compat::store_path::StorePath;
use nix_compat::store_path::{StorePath, StorePathRef};
use std::collections::{btree_map, BTreeSet};
use std::rc::Rc;
use tvix_eval::builtin_macros::builtins;
@ -24,7 +24,10 @@ fn populate_inputs(drv: &mut Derivation, full_context: NixContext) {
for element in full_context.iter() {
match element {
NixContextElement::Plain(source) => {
drv.input_sources.insert(source.clone());
let sp = StorePathRef::from_absolute_path(source.as_bytes())
.expect("invalid store path")
.to_owned();
drv.input_sources.insert(sp);
}
NixContextElement::Single {

View file

@ -40,7 +40,7 @@ pub struct Derivation {
/// Plain store paths of additional inputs.
#[serde(rename = "inputSrcs")]
pub input_sources: BTreeSet<String>,
pub input_sources: BTreeSet<StorePath>,
/// Maps output names to Output.
pub outputs: BTreeMap<String, Output>,
@ -131,16 +131,12 @@ impl Derivation {
// collect the list of paths from input_sources and input_derivations
// into a (sorted, guaranteed by BTreeSet) list of references
let references: BTreeSet<String> = {
let mut inputs = self.input_sources.clone();
let input_derivation_keys: Vec<String> = self
.input_derivations
.keys()
.map(|k| k.to_absolute_path())
.collect();
inputs.extend(input_derivation_keys);
inputs
};
let references: BTreeSet<String> = self
.input_sources
.iter()
.chain(self.input_derivations.keys())
.map(StorePath::to_absolute_path)
.collect();
build_text_path(name, self.to_aterm_bytes(), references)
.map(|s| s.to_owned())

View file

@ -2,7 +2,10 @@
//! Derivations from ATerm.
use nom::IResult;
use crate::{nixhash, store_path};
use crate::{
nixhash,
store_path::{self, StorePath},
};
pub type NomResult<I, O> = IResult<I, O, NomError<I>>;
@ -17,7 +20,7 @@ pub enum ErrorKind {
DuplicateInputDerivationOutputName(String, String),
#[error("duplicate input source: {0}")]
DuplicateInputSource(String),
DuplicateInputSource(StorePath),
#[error("nix hash error: {0}")]
NixHashError(nixhash::Error),

View file

@ -186,11 +186,19 @@ fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTr
Ok((i, input_derivations))
}
fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<String>> {
fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath>> {
let (i, input_sources_lst) = aterm::parse_str_list(i).map_err(into_nomerror)?;
let mut input_sources: BTreeSet<_> = BTreeSet::new();
for input_source in input_sources_lst.into_iter() {
let input_source: StorePath = StorePathRef::from_absolute_path(input_source.as_bytes())
.map_err(|e: store_path::Error| {
nom::Err::Failure(NomError {
input: i,
code: e.into(),
})
})?
.to_owned();
if input_sources.contains(&input_source) {
return Err(nom::Err::Failure(NomError {
input: i,
@ -312,6 +320,7 @@ where
#[cfg(test)]
mod tests {
use crate::store_path::StorePathRef;
use std::collections::{BTreeMap, BTreeSet};
use crate::{
@ -460,7 +469,14 @@ mod tests {
fn parse_input_sources(input: &'static [u8], expected: &BTreeSet<String>) {
let (rest, parsed) = super::parse_input_sources(input).expect("must parse");
assert_eq!(expected, &parsed, "parsed mismatch");
assert_eq!(
expected,
&parsed
.iter()
.map(StorePath::to_absolute_path)
.collect::<BTreeSet<_>>(),
"parsed mismatch"
);
assert!(rest.is_empty(), "rest must be empty");
}
@ -474,7 +490,11 @@ mod tests {
nom::Err::Failure(e) => {
assert_eq!(
ErrorKind::DuplicateInputSource(
"/nix/store/55lwldka5nyxa08wnvlizyqw02ihy8ic-foo".to_string()
StorePathRef::from_absolute_path(
"/nix/store/55lwldka5nyxa08wnvlizyqw02ihy8ic-foo".as_bytes()
)
.unwrap()
.to_owned()
),
e.code
);

View file

@ -1,5 +1,5 @@
use crate::derivation::{Derivation, DerivationError};
use crate::store_path::{self, StorePathRef};
use crate::store_path;
impl Derivation {
/// validate ensures a Derivation struct is properly populated,
@ -87,16 +87,6 @@ impl Derivation {
}
}
// Validate all input_sources
for input_source in self.input_sources.iter() {
if let Err(e) = StorePathRef::from_absolute_path(input_source.as_bytes()) {
return Err(DerivationError::InvalidInputSourcesPath(
input_source.to_string(),
e,
));
}
}
// validate platform
if self.system.is_empty() {
return Err(DerivationError::InvalidPlatform(self.system.to_string()));

View file

@ -33,6 +33,13 @@ pub const QUOTE: char = '"';
/// the context a lot.
pub(crate) trait AtermWriteable: Display {
fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()>;
fn aterm_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
self.aterm_write(&mut bytes)
.expect("unexpected write errors to Vec");
bytes
}
}
impl AtermWriteable for StorePathRef<'_> {
@ -182,12 +189,15 @@ pub(crate) fn write_input_derivations(
pub(crate) fn write_input_sources(
writer: &mut impl Write,
input_sources: &BTreeSet<String>,
input_sources: &BTreeSet<StorePath>,
) -> Result<(), io::Error> {
write_char(writer, BRACKET_OPEN)?;
write_array_elements(
writer,
&input_sources.iter().map(String::from).collect::<Vec<_>>(),
&input_sources
.iter()
.map(StorePath::to_absolute_path)
.collect::<Vec<_>>(),
)?;
write_char(writer, BRACKET_CLOSE)?;