about summary refs log tree commit diff
path: root/tvix/nix-compat
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-12-21T14·29+0200
committerclbot <clbot@tvl.fyi>2023-12-21T16·28+0000
commit9065089b0c4b16237cacf7c0878779cffb7f520f (patch)
treed7a210dce95aa47cabf759cefea675d81b4ccc3a /tvix/nix-compat
parentea8fdb9304f17beb6d967ddaf8913512732e3432 (diff)
refactor(tvix/nix-compat): have helpers interact with StorePathRef r/7236
In most case, we don't actually need an owned `StorePath` struct, but a
`StorePathRef<'_>` is sufficient. The lifetime is only due to it holding
onto the name, but that one is mostly left untouched.

`Derivation::calculate_derivation_path` still needs to return
`StorePath`, as its name has a `.drv` appended.

Change-Id: Ie0d52f369d785711bb0658ea2b0bd2617fd9f45e
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10389
Autosubmit: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Reviewed-by: edef <edef@edef.eu>
Diffstat (limited to 'tvix/nix-compat')
-rw-r--r--tvix/nix-compat/src/derivation/mod.rs1
-rw-r--r--tvix/nix-compat/src/store_path/utils.rs44
2 files changed, 23 insertions, 22 deletions
diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs
index d62a339b77a9..b3f3adc55ba2 100644
--- a/tvix/nix-compat/src/derivation/mod.rs
+++ b/tvix/nix-compat/src/derivation/mod.rs
@@ -115,6 +115,7 @@ impl Derivation {
         };
 
         build_text_path(name, self.to_aterm_bytes(), references)
+            .map(|s| s.to_owned())
             .map_err(|_e| DerivationError::InvalidOutputName(name.to_string()))
     }
 
diff --git a/tvix/nix-compat/src/store_path/utils.rs b/tvix/nix-compat/src/store_path/utils.rs
index dd32135135db..50a1d98240b3 100644
--- a/tvix/nix-compat/src/store_path/utils.rs
+++ b/tvix/nix-compat/src/store_path/utils.rs
@@ -1,6 +1,6 @@
 use crate::nixbase32;
 use crate::nixhash::{CAHash, NixHash};
-use crate::store_path::{Error, StorePath, STORE_DIR};
+use crate::store_path::{Error, StorePathRef, DIGEST_SIZE, STORE_DIR};
 use sha2::{Digest, Sha256};
 use std::io::Write;
 use thiserror;
@@ -47,7 +47,7 @@ pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>>
     name: &str,
     content: C,
     references: I,
-) -> Result<StorePath, BuildStorePathError> {
+) -> Result<StorePathRef<'_>, BuildStorePathError> {
     // produce the sha256 digest of the contents
     let content_digest = Sha256::new_with_prefix(content).finalize().into();
 
@@ -55,12 +55,12 @@ pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>>
 }
 
 /// This builds a store path from a [CAHash] and a list of references.
-pub fn build_ca_path<B: AsRef<[u8]>, S: AsRef<str>, I: IntoIterator<Item = S>>(
-    name: B,
+pub fn build_ca_path<'a, S: AsRef<str>, I: IntoIterator<Item = S>>(
+    name: &'a str,
     ca_hash: &CAHash,
     references: I,
     self_reference: bool,
-) -> Result<StorePath, BuildStorePathError> {
+) -> Result<StorePathRef<'a>, BuildStorePathError> {
     match &ca_hash {
         CAHash::Text(ref digest) => {
             if self_reference {
@@ -71,14 +71,12 @@ pub fn build_ca_path<B: AsRef<[u8]>, S: AsRef<str>, I: IntoIterator<Item = S>>(
                 &NixHash::Sha256(*digest),
                 name,
             )
-            .map_err(BuildStorePathError::InvalidStorePath)
         }
         CAHash::Nar(ref hash @ NixHash::Sha256(_)) => build_store_path_from_fingerprint_parts(
             &make_references_string("source", references, self_reference),
             hash,
             name,
-        )
-        .map_err(BuildStorePathError::InvalidStorePath),
+        ),
         // for all other CAHash::Nar, another custom scheme is used.
         CAHash::Nar(ref hash) => {
             if references.into_iter().next().is_some() {
@@ -101,7 +99,6 @@ pub fn build_ca_path<B: AsRef<[u8]>, S: AsRef<str>, I: IntoIterator<Item = S>>(
                 },
                 name,
             )
-            .map_err(BuildStorePathError::InvalidStorePath)
         }
         // CaHash::Flat is using something very similar, except the `r:` prefix.
         CAHash::Flat(ref hash) => {
@@ -122,13 +119,17 @@ pub fn build_ca_path<B: AsRef<[u8]>, S: AsRef<str>, I: IntoIterator<Item = S>>(
                 },
                 name,
             )
-            .map_err(BuildStorePathError::InvalidStorePath)
         }
     }
+    .map_err(BuildStorePathError::InvalidStorePath)
 }
 
-/// For given NAR sha256 digest and name, return the new [StorePath] this would have.
-pub fn build_nar_based_store_path(nar_sha256_digest: &[u8; 32], name: &str) -> StorePath {
+/// For given NAR sha256 digest and name, return the new [StorePathRef] this
+/// would have.
+pub fn build_nar_based_store_path<'a>(
+    nar_sha256_digest: &[u8; 32],
+    name: &'a str,
+) -> StorePathRef<'a> {
     let nar_hash_with_mode = CAHash::Nar(NixHash::Sha256(nar_sha256_digest.to_owned()));
 
     build_ca_path(name, &nar_hash_with_mode, Vec::<String>::new(), false).unwrap()
@@ -138,11 +139,11 @@ pub fn build_nar_based_store_path(nar_sha256_digest: &[u8; 32], name: &str) -> S
 ///
 /// Input-addresed store paths are always derivation outputs, the "input" in question is the
 /// derivation and its closure.
-pub fn build_output_path(
+pub fn build_output_path<'a>(
     drv_hash: &NixHash,
     output_name: &str,
-    output_path_name: &str,
-) -> Result<StorePath, Error> {
+    output_path_name: &'a str,
+) -> Result<StorePathRef<'a>, Error> {
     build_store_path_from_fingerprint_parts(
         &(String::from("output:") + output_name),
         drv_hash,
@@ -158,20 +159,19 @@ pub fn build_output_path(
 ///
 /// The fingerprint is hashed with sha256, its digest is compressed to 20 bytes,
 /// and nixbase32-encoded (32 characters).
-fn build_store_path_from_fingerprint_parts<B: AsRef<[u8]>>(
+fn build_store_path_from_fingerprint_parts<'a>(
     ty: &str,
     hash: &NixHash,
-    name: B,
-) -> Result<StorePath, Error> {
-    let name = super::validate_name(&name)?.to_owned();
-
-    let digest = compress_hash(&{
+    name: &'a str,
+) -> Result<StorePathRef<'a>, Error> {
+    let digest: [u8; DIGEST_SIZE] = compress_hash(&{
         let mut h = Sha256::new();
         write!(h, "{ty}:{}:{STORE_DIR}:{name}", hash.to_nix_hex_string()).unwrap();
         h.finalize()
     });
 
-    Ok(StorePath { digest, name })
+    // name validation happens in here.
+    StorePathRef::from_name_and_digest(name, &digest)
 }
 
 /// This contains the Nix logic to create "text hash strings", which are used