From d4603fc0af5f2be27716d4d3c3fc6c514c8ffbe9 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Wed, 4 Jan 2023 21:59:23 +0100 Subject: refactor(derivation): return NixPath in calculate_derivation_path This moves all the hash compression logic into a common helper function. Also update the docstring, which said "path" here, which could have been confused with output paths. Change-Id: Iedfb59aeb24f7638afac669dcd18d57b6cfaece2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7759 Reviewed-by: tazjin Tested-by: BuildkiteCI --- tvix/derivation/src/derivation.rs | 45 +++++++++++++++++++++++++-------------- tvix/derivation/src/tests/mod.rs | 6 +++++- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/tvix/derivation/src/derivation.rs b/tvix/derivation/src/derivation.rs index a9ae4191b2de..a5ea56fbbf89 100644 --- a/tvix/derivation/src/derivation.rs +++ b/tvix/derivation/src/derivation.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{collections::BTreeMap, fmt, fmt::Write, iter::FromIterator}; use tvix_store::nixbase32::NIXBASE32; -use tvix_store::nixpath::STORE_DIR; +use tvix_store::nixpath::{NixPath, ParseNixPathError, STORE_DIR}; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct Derivation { @@ -28,6 +28,29 @@ pub struct Derivation { pub system: String, } +/// This returns a store path, either of a derivation or a regular output. +/// The path_hash is compressed to 20 bytes, and nixbase32-encoded (32 characters) +fn build_store_path( + is_derivation: bool, + path_hash: &[u8], + name: &str, +) -> Result { + let compressed = nix_hash::compress_hash(path_hash, 20); + if is_derivation { + NixPath::from_string( + format!( + "{}-{}{}", + NIXBASE32.encode(&compressed), + name, + write::DOT_FILE_EXT, + ) + .as_str(), + ) + } else { + NixPath::from_string(format!("{}-{}", NIXBASE32.encode(&compressed), name,).as_str()) + } +} + impl Derivation { pub fn serialize(&self, writer: &mut impl Write) -> Result<(), fmt::Error> { writer.write_str(write::DERIVATION_PREFIX)?; @@ -46,9 +69,9 @@ impl Derivation { Ok(()) } - /// Returns the path of a Derivation struct. + /// Returns the drv path of a Derivation struct. /// - /// The path is calculated like this: + /// The drv path is calculated like this: /// - Write the fingerprint of the Derivation to the sha256 hash function. /// This is: `text:`, /// all d.InputDerivations and d.InputSources (sorted, separated by a `:`), @@ -61,8 +84,8 @@ impl Derivation { /// - Write the .drv A-Term contents to a hash function /// - Take the digest, run hash.CompressHash(digest, 20) on it. /// - Encode it with nixbase32 - /// - Construct the full path $storeDir/$nixbase32EncodedCompressedHash-$name.drv - pub fn calculate_derivation_path(&self, name: &str) -> String { + /// - Use it (and the name) to construct a NixPath. + pub fn calculate_derivation_path(&self, name: &str) -> Result { let mut hasher = Sha256::new(); // collect the list of paths from input_sources and input_derivations @@ -101,17 +124,7 @@ impl Derivation { hasher.update(name); hasher.update(write::DOT_FILE_EXT); - let compressed = { - let aterm_digest = Vec::from_iter(hasher.finalize()); - nix_hash::compress_hash(&aterm_digest, 20) - }; - - format!( - "{}-{}{}", - NIXBASE32.encode(&compressed), - name, - write::DOT_FILE_EXT - ) + build_store_path(true, &hasher.finalize(), name) } } diff --git a/tvix/derivation/src/tests/mod.rs b/tvix/derivation/src/tests/mod.rs index 1b55c6e3e751..623cc4e5b13a 100644 --- a/tvix/derivation/src/tests/mod.rs +++ b/tvix/derivation/src/tests/mod.rs @@ -4,6 +4,7 @@ use std::io::Read; use std::path::Path; use test_case::test_case; use test_generator::test_resources; +use tvix_store::nixpath::NixPath; const RESOURCES_PATHS: &str = "src/tests/derivation_tests"; @@ -61,5 +62,8 @@ fn derivation_path(name: &str, expected_path: &str) { let data = read_file(&format!("{}/{}.json", RESOURCES_PATHS, expected_path)); let derivation: Derivation = serde_json::from_str(&data).expect("JSON was not well-formatted"); - assert_eq!(derivation.calculate_derivation_path(name), expected_path); + assert_eq!( + derivation.calculate_derivation_path(name).unwrap(), + NixPath::from_string(expected_path).unwrap() + ); } -- cgit 1.4.1