about summary refs log tree commit diff
path: root/tvix/store/src/path_info.rs
diff options
context:
space:
mode:
authorMarijan Petričević <marijan.petricevic94@gmail.com>2024-10-10T14·11-0500
committerMarijan Petričević <marijan.petricevic94@gmail.com>2024-10-11T17·18+0000
commite8040ec61f2119ece2d396704576973f704607f3 (patch)
tree94caa469edb4b6c5534eb19a9683d786f9b7e5bf /tvix/store/src/path_info.rs
parentb4ccaac7ad135249eb0b1866acf4c8e68fd5bdb9 (diff)
refactor(tvix/store): use strictly typed PathInfo struct r/8787
This switches the PathInfoService trait from using the proto-derived
PathInfo struct to a more restrictive struct, and updates all
implementations to use it.

It removes a lot of the previous conversion and checks, as invalid
states became nonrepresentable, and validations are expressed on the
type level.

PathInfoService implementations consuming protobuf need to convert and
do the verification internally, and can only return the strongly typed
variant.

The nix_compat::narinfo::NarInfo conversions for the proto PathInfo
are removed, we only keep a version showing a NarInfo representation for
the strong struct.

Converting back to a PathInfo requires the root node now, but is
otherwise trivial, so left to the users.

Co-Authored-By: Florian Klink <flokli@flokli.de>
Change-Id: I6fdfdb44063efebb44a8f0097b6b81a828717e03
Reviewed-on: https://cl.tvl.fyi/c/depot/+/12588
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
Diffstat (limited to 'tvix/store/src/path_info.rs')
-rw-r--r--tvix/store/src/path_info.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/tvix/store/src/path_info.rs b/tvix/store/src/path_info.rs
new file mode 100644
index 000000000000..487261b4bdcb
--- /dev/null
+++ b/tvix/store/src/path_info.rs
@@ -0,0 +1,87 @@
+use nix_compat::{
+    narinfo::{Flags, Signature},
+    nixhash::CAHash,
+    store_path::StorePath,
+};
+
+/// Holds metadata about a store path, but not its contents.
+///
+/// This is somewhat equivalent to the information Nix holds in its SQLite
+/// database, or publishes as .narinfo files, except we also embed the
+/// [tvix_castore::Node] describing the contents in the castore model.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct PathInfo {
+    /// The store path this is about.
+    pub store_path: StorePath<String>,
+    /// The contents in the tvix-castore model.
+    //// Can be a directory, file or symlink.
+    pub node: tvix_castore::Node,
+    /// A list of references.
+    pub references: Vec<StorePath<String>>,
+    /// The size of the NAR representation of the contents, in bytes.
+    pub nar_size: u64,
+    /// The sha256 digest of the NAR representation of the contents.
+    pub nar_sha256: [u8; 32],
+    /// The signatures, usually shown in a .narinfo file.
+    pub signatures: Vec<Signature<String>>,
+    /// The StorePath of the .drv file producing this output.
+    /// The .drv suffix is omitted in its `name` field.
+    pub deriver: Option<StorePath<String>>,
+    /// The CA field in the .narinfo.
+    /// Its textual representations seen in the wild are one of the following:
+    ///
+    /// * `fixed:r:sha256:1gcky5hlf5vqfzpyhihydmm54grhc94mcs8w7xr8613qsqb1v2j6`
+    ///   fixed-output derivations using "recursive" `outputHashMode`.
+    /// * `fixed:sha256:19xqkh72crbcba7flwxyi3n293vav6d7qkzkh2v4zfyi4iia8vj8 fixed-output derivations using "flat" `outputHashMode\`
+    /// * `text:sha256:19xqkh72crbcba7flwxyi3n293vav6d7qkzkh2v4zfyi4iia8vj8`
+    ///   Text hashing, used for uploaded .drv files and outputs produced by
+    ///   builtins.toFile.
+    ///
+    /// Semantically, they can be split into the following components:
+    ///
+    /// * "content address prefix". Currently, "fixed" and "text" are supported.
+    /// * "hash mode". Currently, "flat" and "recursive" are supported.
+    /// * "hash type". The underlying hash function used.
+    ///   Currently, sha1, md5, sha256, sha512.
+    /// * "digest". The digest itself.
+    ///
+    /// There are some restrictions on the possible combinations.
+    /// For example, `text` and `fixed:recursive` always imply sha256.
+    pub ca: Option<CAHash>,
+}
+
+impl PathInfo {
+    /// Reconstructs a [nix_compat::narinfo::NarInfo<'_>].
+    ///
+    /// It does very little allocation (a Vec each for `signatures` and
+    /// `references`), the rest points to data owned elsewhere.
+    ///
+    /// It can be used to validate Signatures, or render a .narinfo file
+    /// (after some more fields are populated)
+    ///
+    /// Keep in mind this is not able to reconstruct all data present in the
+    /// NarInfo<'_>, as some of it is not stored at all:
+    /// - the `system`, `file_hash` and `file_size` fields are set to `None`.
+    /// - the URL is set to an empty string.
+    /// - Compression is set to "none"
+    ///
+    /// If you want to render it out to a string and be able to parse it back
+    /// in, at least URL *must* be set again.
+    pub fn to_narinfo(&self) -> nix_compat::narinfo::NarInfo<'_> {
+        nix_compat::narinfo::NarInfo {
+            flags: Flags::empty(),
+            store_path: self.store_path.as_ref(),
+            nar_hash: self.nar_sha256,
+            nar_size: self.nar_size,
+            references: self.references.iter().map(StorePath::as_ref).collect(),
+            signatures: self.signatures.iter().map(Signature::as_ref).collect(),
+            ca: self.ca.clone(),
+            system: None,
+            deriver: self.deriver.as_ref().map(StorePath::as_ref),
+            url: "",
+            compression: Some("none"),
+            file_hash: None,
+            file_size: None,
+        }
+    }
+}