oh we're pushing

This commit is contained in:
do butterflies cry? 2026-03-25 11:12:45 +10:00
parent ff28c6f13f
commit ab9886281a
Signed by: cry
GPG key ID: F68745A836CA0412
4 changed files with 79 additions and 55 deletions

View file

@ -197,10 +197,9 @@ impl Store {
///
/// ```no_run
/// # use std::sync::Arc;
/// # use nixide::{Context, Store};
/// # use nixide::Store;
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let ctx = Arc::new(Context::new()?);
/// let store = Store::open(&ctx, None)?;
/// let store = Store::open(None)?;
/// let path = store.store_path("/nix/store/...")?;
/// # Ok(())
/// # }

View file

@ -7,9 +7,9 @@ use crate::errors::{new_nixide_error, ErrorContext};
use crate::util::panic_issue_call_failed;
use crate::util::wrap;
use crate::util::wrappers::AsInnerPtr;
use crate::NixideError;
use crate::NixideResult;
use nixide_sys::{self as sys, nix_err_NIX_OK};
use nixide_sys as sys;
/// A path in the Nix store.
///
@ -36,7 +36,7 @@ impl StorePath {
/// # Errors
///
/// Returns an error if the path cannot be parsed.
pub fn parse(store: &Store, path: &str) -> Result<Self, NixideError> {
pub fn parse(store: &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 {
@ -46,6 +46,10 @@ impl StorePath {
Ok(Self { inner })
}
pub fn fake_path(store: &Store) -> NixideResult<Self> {
Self::parse(store, "/nix/store/00000000000000000000000000000000-fake")
}
/// Get the name component of the store path.
///
/// This returns the name part of the store path (everything after the hash).
@ -55,11 +59,12 @@ impl StorePath {
///
/// Returns an error if the name cannot be retrieved.
///
pub fn name(&self) -> Result<String, NixideError> {
pub fn name(&self) -> NixideResult<String> {
wrap::nix_string_callback!(|callback, userdata: *mut __UserData, _| unsafe {
sys::nix_store_path_name(self.inner.as_ptr(), Some(callback), userdata as *mut c_void);
// NOTE: nix_store_path_name doesn't return nix_err, so we force it to return successfully
nix_err_NIX_OK
// XXX: NOTE: now `nix_string_callback` is a macro this isn't necessary
// sys::nix_err_NIX_OK
})
}
@ -84,7 +89,7 @@ impl StorePath {
///
/// * `store` - The store containing the path
///
pub fn real_path(&self, store: &Store) -> Result<PathBuf, NixideError> {
pub fn real_path(&self, store: &Store) -> NixideResult<PathBuf> {
wrap::nix_pathbuf_callback!(
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
sys::nix_store_real_path(

View file

@ -1,53 +1,82 @@
use serial_test::serial;
use super::*;
use super::{Store, StorePath};
use crate::errors::ErrorContext;
use crate::sys;
use crate::util::wrappers::AsInnerPtr as _;
#[test]
#[serial]
fn test_store_opening() {
let mut ctx = ErrorContext::new();
unsafe {
sys::nix_libutil_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libutil_init failed with bad ErrorContext");
sys::nix_libstore_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libstore_init failed with bad ErrorContext");
sys::nix_libexpr_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libexpr_init failed with bad ErrorContext");
};
let _store = Store::open(None).expect("Failed to open store");
}
#[test]
#[serial]
fn test_store_path_parse() {
let mut ctx = ErrorContext::new();
unsafe {
sys::nix_libutil_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libutil_init failed with bad ErrorContext");
sys::nix_libstore_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libstore_init failed with bad ErrorContext");
sys::nix_libexpr_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libexpr_init failed with bad ErrorContext");
};
let store = Store::open(None).expect("Failed to open store");
// Try parsing a well-formed store path
// Note: This may fail if the path doesn't exist in the store
let result = StorePath::parse(&store, "/nix/store/00000000000000000000000000000000-test");
// We don't assert success here because the path might not exist
// This test mainly checks that the API works correctly
match result {
Ok(_path) => {
// Successfully parsed the path
}
Err(_) => {
// Path doesn't exist or is invalid, which is expected
}
}
let result = StorePath::fake_path(&store);
result.expect("idk hopefully this fails");
}
#[test]
#[serial]
fn test_store_path_clone() {
let mut ctx = ErrorContext::new();
unsafe {
sys::nix_libutil_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libutil_init failed with bad ErrorContext");
sys::nix_libstore_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libstore_init failed with bad ErrorContext");
sys::nix_libexpr_init(ctx.as_ptr());
ctx.pop()
.expect("nix_libexpr_init failed with bad ErrorContext");
};
let store = Store::open(None).expect("Failed to open store");
// Try to get a valid store path by parsing
// Note: This test is somewhat limited without a guaranteed valid path
if let Ok(path) = StorePath::parse(&store, "/nix/store/00000000000000000000000000000000-test") {
let cloned = path.clone();
let path = StorePath::fake_path(&store).expect("Failed to create `StorePath::fake_path`");
let cloned = path.clone();
// Assert that the cloned path has the same name as the original
let original_name = path.name().expect("Failed to get original path name");
let cloned_name = cloned.name().expect("Failed to get cloned path name");
// Assert that the cloned path has the same name as the original
let original_name = path.name().expect("Failed to get original path name");
let cloned_name = cloned.name().expect("Failed to get cloned path name");
assert_eq!(
original_name, cloned_name,
"Cloned path should have the same name as original"
);
}
assert_eq!(
original_name, cloned_name,
"Cloned path should have the same name as original"
);
}
// Note: test_realize is not included because it requires a valid store path

View file

@ -3,6 +3,12 @@
pub(crate) struct UserData<S, T> {
pub inner: S,
pub retval: T,
#[cfg(debug_assertions)]
pub init_inner: bool,
#[cfg(debug_assertions)]
pub init_retval: bool,
}
impl<S, T> AsMut<UserData<S, T>> for UserData<S, T> {
@ -11,30 +17,14 @@ impl<S, T> AsMut<UserData<S, T>> for UserData<S, T> {
}
}
// pub(crate) trait VoidPtrIsomorphism {
// fn as_void_ptr(self) -> *mut c_void;
// fn from_void_ptr(ptr: *mut c_void) -> Self;
// }
// impl<S, T> VoidPtrIsomorphism for *mut UserData<S, T> {
// fn as_void_ptr(self) -> *mut c_void {
// self as *mut c_void
// }
// fn from_void_ptr(ptr: *mut c_void) -> Self {
// ptr as Self
// }
// }
impl<S, T> UserData<S, T> {
/// # Warning
///
/// Ensure `self.retval` has been initialised before unwrapping!
///
pub unsafe fn unwrap(self) -> (S, T) {
(self.inner, self.retval)
}
// pub unsafe fn unwrap(self) -> (S, T) {
// (self.inner, self.retval)
// }
pub unsafe fn as_mut_ptr(&mut self) -> *mut Self {
self as *mut Self
@ -62,7 +52,6 @@ macro_rules! nonnull {
}
}};
}
use std::ffi::c_void;
pub(crate) use nonnull;
@ -146,7 +135,9 @@ macro_rules! nix_callback {
$function(__wrapper_callback, __state.as_mut_ptr(), &__ctx);
__ctx.pop().and_then(|_| unsafe { __state.assume_init().retval })
// type annotations for compiler
let __result: $ret = __ctx.pop().and_then(|_| unsafe { __state.assume_init().retval });
__result
}};
}
pub(crate) use nix_callback;