feat(tvix/store/protos): add Deriver field to PathInfo

This uses the newly introduced StorePath message type to add a Deriver
field to the PathInfo message.

Support for validation is added to both the golang and rust
implementation. This includes extending unit tests.

Change-Id: Ifc3eb3263fa25b9eec260db354cd74234c40af7e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9647
Reviewed-by: Connor Brewster <cbrewster@hey.com>
Tested-by: BuildkiteCI
This commit is contained in:
Florian Klink 2023-10-11 00:22:40 +02:00 committed by flokli
parent 5f8eb4eeaa
commit 2d2c4322d9
10 changed files with 161 additions and 39 deletions

View file

@ -296,6 +296,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
signatures: vec![],
reference_names: vec![],
}),
deriver: None,
};
// put into [PathInfoService], and return the PathInfo that we get back

View file

@ -48,7 +48,7 @@ pub enum ValidatePathInfoError {
#[error("Inconsistent Number of References: {0} (references) vs {1} (narinfo)")]
InconsistentNumberOfReferences(usize, usize),
/// A string in narinfo.reference_names does not parse to a StorePath.
/// A string in narinfo.reference_names does not parse to a [store_path::StorePath].
#[error("Invalid reference_name at position {0}: {1}")]
InvalidNarinfoReferenceName(usize, String),
@ -60,6 +60,10 @@ pub enum ValidatePathInfoError {
[u8; store_path::DIGEST_SIZE],
[u8; store_path::DIGEST_SIZE],
),
/// The deriver field is invalid.
#[error("deriver field is invalid: {0}")]
InvalidDeriverField(store_path::Error),
}
/// Parses a root node name.
@ -152,6 +156,16 @@ impl PathInfo {
}
};
// If the Deriver field is populated, ensure it parses to a
// [store_path::StorePath].
// We can't check for it to *not* end with .drv, as the .drv files produced by
// recursive Nix end with multiple .drv suffixes, and only one is popped when
// converting to this field.
if let Some(deriver) = &self.deriver {
store_path::StorePath::from_name_and_digest(deriver.name.clone(), &deriver.digest)
.map_err(ValidatePathInfoError::InvalidDeriverField)?;
}
// return the root nix path
Ok(root_nix_path)
}

View file

@ -262,3 +262,34 @@ fn validate_symlink_target_null_byte_invalid() {
node.validate().expect_err("must fail validation");
}
/// Create a PathInfo with a correct deriver field and ensure it succeeds.
#[test]
fn validate_valid_deriver() {
let mut path_info = PATH_INFO_WITHOUT_NARINFO.clone();
// add a valid deriver
path_info.deriver = Some(crate::proto::StorePath {
name: "foo".to_string(),
digest: DUMMY_OUTPUT_HASH.clone(),
});
path_info.validate().expect("must validate");
}
/// Create a PathInfo with a broken deriver field and ensure it fails.
#[test]
fn validate_invalid_deriver() {
let mut path_info = PATH_INFO_WITHOUT_NARINFO.clone();
// add a broken deriver (invalid digest)
path_info.deriver = Some(crate::proto::StorePath {
name: "foo".to_string(),
digest: vec![].into(),
});
match path_info.validate().expect_err("must fail validation") {
ValidatePathInfoError::InvalidDeriverField(_) => {}
e => panic!("unexpected error: {:?}", e),
}
}

View file

@ -109,6 +109,7 @@ lazy_static! {
}),
references: vec![DUMMY_OUTPUT_HASH.clone()],
narinfo: None,
deriver: None,
};
/// A PathInfo message with .narinfo populated.