about summary refs log tree commit diff
path: root/tvix/nix-compat/src/derivation/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/nix-compat/src/derivation/mod.rs')
-rw-r--r--tvix/nix-compat/src/derivation/mod.rs67
1 files changed, 37 insertions, 30 deletions
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);