feat: support nix_state_create's lookupPath argument
(cherry picked from commit 6d0906688ea40760217c2e017a4a0a61eb0fd611)
This commit is contained in:
parent
726e891be8
commit
d817e86c59
1 changed files with 49 additions and 37 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue