about summary refs log tree commit diff
path: root/tvix/store/src/bin/tvix-store.rs
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-09-02T18·16+0300
committerclbot <clbot@tvl.fyi>2023-09-04T16·02+0000
commit3c340b28bdc812b9c13393c9e2bb378ba7dd9ec8 (patch)
tree9e45299a02c687275dd6bc30913952fb692edd65 /tvix/store/src/bin/tvix-store.rs
parent428b65584524e03a2f7cf24ed992f143373b3bd3 (diff)
refactor(tvix/{cli,store}): move TvixStoreIO to tvix-cli crate r/6550
This trait is eval-specific, there's no point in dealing with these
things in tvix-store.

This implements the EvalIO interface for a Tvix store.
The proper place for this glue code (for now) is tvix-cli, which knows
about both tvix-store and tvix-eval.

There's one annoyance with this move: The `tvix-store import` subcommand
previously also used the TvixStoreIO implementation (because it
conveniently did what we wanted).
Some of this code had to be duplicated, mostly logic to calculate the
NAR-based output path and create the PathInfo object.

Some, but potentially more of this can be extracted into helper
functions in a shared crate, and then be used from both TvixStoreIO in
tvix-cli as well as the tvix-store CLI entrypoint.

Change-Id: Ia7515e83c1b54f95baf810fbd8414c5521382d40
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9212
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: flokli <flokli@flokli.de>
Diffstat (limited to 'tvix/store/src/bin/tvix-store.rs')
-rw-r--r--tvix/store/src/bin/tvix-store.rs67
1 files changed, 55 insertions, 12 deletions
diff --git a/tvix/store/src/bin/tvix-store.rs b/tvix/store/src/bin/tvix-store.rs
index 6f26734cdc..f0cef0b981 100644
--- a/tvix/store/src/bin/tvix-store.rs
+++ b/tvix/store/src/bin/tvix-store.rs
@@ -1,13 +1,14 @@
 use clap::Subcommand;
 use data_encoding::BASE64;
 use futures::future::try_join_all;
+use nix_compat::store_path;
 use std::io;
 use std::path::Path;
 use std::path::PathBuf;
-use std::sync::Arc;
 use tracing_subscriber::prelude::*;
 use tvix_store::blobservice;
 use tvix_store::directoryservice;
+use tvix_store::import;
 use tvix_store::pathinfoservice;
 use tvix_store::proto::blob_service_server::BlobServiceServer;
 use tvix_store::proto::directory_service_server::DirectoryServiceServer;
@@ -16,7 +17,8 @@ use tvix_store::proto::path_info_service_server::PathInfoServiceServer;
 use tvix_store::proto::GRPCBlobServiceWrapper;
 use tvix_store::proto::GRPCDirectoryServiceWrapper;
 use tvix_store::proto::GRPCPathInfoServiceWrapper;
-use tvix_store::TvixStoreIO;
+use tvix_store::proto::NarInfo;
+use tvix_store::proto::PathInfo;
 use tvix_store::FUSE;
 
 #[cfg(feature = "reflection")]
@@ -173,6 +175,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
             directory_service_addr,
             path_info_service_addr,
         } => {
+            // FUTUREWORK: allow flat for single files?
             let blob_service = blobservice::from_addr(&blob_service_addr)?;
             let directory_service = directoryservice::from_addr(&directory_service_addr)?;
             let path_info_service = pathinfoservice::from_addr(
@@ -181,20 +184,60 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
                 directory_service.clone(),
             )?;
 
-            let io = Arc::new(TvixStoreIO::new(
-                blob_service,
-                directory_service,
-                path_info_service,
-            ));
-
             let tasks = paths
-                .iter()
+                .into_iter()
                 .map(|path| {
-                    let io_move = io.clone();
-                    let path = path.clone();
+                    let blob_service = blob_service.clone();
+                    let directory_service = directory_service.clone();
+                    let path_info_service = path_info_service.clone();
+
                     let task: tokio::task::JoinHandle<Result<(), io::Error>> =
                         tokio::task::spawn_blocking(move || {
-                            let path_info = io_move.import_path_with_pathinfo(&path)?;
+                            // Ingest the path into blob and directory service.
+                            let root_node = import::ingest_path(
+                                blob_service.clone(),
+                                directory_service.clone(),
+                                &path,
+                            )
+                            .expect("failed to ingest path");
+
+                            // Ask the PathInfoService for the NAR size and sha256
+                            let (nar_size, nar_sha256) =
+                                path_info_service.calculate_nar(&root_node)?;
+
+                            // TODO: make a path_to_name helper function?
+                            let name = path
+                                .file_name()
+                                .expect("path must not be ..")
+                                .to_str()
+                                .expect("path must be valid unicode");
+
+                            let output_path =
+                                store_path::build_nar_based_store_path(&nar_sha256, name);
+
+                            // assemble a new root_node with a name that is derived from the nar hash.
+                            let root_node =
+                                root_node.rename(output_path.to_string().into_bytes().into());
+
+                            // assemble the [crate::proto::PathInfo] object.
+                            let path_info = PathInfo {
+                                node: Some(tvix_store::proto::Node {
+                                    node: Some(root_node),
+                                }),
+                                // There's no reference scanning on path contents ingested like this.
+                                references: vec![],
+                                narinfo: Some(NarInfo {
+                                    nar_size,
+                                    nar_sha256: nar_sha256.to_vec().into(),
+                                    signatures: vec![],
+                                    reference_names: vec![],
+                                }),
+                            };
+
+                            // put into [PathInfoService], and return the PathInfo that we get back
+                            // from there (it might contain additional signatures).
+                            let path_info = path_info_service.put(path_info)?;
+
                             print_node(&path_info.node.unwrap().node.unwrap(), &path);
                             Ok(())
                         });