diff options
Diffstat (limited to '')
-rw-r--r-- | tvix/store/src/pathinfoservice/fs/mod.rs | 84 | ||||
-rw-r--r-- | tvix/store/src/pathinfoservice/fs/tests.rs (renamed from tvix/store/src/fs/tests.rs) | 18 | ||||
-rw-r--r-- | tvix/store/src/pathinfoservice/mod.rs | 6 |
3 files changed, 99 insertions, 9 deletions
diff --git a/tvix/store/src/pathinfoservice/fs/mod.rs b/tvix/store/src/pathinfoservice/fs/mod.rs new file mode 100644 index 000000000000..524aa10391f8 --- /dev/null +++ b/tvix/store/src/pathinfoservice/fs/mod.rs @@ -0,0 +1,84 @@ +use futures::Stream; +use futures::StreamExt; +use std::ops::Deref; +use std::pin::Pin; +use tonic::async_trait; +use tvix_castore::fs::{RootNodes, TvixStoreFs}; +use tvix_castore::proto as castorepb; +use tvix_castore::Error; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; + +use super::PathInfoService; + +#[cfg(test)] +mod tests; + +/// Helper to construct a [TvixStoreFs] from a [BlobService], [DirectoryService] +/// and [PathInfoService]. +/// This avoids users to have to interact with the wrapper struct directly, as +/// it leaks into the type signature of TvixStoreFS. +pub fn make_fs<BS, DS, PS>( + blob_service: BS, + directory_service: DS, + path_info_service: PS, + list_root: bool, +) -> TvixStoreFs<BS, DS, RootNodesWrapper<PS>> +where + BS: Deref<Target = dyn BlobService> + Send + Clone + 'static, + DS: Deref<Target = dyn DirectoryService> + Send + Clone + 'static, + PS: Deref<Target = dyn PathInfoService> + Send + Sync + Clone + 'static, +{ + TvixStoreFs::new( + blob_service, + directory_service, + RootNodesWrapper(path_info_service), + list_root, + ) +} + +/// Wrapper to satisfy Rust's orphan rules for trait implementations, as +/// RootNodes is coming from the [tvix-castore] crate. +#[doc(hidden)] +#[derive(Clone, Debug)] +pub struct RootNodesWrapper<T>(pub(crate) T); + +/// 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. +#[cfg(any(feature = "fuse", feature = "virtiofs"))] +#[async_trait] +impl<T> RootNodes for RootNodesWrapper<T> +where + T: Deref<Target = dyn PathInfoService> + Send + Sync, +{ + async fn get_by_basename(&self, name: &[u8]) -> Result<Option<castorepb::node::Node>, Error> { + let Ok(store_path) = nix_compat::store_path::StorePath::from_bytes(name) else { + return Ok(None); + }; + + Ok(self + .0 + .deref() + .get(*store_path.digest()) + .await? + .map(|path_info| { + path_info + .node + .expect("missing root node") + .node + .expect("empty node") + })) + } + + fn list(&self) -> Pin<Box<dyn Stream<Item = Result<castorepb::node::Node, Error>> + Send>> { + Box::pin(self.0.deref().list().map(|result| { + result.map(|path_info| { + path_info + .node + .expect("missing root node") + .node + .expect("empty node") + }) + })) + } +} diff --git a/tvix/store/src/fs/tests.rs b/tvix/store/src/pathinfoservice/fs/tests.rs index a3977c727505..d12ee2f2a03e 100644 --- a/tvix/store/src/fs/tests.rs +++ b/tvix/store/src/pathinfoservice/fs/tests.rs @@ -1,22 +1,22 @@ +use crate::pathinfoservice::PathInfoService; +use crate::proto::PathInfo; +use crate::tests::fixtures; +use crate::tests::utils::{gen_blob_service, gen_directory_service, gen_pathinfo_service}; use futures::StreamExt; use std::io::Cursor; use std::os::unix::prelude::MetadataExt; use std::path::Path; use std::sync::Arc; +use tempfile::TempDir; use tokio::{fs, io}; use tokio_stream::wrappers::ReadDirStream; use tvix_castore::blobservice::BlobService; use tvix_castore::directoryservice::DirectoryService; - -use tempfile::TempDir; - -use crate::fs::{fuse::FuseDaemon, TvixStoreFs}; -use crate::pathinfoservice::PathInfoService; -use crate::proto::PathInfo; -use crate::tests::fixtures; -use crate::tests::utils::{gen_blob_service, gen_directory_service, gen_pathinfo_service}; +use tvix_castore::fs::fuse::FuseDaemon; use tvix_castore::proto as castorepb; +use super::make_fs; + const BLOB_A_NAME: &str = "00000000000000000000000000000000-test"; const BLOB_B_NAME: &str = "55555555555555555555555555555555-test"; const HELLOWORLD_BLOB_NAME: &str = "66666666666666666666666666666666-test"; @@ -44,7 +44,7 @@ fn do_mount<P: AsRef<Path>>( mountpoint: P, list_root: bool, ) -> io::Result<FuseDaemon> { - let fs = TvixStoreFs::new( + let fs = make_fs( blob_service, directory_service, path_info_service, diff --git a/tvix/store/src/pathinfoservice/mod.rs b/tvix/store/src/pathinfoservice/mod.rs index 5faa0900a0b0..3bd0ef206998 100644 --- a/tvix/store/src/pathinfoservice/mod.rs +++ b/tvix/store/src/pathinfoservice/mod.rs @@ -4,6 +4,9 @@ mod memory; mod nix_http; mod sled; +#[cfg(any(feature = "fuse", feature = "virtiofs"))] +mod fs; + use futures::Stream; use std::pin::Pin; use tonic::async_trait; @@ -18,6 +21,9 @@ pub use self::memory::MemoryPathInfoService; pub use self::nix_http::NixHTTPPathInfoService; pub use self::sled::SledPathInfoService; +#[cfg(any(feature = "fuse", feature = "virtiofs"))] +pub use self::fs::make_fs; + /// The base trait all PathInfo services need to implement. #[async_trait] pub trait PathInfoService: Send + Sync { |