about summary refs log tree commit diff
path: root/tvix/nix-compat/src/derivation/output.rs
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-01-31T13·45+0100
committerclbot <clbot@tvl.fyi>2023-01-31T15·16+0000
commit2d24c5f260945216ca01371d4120f5d53f08b2cd (patch)
tree5053bbffefd5a41241ab6ea27fafc290e44e665f /tvix/nix-compat/src/derivation/output.rs
parent9e809e21ccb1768567fc2516c5526ad0cdd56df0 (diff)
refactor(tvix/nix-compat): absorb //tvix/derivation r/5791
Put this in its src/derivation.

Change-Id: Ic047ab1c2da555a833ee454e10ef60c77537b617
Reviewed-on: https://cl.tvl.fyi/c/depot/+/7967
Reviewed-by: tazjin <tazjin@tvl.su>
Tested-by: BuildkiteCI
Autosubmit: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/nix-compat/src/derivation/output.rs')
-rw-r--r--tvix/nix-compat/src/derivation/output.rs54
1 files changed, 54 insertions, 0 deletions
diff --git a/tvix/nix-compat/src/derivation/output.rs b/tvix/nix-compat/src/derivation/output.rs
new file mode 100644
index 000000000000..9aef7172aec6
--- /dev/null
+++ b/tvix/nix-compat/src/derivation/output.rs
@@ -0,0 +1,54 @@
+use crate::derivation::OutputError;
+use crate::{nixbase32, store_path::StorePath};
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
+pub struct Output {
+    pub path: String,
+
+    #[serde(flatten)]
+    pub hash: Option<Hash>,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+pub struct Hash {
+    #[serde(rename = "hash")]
+    pub digest: String,
+    #[serde(rename = "hashAlgo")]
+    pub algo: String,
+}
+
+impl Output {
+    pub fn is_fixed(&self) -> bool {
+        self.hash.is_some()
+    }
+
+    pub fn validate(&self, validate_output_paths: bool) -> Result<(), OutputError> {
+        if let Some(hash) = &self.hash {
+            // try to decode digest
+            let result = nixbase32::decode(&hash.digest.as_bytes());
+            match result {
+                Err(e) => return Err(OutputError::InvalidHashEncoding(hash.digest.clone(), e)),
+                Ok(digest) => {
+                    if hash.algo != "sha1" && hash.algo != "sha256" {
+                        return Err(OutputError::InvalidHashAlgo(hash.algo.to_string()));
+                    }
+                    if (hash.algo == "sha1" && digest.len() != 20)
+                        || (hash.algo == "sha256" && digest.len() != 32)
+                    {
+                        return Err(OutputError::InvalidDigestSizeForAlgo(
+                            digest.len(),
+                            hash.algo.to_string(),
+                        ));
+                    }
+                }
+            };
+        }
+        if validate_output_paths {
+            if let Err(e) = StorePath::from_absolute_path(&self.path) {
+                return Err(OutputError::InvalidOutputPath(self.path.to_string(), e));
+            }
+        }
+        Ok(())
+    }
+}