feat(tvix/store): add as_narinfo() for PathInfo
This allows seeing a PathInfo as a nix_compat::narinfo::NarInfo<'_>. It doesn't allocate any new data, but the NarInfo<'_> view allows us to access things like signature verification, or rendering out (alternations of this) as strings. Change-Id: Id0d8d7feeb626ee02c3d8a4932f24ace77022619 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10108 Reviewed-by: edef <edef@edef.eu> Autosubmit: flokli <flokli@flokli.de> Tested-by: BuildkiteCI
This commit is contained in:
parent
639cca3e22
commit
6b685ec4a5
2 changed files with 106 additions and 2 deletions
|
@ -3,8 +3,9 @@ use bytes::Bytes;
|
|||
use data_encoding::BASE64;
|
||||
// https://github.com/hyperium/tonic/issues/1056
|
||||
use nix_compat::{
|
||||
narinfo::Flags,
|
||||
nixhash::{CAHash, NixHash},
|
||||
store_path,
|
||||
store_path::{self, StorePathRef},
|
||||
};
|
||||
use thiserror::Error;
|
||||
use tvix_castore::proto::{self as castorepb, NamedNode, ValidateNodeError};
|
||||
|
@ -174,6 +175,67 @@ impl PathInfo {
|
|||
// return the root nix path
|
||||
Ok(root_nix_path)
|
||||
}
|
||||
|
||||
/// With self and a given StorePathRef, this reconstructs a
|
||||
/// [nix_compat::narinfo::NarInfo<'_>].
|
||||
/// It can be used to validate Signatures, or get back a (sparse) NarInfo
|
||||
/// struct to prepare writing it out.
|
||||
///
|
||||
/// This doesn't allocate any new data.
|
||||
///
|
||||
/// Keep in mind this is not able to reconstruct all data present in the
|
||||
/// NarInfo<'_>, as some of it is not stored at all:
|
||||
/// - the `system`, `file_hash` and `file_size` fields are set to `None`.
|
||||
/// - the URL is set to an empty string.
|
||||
/// - Compression is set to "none"
|
||||
///
|
||||
/// If you want to render it out to a string and be able to parse it back
|
||||
/// in, at least URL *must* be set again.
|
||||
pub fn as_narinfo<'a>(
|
||||
&'a self,
|
||||
store_path: store_path::StorePathRef<'a>,
|
||||
) -> Option<nix_compat::narinfo::NarInfo<'_>> {
|
||||
let narinfo = &self.narinfo.as_ref()?;
|
||||
|
||||
Some(nix_compat::narinfo::NarInfo {
|
||||
flags: Flags::empty(),
|
||||
store_path,
|
||||
nar_hash: narinfo.nar_sha256.to_vec().try_into().unwrap(),
|
||||
nar_size: narinfo.nar_size,
|
||||
references: narinfo
|
||||
.reference_names
|
||||
.iter()
|
||||
.map(|ref_name| {
|
||||
// This shouldn't pass validation
|
||||
StorePathRef::from_bytes(ref_name.as_bytes()).expect("invalid reference")
|
||||
})
|
||||
.collect(),
|
||||
signatures: narinfo
|
||||
.signatures
|
||||
.iter()
|
||||
.map(|sig| {
|
||||
nix_compat::narinfo::Signature::new(
|
||||
&sig.name,
|
||||
// This shouldn't pass validation
|
||||
sig.data[..].try_into().expect("invalid signature len"),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
ca: narinfo
|
||||
.ca
|
||||
.as_ref()
|
||||
.map(|ca| ca.try_into().expect("invalid ca")),
|
||||
system: None,
|
||||
deriver: narinfo.deriver.as_ref().map(|deriver| {
|
||||
StorePathRef::from_name_and_digest(&deriver.name, &deriver.digest)
|
||||
.expect("invalid deriver")
|
||||
}),
|
||||
url: "",
|
||||
compression: Some("none"),
|
||||
file_hash: None,
|
||||
file_size: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors that can occur when converting from a [&nar_info::Ca] to a (stricter)
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::tests::fixtures::*;
|
|||
use bytes::Bytes;
|
||||
use data_encoding::BASE64;
|
||||
use nix_compat::nixbase32;
|
||||
use nix_compat::store_path::{self, StorePath};
|
||||
use nix_compat::store_path::{self, StorePath, StorePathRef};
|
||||
use std::str::FromStr;
|
||||
use test_case::test_case;
|
||||
use tvix_castore::proto as castorepb;
|
||||
|
@ -404,3 +404,45 @@ CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd"#
|
|||
(&narinfo_parsed).into()
|
||||
);
|
||||
}
|
||||
|
||||
/// Exercise .as_narinfo() on a PathInfo and ensure important fields are preserved..
|
||||
#[test]
|
||||
fn as_narinfo() {
|
||||
let narinfo_parsed = nix_compat::narinfo::NarInfo::parse(
|
||||
r#"StorePath: /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz
|
||||
URL: nar/1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r.nar.xz
|
||||
Compression: xz
|
||||
FileHash: sha256:1zjrhzhaizsrlsvdkqfl073vivmxcqnzkff4s50i0cdf541ary1r
|
||||
FileSize: 1033524
|
||||
NarHash: sha256:1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh
|
||||
NarSize: 1033416
|
||||
References:
|
||||
Deriver: dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv
|
||||
Sig: cache.nixos.org-1:ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg==
|
||||
CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd"#
|
||||
).expect("must parse");
|
||||
|
||||
let path_info: PathInfo = (&narinfo_parsed).into();
|
||||
|
||||
let mut narinfo_returned = path_info
|
||||
.as_narinfo(
|
||||
StorePathRef::from_bytes(b"pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz")
|
||||
.expect("invalid storepath"),
|
||||
)
|
||||
.expect("must be some");
|
||||
narinfo_returned.url = "some.nar";
|
||||
|
||||
assert_eq!(
|
||||
r#"StorePath: /nix/store/pa10z4ngm0g83kx9mssrqzz30s84vq7k-hello-2.12.1.tar.gz
|
||||
URL: some.nar
|
||||
Compression: none
|
||||
NarHash: sha256:1lvqpbk2k1sb39z8jfxixf7p7v8sj4z6mmpa44nnmff3w1y6h8lh
|
||||
NarSize: 1033416
|
||||
References:
|
||||
Deriver: dyivpmlaq2km6c11i0s6bi6mbsx0ylqf-hello-2.12.1.tar.gz.drv
|
||||
Sig: cache.nixos.org-1:ywnIG629nQZQhEr6/HLDrLT/mUEp5J1LC6NmWSlJRWL/nM7oGItJQUYWGLvYGhSQvHrhIuvMpjNmBNh/WWqCDg==
|
||||
CA: fixed:sha256:086vqwk2wl8zfs47sq2xpjc9k066ilmb8z6dn0q6ymwjzlm196cd
|
||||
"#,
|
||||
narinfo_returned.to_string(),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue