feat(tvix/nix-daemon): New operation AddToStoreNar
This operation is particularly used when invoking the following nix commands: ``` nix-store --add-fixed some-path nix-store --add-fixed --recursive some-path ``` Change-Id: I0f9b129c838c00e10415881f1e6e0d7bc1d7a3a6 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12800 Tested-by: BuildkiteCI Reviewed-by: flokli <flokli@flokli.de>
This commit is contained in:
parent
8ef9ba82a8
commit
e9acde3c42
5 changed files with 289 additions and 19 deletions
|
|
@ -60,7 +60,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
|||
}
|
||||
|
||||
async fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
let (_blob_service, _directory_service, path_info_service, _nar_calculation_service) =
|
||||
let (blob_service, directory_service, path_info_service, _nar_calculation_service) =
|
||||
construct_services(cli.service_addrs).await?;
|
||||
|
||||
let listen_address = cli.listen_args.listen_address.unwrap_or_else(|| {
|
||||
|
|
@ -76,7 +76,11 @@ async fn run(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
)
|
||||
.await?;
|
||||
|
||||
let io = Arc::new(TvixDaemon::new(path_info_service));
|
||||
let io = Arc::new(TvixDaemon::new(
|
||||
blob_service,
|
||||
directory_service,
|
||||
path_info_service,
|
||||
));
|
||||
|
||||
while let Ok((connection, _)) = listener.accept().await {
|
||||
let io = io.clone();
|
||||
|
|
|
|||
|
|
@ -4,20 +4,35 @@ use std::{
|
|||
};
|
||||
|
||||
use nix_compat::{
|
||||
nix_daemon::{types::UnkeyedValidPathInfo, NixDaemonIO},
|
||||
nix_daemon::{
|
||||
types::{AddToStoreNarRequest, UnkeyedValidPathInfo},
|
||||
NixDaemonIO,
|
||||
},
|
||||
nixbase32,
|
||||
store_path::StorePath,
|
||||
store_path::{build_ca_path, StorePath},
|
||||
};
|
||||
use tvix_store::{path_info::PathInfo, pathinfoservice::PathInfoService};
|
||||
use tracing::warn;
|
||||
use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService};
|
||||
use tvix_store::{nar::ingest_nar_and_hash, path_info::PathInfo, pathinfoservice::PathInfoService};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct TvixDaemon {
|
||||
blob_service: Arc<dyn BlobService>,
|
||||
directory_service: Arc<dyn DirectoryService>,
|
||||
path_info_service: Arc<dyn PathInfoService>,
|
||||
}
|
||||
|
||||
impl TvixDaemon {
|
||||
pub fn new(path_info_service: Arc<dyn PathInfoService>) -> Self {
|
||||
Self { path_info_service }
|
||||
pub fn new(
|
||||
blob_service: Arc<dyn BlobService>,
|
||||
directory_service: Arc<dyn DirectoryService>,
|
||||
path_info_service: Arc<dyn PathInfoService>,
|
||||
) -> Self {
|
||||
Self {
|
||||
blob_service,
|
||||
directory_service,
|
||||
path_info_service,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +63,60 @@ impl NixDaemonIO for TvixDaemon {
|
|||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_to_store_nar<R>(&self, request: AddToStoreNarRequest, reader: &mut R) -> Result<()>
|
||||
where
|
||||
R: tokio::io::AsyncRead + Send + Unpin,
|
||||
{
|
||||
let (root_node, nar_sha256, nar_size) = ingest_nar_and_hash(
|
||||
self.blob_service.clone(),
|
||||
self.directory_service.clone(),
|
||||
reader,
|
||||
&request.ca,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| Error::other(e.to_string()))?;
|
||||
|
||||
if nar_size != request.nar_size || nar_sha256 != *request.nar_hash {
|
||||
warn!(
|
||||
nar_hash.expected = nixbase32::encode(&*request.nar_hash),
|
||||
nar_hash.actual = nixbase32::encode(&nar_sha256),
|
||||
"nar hash mismatch"
|
||||
);
|
||||
return Err(Error::other(
|
||||
"ingested nar ended up different from what was specified in the request",
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(cahash) = &request.ca {
|
||||
let actual_path: StorePath<String> = build_ca_path(
|
||||
request.path.name(),
|
||||
cahash,
|
||||
request.references.iter().map(|p| p.to_absolute_path()),
|
||||
false,
|
||||
)
|
||||
.map_err(Error::other)?;
|
||||
if actual_path != request.path {
|
||||
return Err(Error::other("path mismatch"));
|
||||
}
|
||||
}
|
||||
|
||||
let path_info = PathInfo {
|
||||
store_path: request.path,
|
||||
node: root_node,
|
||||
references: request.references,
|
||||
nar_size,
|
||||
nar_sha256,
|
||||
signatures: request.signatures,
|
||||
deriver: request.deriver,
|
||||
ca: request.ca,
|
||||
};
|
||||
self.path_info_service
|
||||
.put(path_info)
|
||||
.await
|
||||
.map_err(|e| Error::other(e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// PathInfo lives in the tvix-store crate, but does not depend on nix-compat's wire feature,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue