refactor(tvix/nix-compat): add text_hash_string function
Use it to calculate the text_hash_string, which is then used in the calculate_derivation_path and path_with_references functions. Relates to b/263. Change-Id: I7478825e2a23a11224212fea5e3fd06daa97d5e5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/8364 Autosubmit: flokli <flokli@flokli.de> Reviewed-by: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
This commit is contained in:
parent
14c5781389
commit
971080c912
4 changed files with 58 additions and 60 deletions
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
nixhash::HashAlgo,
|
||||
store_path::{self, StorePath},
|
||||
texthash::text_hash_string,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
@ -78,26 +79,17 @@ impl Derivation {
|
|||
|
||||
/// Returns the drv path of a Derivation struct.
|
||||
///
|
||||
/// 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 `:`),
|
||||
/// a `:`,
|
||||
/// the nix string representation of the sha256 sum of the ATerm representation
|
||||
/// a `:`,
|
||||
/// the storeDir, followed by a `:`,
|
||||
/// the name of a derivation,
|
||||
/// a `.drv`.
|
||||
/// - Write the .drv A-Term contents to a hash function
|
||||
/// - Take the digest, run hash.CompressHash(digest, 20) on it.
|
||||
/// - Encode it with nixbase32
|
||||
/// - Use it (and the name) to construct a [StorePath].
|
||||
/// The drv path is calculated by calculating the [text_hash_string], using
|
||||
/// the `name` with a `.drv` suffix as name, all d.InputDerivations and d.InputSources as references,
|
||||
/// and the ATerm representation of the Derivation as contents.
|
||||
/// The text_hash_string is then passed to the build_store_path function.
|
||||
pub fn calculate_derivation_path(&self, name: &str) -> Result<StorePath, DerivationError> {
|
||||
let mut s = String::from("text:");
|
||||
// append .drv to the name
|
||||
let name_with_suffix = &format!("{}.drv", name);
|
||||
|
||||
// collect the list of paths from input_sources and input_derivations
|
||||
// into a (sorted, guaranteed by BTreeSet) list, and join them by :
|
||||
let concat_inputs: BTreeSet<String> = {
|
||||
// into a (sorted, guaranteed by BTreeSet) list of references
|
||||
let references: BTreeSet<String> = {
|
||||
let mut inputs = self.input_sources.clone();
|
||||
let input_derivation_keys: Vec<String> =
|
||||
self.input_derivations.keys().cloned().collect();
|
||||
|
@ -105,25 +97,9 @@ impl Derivation {
|
|||
inputs
|
||||
};
|
||||
|
||||
for input in concat_inputs {
|
||||
s.push_str(&input);
|
||||
s.push(':');
|
||||
}
|
||||
let text_hash_str = &text_hash_string(name_with_suffix, self.to_aterm_string(), references);
|
||||
|
||||
// calculate the sha256 hash of the ATerm representation, and represent
|
||||
// it as a hex-encoded string (prefixed with sha256:).
|
||||
let aterm_digest = Sha256::new_with_prefix(self.to_aterm_string())
|
||||
.finalize()
|
||||
.to_vec();
|
||||
|
||||
s.push_str(&format!(
|
||||
"{}:{}:{}.drv",
|
||||
NixHash::new(HashAlgo::Sha256, aterm_digest).to_nix_hash_string(),
|
||||
store_path::STORE_DIR,
|
||||
name,
|
||||
));
|
||||
|
||||
utils::build_store_path(true, &s, name)
|
||||
utils::build_store_path(true, text_hash_str, name)
|
||||
}
|
||||
|
||||
/// Returns the FOD digest, if the derivation is fixed-output, or None if
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::derivation::DerivationError;
|
||||
use crate::nixbase32;
|
||||
use crate::nixhash::NixHash;
|
||||
use crate::store_path::{self, StorePath};
|
||||
use crate::store_path::StorePath;
|
||||
use crate::texthash::text_hash_string;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// compress_hash takes an arbitrarily long sequence of bytes (usually
|
||||
|
@ -55,27 +55,6 @@ pub fn path_with_references<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[
|
|||
content: C,
|
||||
references: I,
|
||||
) -> Result<StorePath, DerivationError> {
|
||||
let mut s = String::from("text");
|
||||
|
||||
for reference in references {
|
||||
s.push(':');
|
||||
s.push_str(reference.as_ref());
|
||||
}
|
||||
|
||||
let content_digest = {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(content);
|
||||
hasher.finalize()
|
||||
};
|
||||
|
||||
let h = NixHash::new(crate::nixhash::HashAlgo::Sha256, content_digest.to_vec());
|
||||
|
||||
s.push_str(&format!(
|
||||
":{}:{}:{}",
|
||||
h.to_nix_hash_string(),
|
||||
store_path::STORE_DIR,
|
||||
name
|
||||
));
|
||||
|
||||
build_store_path(false, &s, name)
|
||||
let text_hash_str = text_hash_string(name, content, references);
|
||||
build_store_path(false, &text_hash_str, name)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ pub mod nixhash;
|
|||
mod nixhash_algos;
|
||||
mod nixhash_with_mode;
|
||||
pub mod store_path;
|
||||
mod texthash;
|
||||
|
||||
/// Nix placeholders (i.e. values returned by `builtins.placeholder`)
|
||||
/// are used to populate outputs with paths that must be
|
||||
|
|
42
tvix/nix-compat/src/texthash.rs
Normal file
42
tvix/nix-compat/src/texthash.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use sha2::{Digest, Sha256};
|
||||
|
||||
use crate::{nixhash::NixHash, store_path};
|
||||
|
||||
/// This contains the Nix logic to create "text hash strings", which are used
|
||||
/// in `builtins.toFile`, as well as in Derivation Path calculation.
|
||||
///
|
||||
/// A text hash is calculated by concatenating the following fields, separated by a `:`:
|
||||
///
|
||||
/// - text
|
||||
/// - references, individually joined by `:`
|
||||
/// - the nix_hash_string representation of the sha256 digest of some contents
|
||||
/// - the value of `storeDir`
|
||||
/// - the name
|
||||
pub fn text_hash_string<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>>(
|
||||
name: &str,
|
||||
content: C,
|
||||
references: I,
|
||||
) -> String {
|
||||
let mut s = String::from("text:");
|
||||
|
||||
for reference in references {
|
||||
s.push_str(reference.as_ref());
|
||||
s.push(':');
|
||||
}
|
||||
|
||||
// the nix_hash_string representation of the sha256 digest of some contents
|
||||
s.push_str(
|
||||
&{
|
||||
let content_digest = {
|
||||
let hasher = Sha256::new_with_prefix(content);
|
||||
hasher.finalize()
|
||||
};
|
||||
NixHash::new(crate::nixhash::HashAlgo::Sha256, content_digest.to_vec())
|
||||
}
|
||||
.to_nix_hash_string(),
|
||||
);
|
||||
|
||||
s.push_str(&format!(":{}:{}", store_path::STORE_DIR, name));
|
||||
|
||||
s
|
||||
}
|
Loading…
Reference in a new issue