From b55d1f97ce8762711ff44f9b5695452cc8083c44 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Tue, 14 Mar 2023 17:16:05 +0100 Subject: refactor(tvix/nix-compat): -derivation::Hash, +NixHash This stops using our own custom Hash structure, which was mostly only used because we had to parse the JSON representation somehow. Since cl/8217, there's a `NixHash` struct, which is better suited to hold this data. Converting the format requires a bit of serde labor though, but that only really matters when interacting with JSON representations (which we mostly don't). Change-Id: Idc5ee511e36e6726c71f66face8300a441b0bf4c Reviewed-on: https://cl.tvl.fyi/c/depot/+/8304 Autosubmit: flokli Tested-by: BuildkiteCI Reviewed-by: tazjin --- tvix/nix-compat/src/derivation/mod.rs | 67 +++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'tvix/nix-compat/src/derivation/mod.rs') diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs index 2b549536b247..06b7ba02f4d8 100644 --- a/tvix/nix-compat/src/derivation/mod.rs +++ b/tvix/nix-compat/src/derivation/mod.rs @@ -1,5 +1,5 @@ use crate::{ - nixhash::NixHash, + nixhash::HashAlgo, store_path::{self, StorePath}, }; use serde::{Deserialize, Serialize}; @@ -17,8 +17,9 @@ mod write; mod tests; // Public API of the crate. +pub use crate::nixhash::{NixHash, NixHashWithMode}; pub use errors::{DerivationError, OutputError}; -pub use output::{Hash, Output}; +pub use output::Output; pub use utils::path_with_references; #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] @@ -75,23 +76,22 @@ impl Derivation { buffer } - /// Returns the fixed output path and its hash - // (if the Derivation is fixed output), - /// or None if there is no fixed output. + /// 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, &Hash)> { + 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 { + 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 } - return None; + None } /// Returns the drv path of a Derivation struct. @@ -160,8 +160,6 @@ impl Derivation { /// `fixed:out:${algo}:${digest}:${fodPath}` string is hashed instead of /// the A-Term. /// - /// TODO: what's the representation of ${digest}? - /// /// If the derivation is not a fixed derivation, it's up to the caller of /// this function to provide a lookup function to lookup these calculation /// results of parent derivations at `fn_get_hash_derivation_modulo` (by @@ -175,8 +173,9 @@ impl Derivation { // Fixed-output derivations return a fixed hash Some((fixed_output_path, fixed_output_hash)) => { hasher.update(format!( - "fixed:out:{}:{}:{}", - &fixed_output_hash.algo, &fixed_output_hash.digest, fixed_output_path, + "fixed:out:{}:{}", + fixed_output_hash.to_nix_hash_string(), + fixed_output_path )); hasher.finalize() } @@ -196,7 +195,7 @@ impl Derivation { 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), + .encode(&fn_get_derivation_or_fod_hash(drv_path).digest), output_names.clone(), ); } @@ -255,7 +254,7 @@ impl Derivation { output_path_name.push_str(output_name); } - let s = &format!( + let fp = &format!( "output:{}:{}:{}:{}", output_name, derivation_or_fod_hash.to_nix_hash_string(), @@ -264,7 +263,7 @@ impl Derivation { ); let abs_store_path = - utils::build_store_path(false, s, &output_path_name)?.to_absolute_path(); + utils::build_store_path(false, fp, &output_path_name)?.to_absolute_path(); output.path = abs_store_path.clone(); self.environment @@ -277,33 +276,41 @@ impl Derivation { // footgun prevention mechanism. assert!(fixed_output_path.is_empty()); - let s = { - let mut s = String::new(); + let fp = { + let mut fp = String::new(); // Fixed-output derivation. - // There's two different hashing strategies in place, depending on the value of hash.algo. + // There's two different hashing strategies in place, + // depending on whether the hash is recursive AND sha256 or anything else. // This code is _weird_ but it is what Nix is doing. See: // https://github.com/NixOS/nix/blob/1385b2007804c8a0370f2a6555045a00e34b07c7/src/libstore/store-api.cc#L178-L196 - if fixed_output_hash.algo == "r:sha256" { - s.push_str(&format!( - "source:sha256:{}", - fixed_output_hash.digest, // lowerhex - )); + if let NixHashWithMode::Recursive(recursive_hash) = fixed_output_hash { + if recursive_hash.algo == HashAlgo::Sha256 { + fp.push_str(&format!("source:{}", recursive_hash.to_nix_hash_string())); + } else { + // This is similar to the FOD case, with an empty fixed_output_path. + fp.push_str(&format!( + "output:out:{}", + derivation_or_fod_hash.to_nix_hash_string(), + )); + } } else { - s.push_str("output:out:"); - // This is drv_replacement for FOD, with an empty fixed_output_path. - s.push_str(&derivation_or_fod_hash.to_nix_hash_string()); + // This is similar to the FOD case, with an empty fixed_output_path. + fp.push_str(&format!( + "output:out:{}", + derivation_or_fod_hash.to_nix_hash_string(), + )); } - s.push_str(&format!(":{}:{}", store_path::STORE_DIR, name)); - s + fp.push_str(&format!(":{}:{}", store_path::STORE_DIR, name)); + fp }; - let abs_store_path = utils::build_store_path(false, &s, name)?.to_absolute_path(); + let abs_store_path = utils::build_store_path(false, &fp, name)?.to_absolute_path(); self.outputs.insert( "out".to_string(), Output { path: abs_store_path.clone(), - hash: Some(fixed_output_hash.clone()), + hash_with_mode: Some(fixed_output_hash.clone()), }, ); self.environment.insert("out".to_string(), abs_store_path); -- cgit 1.4.1