about summary refs log tree commit diff
path: root/tvix/nix-compat/src/derivation
diff options
context:
space:
mode:
authorPeter Kolloch <info@eigenvalue.net>2024-02-17T05·15+0700
committerclbot <clbot@tvl.fyi>2024-02-17T07·30+0000
commit48d4d10bacdf2843f0a59711c872062348208a37 (patch)
tree02bfcd254f7f15f6c8ac878a23a81769f0b2bd2c /tvix/nix-compat/src/derivation
parenta9f5bb859fa23e9b00621df2cd725a1b0f1bd4d8 (diff)
refactor(tvix/nix-compat): derivation_or_fod_hash w/o self.clone() r/7538
Instead of constructing a completely new derivation for hashing,
allow to call hashing with substituted input_derivations.

This

1. reduces the number of allocations,
2. prepares substituting `String`s for store paths with proper `StorePath`s without needing a separate derivation struct that allows hashes without `/nix/store` in input_derivations, and
3. keeps the change local to the `Derivation` implementation.

Change-Id: I36732c78f98fc59f0925b65823773222782017b0
Reviewed-on: https://cl.tvl.fyi/c/depot/+/10935
Tested-by: BuildkiteCI
Reviewed-by: flokli <flokli@flokli.de>
Autosubmit: Peter Kolloch <info@eigenvalue.net>
Diffstat (limited to 'tvix/nix-compat/src/derivation')
-rw-r--r--tvix/nix-compat/src/derivation/mod.rs58
1 files changed, 36 insertions, 22 deletions
diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs
index b876a215a22f..4d27bbb26d66 100644
--- a/tvix/nix-compat/src/derivation/mod.rs
+++ b/tvix/nix-compat/src/derivation/mod.rs
@@ -51,6 +51,15 @@ impl Derivation {
     ///
     /// The only errors returns are these when writing to the passed writer.
     pub fn serialize(&self, writer: &mut impl std::io::Write) -> Result<(), io::Error> {
+        self.serialize_with_replacements(writer, &self.input_derivations)
+    }
+
+    /// Like `serialize` but allow replacing the input_derivations for hash calculations.
+    fn serialize_with_replacements(
+        &self,
+        writer: &mut impl std::io::Write,
+        input_derivations: &BTreeMap<String, BTreeSet<String>>,
+    ) -> Result<(), io::Error> {
         use write::*;
 
         writer.write_all(write::DERIVATION_PREFIX.as_bytes())?;
@@ -59,7 +68,7 @@ impl Derivation {
         write_outputs(writer, &self.outputs)?;
         write_char(writer, COMMA)?;
 
-        write_input_derivations(writer, &self.input_derivations)?;
+        write_input_derivations(writer, input_derivations)?;
         write_char(writer, COMMA)?;
 
         write_input_sources(writer, &self.input_sources)?;
@@ -83,12 +92,21 @@ impl Derivation {
 
     /// return the ATerm serialization.
     pub fn to_aterm_bytes(&self) -> Vec<u8> {
+        self.to_aterm_bytes_with_replacements(&self.input_derivations)
+    }
+
+    /// Like `to_aterm_bytes` but allow input_derivation replacements for hashing.
+    fn to_aterm_bytes_with_replacements(
+        &self,
+        input_derivations: &BTreeMap<String, BTreeSet<String>>,
+    ) -> Vec<u8> {
         let mut buffer: Vec<u8> = Vec::new();
 
         // invoke serialize and write to the buffer.
         // Note we only propagate errors writing to the writer in serialize,
         // which won't panic for the string we write to.
-        self.serialize(&mut buffer).unwrap();
+        self.serialize_with_replacements(&mut buffer, input_derivations)
+            .unwrap();
 
         buffer
     }
@@ -175,29 +193,25 @@ impl Derivation {
         // call to this function.
         // We use fn_get_derivation_or_fod_hash here, so callers can precompute this.
         NixHash::Sha256(self.fod_digest().unwrap_or({
-            // construct a new Derivation struct with input derivation strings replaced.
-            let replaced_derivation = Derivation {
-                // For each input_derivation, look up the
-                // derivation_or_fod_hash, and replace the derivation path with
-                // it's HEXLOWER digest.
-                input_derivations: BTreeMap::from_iter(self.input_derivations.iter().map(
-                    |(drv_path_str, output_names)| {
-                        // parse drv_path to StorePathRef
-                        let drv_path = StorePathRef::from_absolute_path(drv_path_str.as_bytes())
-                            .expect("invalid input derivation path");
-
-                        let encoded_hash = data_encoding::HEXLOWER
-                            .encode(fn_get_derivation_or_fod_hash(&drv_path).digest_as_bytes());
-
-                        (encoded_hash, output_names.to_owned())
-                    },
-                )),
-                ..self.clone()
-            };
+            // For each input_derivation, look up the
+            // derivation_or_fod_hash, and replace the derivation path with
+            // it's HEXLOWER digest.
+            let input_derivations = BTreeMap::from_iter(self.input_derivations.iter().map(
+                |(drv_path_str, output_names)| {
+                    // parse drv_path to StorePathRef
+                    let drv_path = StorePathRef::from_absolute_path(drv_path_str.as_bytes())
+                        .expect("invalid input derivation path");
+
+                    let encoded_hash = data_encoding::HEXLOWER
+                        .encode(fn_get_derivation_or_fod_hash(&drv_path).digest_as_bytes());
+
+                    (encoded_hash, output_names.to_owned())
+                },
+            ));
 
             // write the ATerm of that to the hash function
             let mut hasher = Sha256::new();
-            hasher.update(replaced_derivation.to_aterm_bytes());
+            hasher.update(self.to_aterm_bytes_with_replacements(&input_derivations));
 
             hasher.finalize().into()
         }))