Compare commits

...

5 commits

4 changed files with 82 additions and 15 deletions

View file

@ -137,6 +137,7 @@ fn main() {
.file("libnixide-c/nixide_api_flake.cc")
.file("libnixide-c/nixide_api_fetchers.cc")
// .files(LIBS.iter().map(|s| (*s).strip_prefix("nix-").unwrap().strip_suffix("-c").unwrap()))
.opt_level((!cfg!(debug_assertions)) as u32 * 3)
.includes(&include_paths)
.compile("libnixide");

View file

@ -108,7 +108,7 @@ impl Store {
///
/// Returns an error if the path cannot be realized.
///
pub fn realise<F>(
pub fn realise(
&self,
path: &StorePath,
user_callback: fn(&str, &StorePath),
@ -130,7 +130,7 @@ impl Store {
let callback = unsafe { (*userdata).inner };
callback(output_name.as_ref(), &store_path);
(output_name, store_path);
(unsafe {(*userdata).retval }).append((output_name, store_path));
},
|callback,
state: *mut __UserData,
@ -139,6 +139,8 @@ impl Store {
// WARNING: Using `write` instead of assignment via `=`
// WARNING: to not call `drop` on the old, uninitialized value.
(&raw mut (*state).inner).write(user_callback);
// register return value
(&raw mut (*state).retval).write(Vec::new());
sys::nix_store_realise(
ctx.as_ptr(),

View file

@ -1,6 +1,8 @@
use std::cell::RefCell;
use std::ffi::{CString, c_void};
use std::path::PathBuf;
use std::ptr::NonNull;
use std::rc::Rc;
use super::Store;
use crate::NixideResult;
@ -15,7 +17,8 @@ use crate::util::wrappers::AsInnerPtr;
/// Represents a store path that can be realized, queried, or manipulated.
///
pub struct StorePath {
pub(crate) inner: NonNull<sys::StorePath>,
inner: NonNull<sys::StorePath>,
store: Rc<RefCell<Store>>,
}
impl Clone for StorePath {
@ -25,7 +28,10 @@ impl Clone for StorePath {
panic_issue_call_failed!("nix_store_path_clone returned None for valid path")
});
StorePath { inner }
StorePath {
inner,
store: self.store.clone(),
}
}
}
@ -65,17 +71,17 @@ impl StorePath {
/// # Errors
///
/// Returns an error if the path cannot be parsed.
pub fn parse(store: &Store, path: &str) -> NixideResult<Self> {
pub fn parse(store: Rc<RefCell<Store>>, path: &str) -> NixideResult<Self> {
let c_path = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?;
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
sys::nix_store_parse_path(ctx.as_ptr(), store.as_ptr(), c_path.as_ptr())
sys::nix_store_parse_path(ctx.as_ptr(), store.borrow().as_ptr(), c_path.as_ptr())
})?;
Ok(Self { inner })
Ok(Self { inner, store })
}
pub fn fake_path(store: &Store) -> NixideResult<Self> {
pub fn fake_path(store: Rc<RefCell<Store>>) -> NixideResult<Self> {
Self::parse(store, "/nix/store/00000000000000000000000000000000-fake")
}
@ -108,22 +114,18 @@ impl StorePath {
/// Not all types of stores support this operation.
///
/// # Arguments
/// * `context` [in] - Optional, stores error information
/// * `store` [in] - nix store reference
/// * `path` [in] - the path to get the real path from
/// * `callback` [in] - called with the real path
/// * `user_data` [in] - arbitrary data, passed to the callback when it's called.
/// * `store` - nix store reference
///
/// # Arguments
///
/// * `store` - The store containing the path
///
pub fn real_path(&self, store: &Store) -> NixideResult<PathBuf> {
pub fn real_path(&self) -> NixideResult<PathBuf> {
wrap::nix_pathbuf_callback!(
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
sys::nix_store_real_path(
ctx.as_ptr(),
store.inner.as_ptr(),
self.store.borrow().as_ptr(),
self.as_ptr(),
Some(callback),
userdata as *mut c_void,
@ -145,4 +147,66 @@ impl StorePath {
})
.is_ok()
}
/// Gets the closure of a specific store path
///
/// The callback borrows each StorePath only for the duration of the call.
///
/// # Arguments
///
/// * flip - If false, compute the forward closure (paths referenced by any store path in the closure).
/// If true, compute the backward closure (paths that reference any store path in the closure).
/// * include_outputs - If flip_direction is false: for any derivation in the closure, include its outputs.
/// If flip_direction is true: for any output in the closure, include derivations that produce it.
/// * include_derivers - If flip_direction is false: for any output in the closure, include the derivation that
/// produced it.
/// If flip_direction is true: for any derivation in the closure, include its outputs.
/// * user_callback - The function to call for every store path, in no particular order
///
pub fn with_closure(
&self,
flip: bool,
include_outputs: bool,
include_derivers: bool,
user_callback: fn(&StorePath),
) -> NixideResult<()> {
wrap::nix_callback!(
|context: *mut sys::NixCContext,
; userdata: (Rc<RefCell<Store>>, fn(&StorePath));
store_path: *const sys::StorePath,
| -> () {
let callback: fn(&StorePath) = unsafe { (*userdata).inner.1 };
let store = unsafe { (*userdata).inner.0.clone() };
let path = &StorePath {
inner: NonNull::new(unsafe { store.borrow().as_ptr() } as *mut sys::StorePath).unwrap(),
store,
};
callback(&path);
},
|callback,
state: *mut __UserData,
ctx: &ErrorContext| unsafe {
// register userdata
// WARNING: Using `write` instead of assignment via `=`
// WARNING: to not call `drop` on the old, uninitialized value.
(&raw mut (*state).inner).write((self.store.clone(), user_callback));
sys::nix_store_get_fs_closure(
ctx.as_ptr(),
self.store.borrow().as_ptr(),
self.as_ptr(),
flip,
include_outputs,
include_derivers,
(*state).inner_ptr() as *mut c_void,
Some(callback));
}
)
}
// XXX: TODO: nix 2.34.4 adds a LOT here (ie especially around derivations)
// XXX: TODO: it also removes nix_store_path* functions (ie nix_store_path_free)?
// XXX: TODO: why?? try and research this, maybe they didn't mean to??
}