use std::{ffi::OsStr, os::unix::ffi::OsStrExt, sync::Arc}; use anyhow::{Context, Result}; use nix_compat::store_path::StorePath; use tokio::{io::AsyncRead, task}; use tokio_util::io::StreamReader; use crate::{ bindings::{self, AsyncWriteAdapter}, path_info::PathInfo, }; pub struct Store { inner: Arc, } impl Store { pub fn connect() -> Result { let inner = unsafe { bindings::open_nix_store()? }; Ok(Self { inner: Arc::new(inner), }) } pub async fn compute_fs_closure( &self, path: StorePath, ) -> Result>> { let inner = self.inner.clone(); task::spawn_blocking(move || { let cxx_vector = inner .store() .compute_fs_closure(path.to_string().as_bytes(), false, true, true)?; cxx_vector .iter() .map(|x| { StorePath::from_bytes(x.as_bytes()) .context("make StorePath from vector returned by compute_fs_closure") }) .collect::>() }) .await .unwrap() } pub async fn query_path_info(&self, path: StorePath) -> Result { let inner = self.inner.clone(); task::spawn_blocking(move || { let mut c_path_info = inner .store() .query_path_info(path.to_string().as_bytes()) .context("query cpp for path info")?; let signatures = c_path_info .pin_mut() .sigs() .into_iter() .map(|x| { let osstr = OsStr::from_bytes(x.as_bytes()); osstr.to_str().unwrap().to_string() }) .collect(); let references = c_path_info .pin_mut() .references() .into_iter() .map(|x| StorePath::from_bytes(x.as_bytes())) .collect::>() .context("get references from pathinfo")?; let nar_size = c_path_info.pin_mut().nar_size(); Ok(PathInfo { path, signatures, references, nar_size, }) }) .await .unwrap() } pub fn nar_from_path(&self, store_path: StorePath) -> impl AsyncRead { let inner = self.inner.clone(); let (adapter, mut sender) = AsyncWriteAdapter::new(); let base_name = store_path.to_string().as_bytes().to_vec(); tokio::task::spawn_blocking(move || { // Send all exceptions through the channel, and ignore errors // during sending (the channel may have been closed). if let Err(e) = inner.store().nar_from_path(base_name, sender.clone()) { let _ = sender.rust_error(e); } }); StreamReader::new(adapter) } }