diff options
Diffstat (limited to 'tvix')
-rw-r--r-- | tvix/nix-compat/src/derivation/mod.rs | 118 |
1 files changed, 52 insertions, 66 deletions
diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs index d5857c1a6954..281fe3a3c875 100644 --- a/tvix/nix-compat/src/derivation/mod.rs +++ b/tvix/nix-compat/src/derivation/mod.rs @@ -76,24 +76,6 @@ impl Derivation { buffer } - /// Returns the fixed output path and its [NixHashWithMode] - /// (if the Derivation is fixed output), or None if there is no fixed output. - /// This takes some shortcuts in case more than one output exists, as this - /// can't be a valid fixed-output Derivation. - pub fn get_fixed_output(&self) -> Option<(&String, &NixHashWithMode)> { - if self.outputs.len() != 1 { - return None; - } - - if let Some(out_output) = self.outputs.get("out") { - if let Some(out_output_hash) = &out_output.hash_with_mode { - return Some((&out_output.path, out_output_hash)); - } - // There has to be a hash, otherwise it would not be FOD - } - None - } - /// Returns the drv path of a Derivation struct. /// /// The drv path is calculated like this: @@ -130,17 +112,13 @@ impl Derivation { // calculate the sha256 hash of the ATerm representation, and represent // it as a hex-encoded string (prefixed with sha256:). - let aterm_digest = { - let mut derivation_hasher = Sha256::new(); - derivation_hasher.update(self.to_aterm_string()); - derivation_hasher.finalize() - }; - - let h = NixHash::new(crate::nixhash::HashAlgo::Sha256, aterm_digest.to_vec()); + let aterm_digest = Sha256::new_with_prefix(self.to_aterm_string()) + .finalize() + .to_vec(); s.push_str(&format!( "{}:{}:{}.drv", - h.to_nix_hash_string(), + NixHash::new(HashAlgo::Sha256, aterm_digest).to_nix_hash_string(), store_path::STORE_DIR, name, )); @@ -148,6 +126,25 @@ impl Derivation { utils::build_store_path(true, &s, name) } + /// Returns the FOD digest, if the derivation is fixed-output, or None if + /// it's not. + fn fod_digest(&self) -> Option<Vec<u8>> { + if self.outputs.len() != 1 { + return None; + } + + let out_output = self.outputs.get("out")?; + Some( + Sha256::new_with_prefix(format!( + "fixed:out:{}:{}", + out_output.hash_with_mode.clone()?.to_nix_hash_string(), + out_output.path + )) + .finalize() + .to_vec(), + ) + } + /// Calculates the hash of a derivation modulo fixed-output subderivations. /// /// This is called `hashDerivationModulo` in nixcpp. @@ -168,50 +165,39 @@ impl Derivation { where F: Fn(&str) -> NixHash, { - let mut hasher = Sha256::new(); - let digest = match self.get_fixed_output() { - // Fixed-output derivations return a fixed hash - Some((fixed_output_path, fixed_output_hash)) => { - hasher.update(format!( - "fixed:out:{}:{}", - fixed_output_hash.to_nix_hash_string(), - fixed_output_path - )); - hasher.finalize() + // Fixed-output derivations return a fixed hash. + // Non-Fixed-output derivations return a hash of the ATerm notation, but with all + // input_derivation paths replaced by a recursive call to this function. + // We use fn_get_derivation_or_fod_hash here, so callers can precompute this. + let digest = self.fod_digest().unwrap_or({ + // This is a new map from derivation_or_fod_hash.digest (as lowerhex) + // to list of output names + let mut replaced_input_derivations: BTreeMap<String, BTreeSet<String>> = + BTreeMap::new(); + + // For each input_derivation, look up the + // derivation_or_fod_hash, and replace the derivation path with it's HEXLOWER + // digest. + // This is not the [NixHash::to_nix_hash_string], but without the sha256: prefix). + for (drv_path, output_names) in &self.input_derivations { + replaced_input_derivations.insert( + data_encoding::HEXLOWER.encode(&fn_get_derivation_or_fod_hash(drv_path).digest), + output_names.clone(), + ); } - // Non-Fixed-output derivations return a hash of the ATerm notation, but with all - // input_derivation paths replaced by a recursive call to this function. - // We use fn_get_derivation_or_fod_hash here, so callers can precompute this. - None => { - // This is a new map from derivation_or_fod_hash.digest (as lowerhex) - // to list of output names - let mut replaced_input_derivations: BTreeMap<String, BTreeSet<String>> = - BTreeMap::new(); - - // For each input_derivation, look up the - // derivation_or_fod_hash, and replace the derivation path with it's HEXLOWER - // digest. - // This is not the [NixHash::to_nix_hash_string], but without the sha256: prefix). - for (drv_path, output_names) in &self.input_derivations { - replaced_input_derivations.insert( - data_encoding::HEXLOWER - .encode(&fn_get_derivation_or_fod_hash(drv_path).digest), - output_names.clone(), - ); - } - // construct a new derivation struct with these replaced input derivation strings - let replaced_derivation = Derivation { - input_derivations: replaced_input_derivations, - ..self.clone() - }; + // construct a new derivation struct with these replaced input derivation strings + let replaced_derivation = Derivation { + input_derivations: replaced_input_derivations, + ..self.clone() + }; - // write the ATerm of that to the hash function - hasher.update(replaced_derivation.to_aterm_string()); + // write the ATerm of that to the hash function + let mut hasher = Sha256::new(); + hasher.update(replaced_derivation.to_aterm_string()); - hasher.finalize() - } - }; + hasher.finalize().to_vec() + }); NixHash::new(crate::nixhash::HashAlgo::Sha256, digest.to_vec()) } |