snix_store/
import.rs

1use snix_castore::{
2    blobservice::BlobService, directoryservice::DirectoryService, import::fs::ingest_path,
3};
4use tracing::instrument;
5
6use nix_compat::{
7    nixhash::{CAHash, NixHash},
8    store_path::{self, StorePath},
9};
10
11use crate::{
12    nar::NarCalculationService,
13    pathinfoservice::{PathInfo, PathInfoService},
14    proto::nar_info,
15};
16
17impl From<CAHash> for nar_info::Ca {
18    fn from(value: CAHash) -> Self {
19        let hash_type: nar_info::ca::Hash = (&value).into();
20        let digest: bytes::Bytes = value.hash().to_string().into();
21        nar_info::Ca {
22            r#type: hash_type.into(),
23            digest,
24        }
25    }
26}
27
28/// Ingest the contents at the given path `path` into castore, and registers the
29/// resulting root node in the passed PathInfoService, using the "NAR sha256
30/// digest" and the passed name for output path calculation.
31/// Inserts the PathInfo into the PathInfoService and returns it back to the caller.
32/// The `name` should have been checked by [nix_compat::store_path::validate_name]
33/// before, to avoid unnecessarily importing, but will prevent the PathInfo from
34/// being created in case of an invalid name.
35#[instrument(skip_all, fields(name=name.as_ref(), path=?path.as_ref()), err)]
36pub async fn import_path_as_nar_ca<BS, DS, PS, NS, P>(
37    path: P,
38    name: impl AsRef<str>,
39    blob_service: BS,
40    directory_service: DS,
41    path_info_service: PS,
42    nar_calculation_service: NS,
43) -> Result<PathInfo, std::io::Error>
44where
45    P: AsRef<std::path::Path>,
46    BS: BlobService + Clone,
47    DS: DirectoryService,
48    PS: AsRef<dyn PathInfoService>,
49    NS: NarCalculationService,
50{
51    // Ingest the contents at the given path `path` into castore.
52    let root_node = ingest_path::<_, _, _, &[u8]>(blob_service, directory_service, path, None)
53        .await
54        .map_err(std::io::Error::other)?;
55
56    // Ask for the NAR size and sha256
57    let (nar_size, nar_sha256) = nar_calculation_service
58        .calculate_nar(&root_node)
59        .await
60        .map_err(std::io::Error::other)?;
61
62    let ca = CAHash::Nar(NixHash::Sha256(nar_sha256));
63
64    // Calculate the output path. Will fail if the previously passed name doesn't pass
65    // the [nix_compat::store_path::validate_name] check.
66    let output_path: StorePath<String> =
67        store_path::build_ca_path(name.as_ref(), &ca, std::iter::empty::<&str>(), false).map_err(
68            |_| {
69                std::io::Error::new(
70                    std::io::ErrorKind::InvalidData,
71                    format!("invalid name: {0}", name.as_ref()),
72                )
73            },
74        )?;
75
76    // Insert a PathInfo. On success, return it back to the caller.
77    path_info_service
78        .as_ref()
79        .put(PathInfo {
80            store_path: output_path.to_owned(),
81            node: root_node,
82            // There's no reference scanning on imported paths
83            references: vec![],
84            nar_size,
85            nar_sha256,
86            signatures: vec![],
87            deriver: None,
88            ca: Some(ca),
89        })
90        .await
91        .map_err(std::io::Error::other)
92}