about summary refs log tree commit diff
path: root/tvix/store/src
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-10-10T22·22+0200
committerflokli <flokli@flokli.de>2023-10-14T13·23+0000
commit2d2c4322d93308ddffe1647466abd91025af6a68 (patch)
tree37ead8574df6eb98d76ca95636b50bf8fe1945cb /tvix/store/src
parent5f8eb4eeaaad31aedc45efee3143e6b0bbc982a4 (diff)
feat(tvix/store/protos): add Deriver field to PathInfo r/6805
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
Diffstat (limited to 'tvix/store/src')
-rw-r--r--tvix/store/src/bin/tvix-store.rs1
-rw-r--r--tvix/store/src/proto/mod.rs16
-rw-r--r--tvix/store/src/proto/tests/pathinfo.rs31
-rw-r--r--tvix/store/src/tests/fixtures.rs1
4 files changed, 48 insertions, 1 deletions
diff --git a/tvix/store/src/bin/tvix-store.rs b/tvix/store/src/bin/tvix-store.rs
index 11f19857dd6f..2f7589b07356 100644
--- a/tvix/store/src/bin/tvix-store.rs
+++ b/tvix/store/src/bin/tvix-store.rs
@@ -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
diff --git a/tvix/store/src/proto/mod.rs b/tvix/store/src/proto/mod.rs
index 718e24912de1..4ebd4a31908f 100644
--- a/tvix/store/src/proto/mod.rs
+++ b/tvix/store/src/proto/mod.rs
@@ -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)
     }
diff --git a/tvix/store/src/proto/tests/pathinfo.rs b/tvix/store/src/proto/tests/pathinfo.rs
index 5e1ae9c45b64..03094ed734ce 100644
--- a/tvix/store/src/proto/tests/pathinfo.rs
+++ b/tvix/store/src/proto/tests/pathinfo.rs
@@ -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),
+    }
+}
diff --git a/tvix/store/src/tests/fixtures.rs b/tvix/store/src/tests/fixtures.rs
index f0d0f35378cf..5290581688e6 100644
--- a/tvix/store/src/tests/fixtures.rs
+++ b/tvix/store/src/tests/fixtures.rs
@@ -109,6 +109,7 @@ lazy_static! {
         }),
         references: vec![DUMMY_OUTPUT_HASH.clone()],
         narinfo: None,
+        deriver: None,
     };
 
     /// A PathInfo message with .narinfo populated.