diff options
author | Peter Kolloch <info@eigenvalue.net> | 2024-02-17T05·15+0700 |
---|---|---|
committer | clbot <clbot@tvl.fyi> | 2024-02-17T07·30+0000 |
commit | 48d4d10bacdf2843f0a59711c872062348208a37 (patch) | |
tree | 02bfcd254f7f15f6c8ac878a23a81769f0b2bd2c | |
parent | a9f5bb859fa23e9b00621df2cd725a1b0f1bd4d8 (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>
-rw-r--r-- | tvix/nix-compat/src/derivation/mod.rs | 58 |
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() })) |