From 6815572274c1e61b19bd386d52030e09289a511c Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Thu, 14 Dec 2023 10:00:55 -0600 Subject: refactor(tvix/store/fs): Decouple TvixStoreFs from Nix concepts To support tvix builds, we need to be able to use the `TvixStoreFs` to materialize the sandbox's /nix/store filesystem with just the list of inputs needed for the build. Currently we'd need to seed an in-memory `PathInfoService`, which includes more functionality than what is required for `TvixStoreFs`. Additionally, the `PathInfoService` is specific to Nix. By decoupling `TvixStoreFs` and `PathInfoService`, we allow for usage of `TvixStoreFs` with `tvix-castore` without needing a `PathInfoService`. This introduces a new `RootNodes` trait which provides a way for the filesystem to look up CA nodes via their basename in the root directory of the filesystem. We then implement `RootNodes` for any `PathInfoService`. Additionally, the filesystem root inode tracker now stores basenames rather than `StorePath`s since `StorePath`s are specific to Nix. As a followup we can rename `TvixStoreFs` to `TvixCaStoreFs` and move it to the `castore` crate (or its own crate). b/341 Change-Id: I928372955017c23b1bf2b37190cbc508a4ed10d5 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10363 Tested-by: BuildkiteCI Reviewed-by: flokli --- tvix/store/src/fs/root_nodes.rs | 61 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tvix/store/src/fs/root_nodes.rs (limited to 'tvix/store/src/fs/root_nodes.rs') diff --git a/tvix/store/src/fs/root_nodes.rs b/tvix/store/src/fs/root_nodes.rs new file mode 100644 index 000000000000..e672c6e647f3 --- /dev/null +++ b/tvix/store/src/fs/root_nodes.rs @@ -0,0 +1,61 @@ +use std::{ops::Deref, pin::Pin}; + +use futures::{Stream, StreamExt}; +use nix_compat::store_path::StorePath; +use tonic::async_trait; +use tvix_castore::{proto::node::Node, Error}; + +use crate::pathinfoservice::PathInfoService; + +/// Provides an interface for looking up root nodes in tvix-castore by given +/// a lookup key (usually the basename), and optionally allow a listing. +/// +#[async_trait] +pub trait RootNodes: Send + Sync { + /// Looks up a root CA node based on the basename of the node in the root + /// directory of the filesystem. + async fn get_by_basename(&self, name: &[u8]) -> Result, Error>; + + /// Lists all root CA nodes in the filesystem. An error can be returned + /// in case listing is not allowed + fn list(&self) -> Pin> + Send>>; +} + +/// Implements root node lookup for any [PathInfoService]. This represents a flat +/// directory structure like /nix/store where each entry in the root filesystem +/// directory corresponds to a CA node. +#[async_trait] +impl RootNodes for T +where + T: Deref + Send + Sync, +{ + async fn get_by_basename(&self, name: &[u8]) -> Result, Error> { + let Ok(store_path) = StorePath::from_bytes(name) else { + return Ok(None); + }; + + Ok(self + .deref() + .get(*store_path.digest()) + .await? + .map(|path_info| { + path_info + .node + .expect("missing root node") + .node + .expect("empty node") + })) + } + + fn list(&self) -> Pin> + Send>> { + Box::pin(self.deref().list().map(|result| { + result.map(|path_info| { + path_info + .node + .expect("missing root node") + .node + .expect("empty node") + }) + })) + } +} -- cgit 1.4.1