feat: support nix_state_create's lookupPath argument

(cherry picked from commit 6d0906688ea40760217c2e017a4a0a61eb0fd611)
This commit is contained in:
Philipp Zander 2024-05-13 19:26:58 +02:00 committed by Robert Hensing
parent 726e891be8
commit d817e86c59

View file

@ -8,10 +8,9 @@ use nix_store::store::Store;
use nix_util::context::Context;
use nix_util::result_string_init;
use nix_util::string_return::{callback_get_result_string, callback_get_result_string_data};
use std::ffi::CString;
use std::ffi::{c_char, CString};
use std::os::raw::c_uint;
use std::ptr::null_mut;
use std::ptr::NonNull;
use std::ptr::{null, null_mut, NonNull};
lazy_static! {
static ref INIT: Result<()> = {
@ -48,18 +47,31 @@ pub struct EvalState {
context: Context,
}
impl EvalState {
pub fn new(store: Store) -> Result<Self> {
pub fn new<'a>(store: Store, lookup_path: impl IntoIterator<Item = &'a str>) -> Result<Self> {
let context = Context::new();
// this intermediate value must be here and must not be moved
// because it owns the data the `*const c_char` pointers point to.
let lookup_path: Vec<CString> = lookup_path
.into_iter()
.map(|path| {
CString::new(path).with_context(|| {
format!("EvalState::new: lookup_path `{path}` contains null byte")
})
})
.collect::<Result<_>>()?;
// this intermediate value owns the data the `*mut *const c_char` pointer points to.
let mut lookup_path: Vec<*const c_char> = lookup_path
.iter()
.map(|s| s.as_ptr())
.chain(std::iter::once(null())) // signal the end of the array
.collect();
init()?;
let eval_state = unsafe {
raw::state_create(
context.ptr(),
/* searchPath */ null_mut(),
store.raw_ptr(),
)
};
let eval_state =
unsafe { raw::state_create(context.ptr(), lookup_path.as_mut_ptr(), store.raw_ptr()) };
context.check_err()?;
if eval_state.is_null() {
panic!("nix_state_create returned a null pointer without an error");
@ -386,7 +398,7 @@ mod tests {
gc_registering_current_thread(|| {
// very basic test: make sure initialization doesn't crash
let store = Store::open("auto").unwrap();
let _e = EvalState::new(store).unwrap();
let _e = EvalState::new(store, []).unwrap();
})
.unwrap();
}
@ -395,7 +407,7 @@ mod tests {
fn eval_state_eval_from_string() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("1", "<test>").unwrap();
let v2 = v.clone();
es.force(&v).unwrap();
@ -412,7 +424,7 @@ mod tests {
fn eval_state_value_bool() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("true", "<test>").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -425,7 +437,7 @@ mod tests {
fn eval_state_value_int() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("1", "<test>").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -440,7 +452,7 @@ mod tests {
fn eval_state_value_attrs_names_empty() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("{ }", "<test>").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -455,7 +467,7 @@ mod tests {
fn eval_state_require_attrs_names_bad_type() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("1", "<test>").unwrap();
es.force(&v).unwrap();
let r = es.require_attrs_names(&v);
@ -472,7 +484,7 @@ mod tests {
fn eval_state_value_attrs_names_example() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"{ a = throw "nope a"; b = throw "nope b"; }"#;
let v = es.eval_from_string(expr, "<test>").unwrap();
let attrs = es.require_attrs_names(&v).unwrap();
@ -487,7 +499,7 @@ mod tests {
fn eval_state_require_attrs_select() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"{ a = "aye"; b = "bee"; }"#;
let v = es.eval_from_string(expr, "<test>").unwrap();
let a = es.require_attrs_select(&v, "a").unwrap();
@ -502,7 +514,7 @@ mod tests {
fn eval_state_require_attrs_select_error() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"{ a = throw "oh no the error"; }"#;
let v = es.eval_from_string(expr, "<test>").unwrap();
let r = es.require_attrs_select(&v, "a");
@ -523,7 +535,7 @@ mod tests {
fn eval_state_require_attrs_select_opt() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"{ a = "aye"; b = "bee"; }"#;
let v = es.eval_from_string(expr, "<test>").unwrap();
let a = es.require_attrs_select_opt(&v, "a").unwrap().unwrap();
@ -540,7 +552,7 @@ mod tests {
fn eval_state_require_attrs_select_opt_error() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"{ a = throw "oh no the error"; }"#;
let v = es.eval_from_string(expr, "<test>").unwrap();
let r = es.require_attrs_select_opt(&v, "a");
@ -561,7 +573,7 @@ mod tests {
fn eval_state_value_string() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("\"hello\"", "<test>").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -576,7 +588,7 @@ mod tests {
fn eval_state_value_string_unexpected_bool() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("true", "<test>").unwrap();
es.force(&v).unwrap();
let r = es.require_string(&v);
@ -594,7 +606,7 @@ mod tests {
fn eval_state_value_string_unexpected_path_value() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("/foo", "<test>").unwrap();
es.force(&v).unwrap();
let r = es.require_string(&v);
@ -611,7 +623,7 @@ mod tests {
fn eval_state_value_string_bad_utf() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es
.eval_from_string("builtins.substring 0 1 \"ü\"", "<test>")
.unwrap();
@ -632,7 +644,7 @@ mod tests {
fn eval_state_value_string_unexpected_context() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es
.eval_from_string("(derivation { name = \"hello\"; system = \"dummy\"; builder = \"cmd.exe\"; }).outPath", "<test>")
.unwrap();
@ -651,7 +663,7 @@ mod tests {
fn eval_state_new_string() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.new_value_str("hello").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -666,7 +678,7 @@ mod tests {
fn eval_state_new_string_empty() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.new_value_str("").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -681,7 +693,7 @@ mod tests {
fn eval_state_new_string_invalid() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let r = es.new_value_str("hell\0no");
match r {
Ok(_) => panic!("expected an error"),
@ -700,7 +712,7 @@ mod tests {
fn eval_state_new_int() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.new_value_int(42).unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -715,7 +727,7 @@ mod tests {
fn eval_state_value_attrset() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es.eval_from_string("{ }", "<test>").unwrap();
es.force(&v).unwrap();
let t = es.value_type(&v).unwrap();
@ -728,7 +740,7 @@ mod tests {
fn eval_state_value_list() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let v = es
.eval_from_string("[ ]", "<test>")
.unwrap();
@ -743,7 +755,7 @@ mod tests {
fn eval_state_realise_string() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let expr = r#"
''
a derivation output: ${
@ -790,7 +802,7 @@ mod tests {
fn eval_state_call() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let f = es.eval_from_string("x: x + 1", "<test>").unwrap();
let a = es.eval_from_string("2", "<test>").unwrap();
let v = es.call(f, a).unwrap();
@ -807,7 +819,7 @@ mod tests {
fn eval_state_call_fail_body() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let f = es.eval_from_string("x: x + 1", "<test>").unwrap();
let a = es.eval_from_string("true", "<test>").unwrap();
let r = es.call(f, a);
@ -828,7 +840,7 @@ mod tests {
fn eval_state_call_fail_args() {
gc_registering_current_thread(|| {
let store = Store::open("auto").unwrap();
let es = EvalState::new(store).unwrap();
let es = EvalState::new(store, []).unwrap();
let f = es.eval_from_string("{x}: x + 1", "<test>").unwrap();
let a = es.eval_from_string("{}", "<test>").unwrap();
let r = es.call(f, a);