fix bad usage of sys::nix_gc_incref
This commit is contained in:
parent
53c2d40393
commit
fee35fa88b
32 changed files with 1359 additions and 682 deletions
356
Cargo.lock
generated
356
Cargo.lock
generated
|
|
@ -11,6 +11,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.102"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.72.1"
|
||||
|
|
@ -118,12 +124,40 @@ version = "1.15.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
|
|
@ -159,12 +193,64 @@ dependencies = [
|
|||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasip2",
|
||||
"wasip3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "id-arena"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
|
|
@ -174,6 +260,18 @@ dependencies = [
|
|||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "leb128fmt"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.183"
|
||||
|
|
@ -190,6 +288,12 @@ dependencies = [
|
|||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
|
|
@ -226,6 +330,7 @@ dependencies = [
|
|||
"nixide-sys",
|
||||
"serial_test",
|
||||
"stdext",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -290,6 +395,16 @@ version = "0.3.32"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
|
|
@ -308,6 +423,12 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.18"
|
||||
|
|
@ -352,6 +473,19 @@ version = "2.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scc"
|
||||
version = "2.4.0"
|
||||
|
|
@ -373,6 +507,54 @@ version = "3.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "3.4.0"
|
||||
|
|
@ -434,20 +616,194 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.2+wasi-0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip3"
|
||||
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-encoder"
|
||||
version = "0.244.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
||||
dependencies = [
|
||||
"leb128fmt",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-metadata"
|
||||
version = "0.244.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"indexmap",
|
||||
"wasm-encoder",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmparser"
|
||||
version = "0.244.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||
dependencies = [
|
||||
"wit-bindgen-rust-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-core"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"heck",
|
||||
"wit-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rust"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"heck",
|
||||
"indexmap",
|
||||
"prettyplease",
|
||||
"syn",
|
||||
"wasm-metadata",
|
||||
"wit-bindgen-core",
|
||||
"wit-component",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rust-macro"
|
||||
version = "0.51.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wit-bindgen-core",
|
||||
"wit-bindgen-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-component"
|
||||
version = "0.244.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"indexmap",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"wasm-encoder",
|
||||
"wasm-metadata",
|
||||
"wasmparser",
|
||||
"wit-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-parser"
|
||||
version = "0.244.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"id-arena",
|
||||
"indexmap",
|
||||
"log",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"unicode-xid",
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yap"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfe269e7b803a5e8e20cbd97860e136529cd83bf2c9c6d37b142467e7e1f051f"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ libc = "0.2.183"
|
|||
stdext = "0.3.3"
|
||||
ctor = "0.6.3"
|
||||
nixide-sys = { path = "../nixide-sys", version = "0.1.0", features = ["nix-util-c", "nix-main-c"]}
|
||||
tempfile = "3.27.0"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "3.4.0"
|
||||
|
|
|
|||
|
|
@ -10,14 +10,14 @@
|
|||
// * These may be rendered differently, so that users can distinguish them.
|
||||
// */
|
||||
// bool isFromExpr = false;
|
||||
|
||||
//
|
||||
// /**
|
||||
// * Exit status.
|
||||
// */
|
||||
// unsigned int status = 1;
|
||||
|
||||
//
|
||||
// Suggestions suggestions;
|
||||
|
||||
//
|
||||
// static std::optional<std::string> programName;
|
||||
// };
|
||||
|
||||
|
|
@ -67,6 +67,19 @@ pub(crate) struct ErrorContext {
|
|||
inner: NonNull<sys::nix_c_context>,
|
||||
}
|
||||
|
||||
// impl Clone for ErrorContext {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
//
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self { inner }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl AsInnerPtr<sys::nix_c_context> for ErrorContext {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_c_context {
|
||||
|
|
@ -183,7 +196,6 @@ impl ErrorContext {
|
|||
/// nix_err nix_set_err_msg(nix_c_context * context, nix_err err, const char * msg)
|
||||
/// {
|
||||
/// if (context == nullptr) {
|
||||
/// // todo last_err_code
|
||||
/// throw nix::Error("Nix C api error: %s", msg);
|
||||
/// }
|
||||
/// context->last_err_code = err;
|
||||
|
|
@ -218,11 +230,9 @@ impl ErrorContext {
|
|||
/// This function **never fails**.
|
||||
///
|
||||
fn get_err(&self) -> Option<sys::nix_err> {
|
||||
let err = unsafe { sys::nix_err_code(self.as_ptr()) };
|
||||
|
||||
match err {
|
||||
match unsafe { sys::nix_err_code(self.as_ptr()) } {
|
||||
sys::nix_err_NIX_OK => None,
|
||||
_ => Some(err),
|
||||
err => Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -257,13 +267,17 @@ impl ErrorContext {
|
|||
/// and avoid passing in a [sys::nix_c_context] struct.
|
||||
///
|
||||
fn get_msg(&self) -> Option<String> {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
// NOTE: an Err here only occurs when `self.get_code() == Ok(())`
|
||||
let mut n: c_uint = 0;
|
||||
// NOTE: an Err here only occurs when `self.get_code() == Ok(())`
|
||||
let mut n: c_uint = 0;
|
||||
let result = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_err_msg(ctx.as_ptr(), self.as_ptr(), &mut n)
|
||||
.to_utf8_string_n(n as usize)
|
||||
.ok()
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(option) => option,
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -305,19 +319,18 @@ impl ErrorContext {
|
|||
/// ```
|
||||
///
|
||||
fn get_nix_err_name(&self) -> Option<String> {
|
||||
#[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe`
|
||||
unsafe {
|
||||
// NOTE: an Err here only occurs when "Last error was not a nix error"
|
||||
wrap::nix_string_callback!(|callback, userdata: *mut __UserData, ctx: &ErrorContext| {
|
||||
// NOTE: an Err here only occurs when "Last error was not a nix error"
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_err_name(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
)
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Returns [None] if [self.code] is [sys::nix_err_NIX_OK], and [Some] otherwise.
|
||||
|
|
@ -358,19 +371,16 @@ impl ErrorContext {
|
|||
/// ```
|
||||
///
|
||||
fn get_nix_err_info_msg(&self) -> Option<String> {
|
||||
#[allow(unused_unsafe)] // XXX: TODO: remove this `unused_unsafe`
|
||||
unsafe {
|
||||
// NOTE: an Err here only occurs when "Last error was not a nix error"
|
||||
wrap::nix_string_callback!(|callback, userdata, ctx: &ErrorContext| {
|
||||
sys::nix_err_info_msg(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
// NOTE: an Err here only occurs when "Last error was not a nix error"
|
||||
wrap::nix_string_callback!(|callback, userdata, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_err_info_msg(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
use std::ffi::{CString, c_void};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::errors::new_nixide_error;
|
||||
|
||||
|
|
@ -18,46 +15,56 @@ use crate::{NixideResult, Store};
|
|||
/// This provides the main interface for evaluating Nix expressions
|
||||
/// and creating values.
|
||||
pub struct EvalState {
|
||||
inner: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
inner: NonNull<sys::EvalState>,
|
||||
|
||||
// XXX: TODO: is an `Arc<Store>` necessary or just a `Store`
|
||||
store: Arc<Store>,
|
||||
store: Store,
|
||||
}
|
||||
|
||||
// impl Clone for EvalState {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
//
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner,
|
||||
// store: self.store.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl AsInnerPtr<sys::EvalState> for EvalState {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::EvalState {
|
||||
self.inner.borrow().as_ptr()
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::EvalState {
|
||||
unsafe { self.inner.borrow().as_ref() }
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::EvalState {
|
||||
unsafe { self.inner.borrow_mut().as_mut() }
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl EvalState {
|
||||
/// Construct a new EvalState directly from its attributes
|
||||
pub(super) fn new(inner: NonNull<sys::EvalState>, store: Arc<Store>) -> Self {
|
||||
///
|
||||
pub(super) fn new(inner: NonNull<sys::EvalState>, store: &Store) -> Self {
|
||||
Self {
|
||||
inner: Rc::new(RefCell::new(inner)),
|
||||
store,
|
||||
inner,
|
||||
store: store.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn inner_ref(&self) -> Rc<RefCell<NonNull<sys::EvalState>>> {
|
||||
self.inner.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn store_ref(&self) -> &Store {
|
||||
self.store.as_ref()
|
||||
pub fn store_ref(&self) -> &Store {
|
||||
&self.store
|
||||
}
|
||||
|
||||
/// Evaluate a Nix expression from a string.
|
||||
|
|
@ -70,7 +77,7 @@ impl EvalState {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if evaluation fails.
|
||||
pub fn eval_from_string(&self, expr: &str, path: &str) -> NixideResult<Value> {
|
||||
pub fn interpret(&self, expr: &str, path: &str) -> NixideResult<Value> {
|
||||
let expr_c = CString::new(expr).or(Err(new_nixide_error!(StringNulByte)))?;
|
||||
let path_c = CString::new(path).or(Err(new_nixide_error!(StringNulByte)))?;
|
||||
|
||||
|
|
@ -92,7 +99,7 @@ impl EvalState {
|
|||
);
|
||||
value
|
||||
})
|
||||
.map(|ptr| Value::from((ptr, self.inner_ref())))
|
||||
.map(|ptr| Value::from((ptr, self)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::ffi::{CString, c_char};
|
||||
use std::ffi::{CString, c_char, c_void};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::EvalState;
|
||||
#[cfg(feature = "flakes")]
|
||||
|
|
@ -15,11 +14,28 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
///
|
||||
/// This allows configuring the evaluation environment before creating
|
||||
/// the evaluation state.
|
||||
///
|
||||
pub struct EvalStateBuilder {
|
||||
inner: NonNull<sys::nix_eval_state_builder>,
|
||||
store: Arc<Store>,
|
||||
store: Store,
|
||||
}
|
||||
|
||||
// impl Clone for EvalStateBuilder {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
//
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner,
|
||||
// store: self.store.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl AsInnerPtr<sys::nix_eval_state_builder> for EvalStateBuilder {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_eval_state_builder {
|
||||
|
|
@ -47,17 +63,15 @@ impl EvalStateBuilder {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the builder cannot be created.
|
||||
pub fn new(store: &Arc<Store>) -> NixideResult<Self> {
|
||||
///
|
||||
pub fn new(store: &Store) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_eval_state_builder_new(ctx.as_ptr(), store.as_ptr())
|
||||
})?;
|
||||
|
||||
// sys::nix_eval_state_builder_load(context, builder);
|
||||
// sys::nix_flake_settings_add_to_eval_state_builder(context, settings, builder);
|
||||
|
||||
Ok(EvalStateBuilder {
|
||||
inner,
|
||||
store: Arc::clone(store),
|
||||
store: store.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -66,18 +80,20 @@ impl EvalStateBuilder {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the evaluation state cannot be built.
|
||||
///
|
||||
pub fn build(self) -> NixideResult<EvalState> {
|
||||
// Build the state
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_eval_state_build(ctx.as_ptr(), self.as_ptr())
|
||||
})?;
|
||||
|
||||
Ok(EvalState::new(inner, self.store.clone()))
|
||||
Ok(EvalState::new(inner, &self.store))
|
||||
}
|
||||
|
||||
// XXX: TODO
|
||||
// XXX: TODO: use `flakes()` instead
|
||||
#[deprecated]
|
||||
#[cfg(feature = "flakes")]
|
||||
fn set_flake_settings(self, settings: FlakeSettings) -> NixideResult<Self> {
|
||||
pub fn set_flake_settings(self, settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_settings_add_to_eval_state_builder(
|
||||
ctx.as_ptr(),
|
||||
|
|
@ -89,7 +105,13 @@ impl EvalStateBuilder {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
fn load_ambient_settings(self) -> NixideResult<Self> {
|
||||
#[cfg(feature = "flakes")]
|
||||
pub fn flakes(self) -> NixideResult<Self> {
|
||||
#[allow(deprecated)]
|
||||
self.set_flake_settings(&FlakeSettings::new()?)
|
||||
}
|
||||
|
||||
pub fn load_ambient_settings(self) -> NixideResult<Self> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_eval_state_builder_load(ctx.as_ptr(), self.as_ptr());
|
||||
})?;
|
||||
|
|
@ -97,7 +119,7 @@ impl EvalStateBuilder {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
fn set_lookup_path<P: AsRef<str>>(self, paths: Vec<P>) -> NixideResult<Self> {
|
||||
pub fn set_lookup_path<P: AsRef<str>>(self, paths: Vec<P>) -> NixideResult<Self> {
|
||||
let paths_len = paths.len();
|
||||
let paths_capacity = paths.capacity();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_char;
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::expr::values::NixString;
|
||||
use crate::stdext::CCharPtrExt;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::LazyArray;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, NixideResult, StorePath};
|
||||
|
||||
|
|
@ -17,6 +17,23 @@ pub struct RealisedString<'a> {
|
|||
pub children: LazyArray<StorePath, Box<dyn Fn(usize) -> StorePath + 'a>>,
|
||||
}
|
||||
|
||||
// impl<'a> Clone for RealisedString<'a> {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
// Self {
|
||||
// inner,
|
||||
// path: self.path.clone(),
|
||||
// children: self.children,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'a> AsInnerPtr<sys::nix_realised_string> for RealisedString<'a> {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_realised_string {
|
||||
|
|
@ -81,7 +98,7 @@ impl<'a> RealisedString<'a> {
|
|||
path: Self::parse_path(inner.as_ptr(), state),
|
||||
children: LazyArray::new(
|
||||
size,
|
||||
Box::new(|_| StorePath::fake_path(unsafe { state.store_ref() }).unwrap()),
|
||||
Box::new(|_| StorePath::fake_path(state.store_ref()).unwrap()),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
|
@ -98,7 +115,7 @@ impl<'a> RealisedString<'a> {
|
|||
err
|
||||
)
|
||||
});
|
||||
StorePath::parse(unsafe { state.store_ref() }, &path_str).unwrap_or_else(|err| {
|
||||
StorePath::parse(state.store_ref(), &path_str).unwrap_or_else(|err| {
|
||||
panic_issue_call_failed!(
|
||||
"`sys::nix_realised_string_get_buffer_(start|size)` invalid store path ({})",
|
||||
err
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::sync::Arc;
|
||||
use std::rc::Rc;
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ use crate::Store;
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_eval_state_builder() {
|
||||
let store = Arc::new(Store::open(None).expect("Failed to open store"));
|
||||
let store = Rc::new(Store::default().expect("Failed to open store"));
|
||||
let _state = EvalStateBuilder::new(&store)
|
||||
.expect("Failed to create builder")
|
||||
.build()
|
||||
|
|
@ -19,14 +19,14 @@ fn test_eval_state_builder() {
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_simple_evaluation() {
|
||||
let store = Arc::new(Store::open(None).expect("Failed to open store"));
|
||||
let store = Rc::new(Store::default().expect("Failed to open store"));
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
.expect("Failed to create builder")
|
||||
.build()
|
||||
.expect("Failed to build state");
|
||||
|
||||
let result = state
|
||||
.eval_from_string("1 + 2", "<eval>")
|
||||
.interpret("1 + 2", "<eval>")
|
||||
.expect("Failed to evaluate expression");
|
||||
|
||||
assert!(matches!(result, Value::Int(_)));
|
||||
|
|
@ -40,7 +40,7 @@ fn test_simple_evaluation() {
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_value_types() {
|
||||
let store = Arc::new(Store::open(None).expect("Failed to open store"));
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
.expect("Failed to create builder")
|
||||
.build()
|
||||
|
|
@ -48,7 +48,7 @@ fn test_value_types() {
|
|||
|
||||
// Test integer
|
||||
let int_val = state
|
||||
.eval_from_string("42", "<eval>")
|
||||
.interpret("42", "<eval>")
|
||||
.expect("Failed to evaluate int");
|
||||
assert!(matches!(int_val, Value::Int(_)));
|
||||
if let Value::Int(value) = int_val {
|
||||
|
|
@ -59,7 +59,7 @@ fn test_value_types() {
|
|||
|
||||
// Test boolean
|
||||
let bool_val = state
|
||||
.eval_from_string("true", "<eval>")
|
||||
.interpret("true", "<eval>")
|
||||
.expect("Failed to evaluate bool");
|
||||
assert!(matches!(bool_val, Value::Bool(_)));
|
||||
if let Value::Bool(value) = bool_val {
|
||||
|
|
@ -70,7 +70,7 @@ fn test_value_types() {
|
|||
|
||||
// Test string
|
||||
let string_val = state
|
||||
.eval_from_string("\"hello\"", "<eval>")
|
||||
.interpret("\"hello\"", "<eval>")
|
||||
.expect("Failed to evaluate string");
|
||||
assert!(matches!(string_val, Value::String(_)));
|
||||
if let Value::String(value) = string_val {
|
||||
|
|
@ -83,7 +83,7 @@ fn test_value_types() {
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_value_formatting() {
|
||||
let store = Arc::new(Store::open(None).expect("Failed to open store"));
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
.expect("Failed to create builder")
|
||||
.build()
|
||||
|
|
@ -91,27 +91,27 @@ fn test_value_formatting() {
|
|||
|
||||
// Test integer formatting
|
||||
let int_val = state
|
||||
.eval_from_string("42", "<eval>")
|
||||
.interpret("42", "<eval>")
|
||||
.expect("Failed to evaluate int");
|
||||
assert_eq!(format!("{int_val}"), "42");
|
||||
assert_eq!(format!("{int_val:?}"), "Value::Int(NixInt(42))");
|
||||
|
||||
// Test boolean formatting
|
||||
let true_val = state
|
||||
.eval_from_string("true", "<eval>")
|
||||
.interpret("true", "<eval>")
|
||||
.expect("Failed to evaluate bool");
|
||||
assert_eq!(format!("{true_val}"), "true");
|
||||
assert_eq!(format!("{true_val:?}"), "Value::Bool(NixBool(true))");
|
||||
|
||||
let false_val = state
|
||||
.eval_from_string("false", "<eval>")
|
||||
.interpret("false", "<eval>")
|
||||
.expect("Failed to evaluate bool");
|
||||
assert_eq!(format!("{false_val}"), "false");
|
||||
assert_eq!(format!("{false_val:?}"), "Value::Bool(NixBool(false))");
|
||||
|
||||
// Test string formatting
|
||||
let str_val = state
|
||||
.eval_from_string("\"hello world\"", "<eval>")
|
||||
.interpret("\"hello world\"", "<eval>")
|
||||
.expect("Failed to evaluate string");
|
||||
assert_eq!(format!("{str_val}"), "hello world");
|
||||
assert_eq!(
|
||||
|
|
@ -121,7 +121,7 @@ fn test_value_formatting() {
|
|||
|
||||
// Test string with quotes
|
||||
let quoted_str = state
|
||||
.eval_from_string("\"say \\\"hello\\\"\"", "<eval>")
|
||||
.interpret("\"say \\\"hello\\\"\"", "<eval>")
|
||||
.expect("Failed to evaluate quoted string");
|
||||
assert_eq!(format!("{quoted_str}"), "say \"hello\"");
|
||||
assert_eq!(
|
||||
|
|
@ -131,14 +131,14 @@ fn test_value_formatting() {
|
|||
|
||||
// Test null formatting
|
||||
let null_val = state
|
||||
.eval_from_string("null", "<eval>")
|
||||
.interpret("null", "<eval>")
|
||||
.expect("Failed to evaluate null");
|
||||
assert_eq!(format!("{null_val}"), "null");
|
||||
assert_eq!(format!("{null_val:?}"), "Value::Null(NixNull)");
|
||||
|
||||
// Test collection formatting
|
||||
let attrs_val = state
|
||||
.eval_from_string("{ a = 1; }", "<eval>")
|
||||
.interpret("{ a = 1; }", "<eval>")
|
||||
.expect("Failed to evaluate attrs");
|
||||
assert_eq!(format!("{attrs_val}"), "{ <attrs> }");
|
||||
assert_eq!(
|
||||
|
|
@ -147,7 +147,7 @@ fn test_value_formatting() {
|
|||
);
|
||||
|
||||
let list_val = state
|
||||
.eval_from_string("[ 1 2 3 ]", "<eval>")
|
||||
.interpret("[ 1 2 3 ]", "<eval>")
|
||||
.expect("Failed to evaluate list");
|
||||
assert_eq!(format!("{list_val}"), "[ <list> ]");
|
||||
assert_eq!(format!("{list_val:?}"), "Value::List(NixList([ <list> ]))");
|
||||
|
|
|
|||
|
|
@ -1,22 +1,38 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixThunk, NixValue, Value};
|
||||
use crate::NixError;
|
||||
use crate::errors::{ErrorContext, NixideError};
|
||||
use crate::stdext::{AsCPtr, CCharPtrExt};
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, NixError};
|
||||
|
||||
pub struct NixAttrs {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
impl Clone for NixAttrs {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixAttrs {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -61,13 +77,17 @@ impl NixValue for NixAttrs {
|
|||
sys::ValueType_NIX_TYPE_ATTRS
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let len = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attrs_size(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Self { inner, state, len }
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +108,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
|
|
@ -99,7 +119,7 @@ impl NixAttrs {
|
|||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = Value::from((inner, self.state.clone()));
|
||||
let value = Value::from((inner, &self.state));
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
|
@ -115,7 +135,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
|
|
@ -126,7 +146,7 @@ impl NixAttrs {
|
|||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = <NixThunk as NixValue>::from(inner, self.state.clone());
|
||||
let value = <NixThunk as NixValue>::from(inner, &self.state);
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
|
@ -137,12 +157,7 @@ impl NixAttrs {
|
|||
}
|
||||
|
||||
let name_ptr = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_name_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
index,
|
||||
)
|
||||
sys::nix_get_attr_name_byidx(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
|
|
@ -161,7 +176,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byname(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
|
|
@ -169,7 +184,7 @@ impl NixAttrs {
|
|||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(Value::from((inner, self.state.clone()))),
|
||||
Ok(inner) => Some(Value::from((inner, &self.state))),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
|
|
@ -187,7 +202,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byname_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
|
|
@ -195,7 +210,7 @@ impl NixAttrs {
|
|||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, self.state.clone())),
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, &self.state)),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
|
|
|
|||
|
|
@ -1,21 +1,37 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixBool {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
value: bool,
|
||||
}
|
||||
|
||||
impl Clone for NixBool {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixBool {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -60,7 +76,7 @@ impl NixValue for NixBool {
|
|||
sys::ValueType_NIX_TYPE_BOOL
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_bool(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -70,7 +86,7 @@ impl NixValue for NixBool {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
state: state.clone(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -11,10 +11,27 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixFloat {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
value: f64,
|
||||
}
|
||||
|
||||
impl Clone for NixFloat {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixFloat {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -59,7 +76,7 @@ impl NixValue for NixFloat {
|
|||
sys::ValueType_NIX_TYPE_FLOAT
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_float(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -69,7 +86,7 @@ impl NixValue for NixFloat {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
state: state.clone(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,33 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixValue, Value};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::SliceExt;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixFunction {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: i64,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixFunction {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixFunction {
|
||||
|
|
@ -60,16 +74,10 @@ impl NixValue for NixFunction {
|
|||
sys::ValueType_NIX_TYPE_FUNCTION
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_int(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
value,
|
||||
state: state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,14 +88,14 @@ impl NixFunction {
|
|||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr())
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_call(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.as_ptr(),
|
||||
arg.as_ptr(),
|
||||
inner.as_ptr(),
|
||||
|
|
@ -95,7 +103,7 @@ impl NixFunction {
|
|||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
Value::from((inner, &self.state))
|
||||
}
|
||||
|
||||
pub fn call_many<T>(&self, args: &[&T]) -> Value
|
||||
|
|
@ -103,14 +111,14 @@ impl NixFunction {
|
|||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().as_ptr())
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_call_multi(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.as_ptr(),
|
||||
args.len(),
|
||||
args.into_c_array(),
|
||||
|
|
@ -119,7 +127,7 @@ impl NixFunction {
|
|||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
Value::from((inner, &self.state))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -11,10 +11,27 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixInt {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
impl Clone for NixInt {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixInt {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -59,7 +76,7 @@ impl NixValue for NixInt {
|
|||
sys::ValueType_NIX_TYPE_INT
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_int(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -67,7 +84,7 @@ impl NixValue for NixInt {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
state: state.clone(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixThunk, NixValue, Value};
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -11,7 +11,23 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixList {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixList {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixList {
|
||||
|
|
@ -58,8 +74,11 @@ impl NixValue for NixList {
|
|||
sys::ValueType_NIX_TYPE_LIST
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,29 +117,19 @@ impl NixList {
|
|||
|
||||
pub fn get(&self, index: u32) -> Value {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_list_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
sys::nix_get_list_byidx(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, self.state.clone()))
|
||||
Value::from((inner, &self.state))
|
||||
}
|
||||
|
||||
pub fn get_lazy(&self, index: u32) -> NixThunk {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_list_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
sys::nix_get_list_byidx_lazy(ctx.as_ptr(), self.as_ptr(), self.state.as_ptr(), index)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
<NixThunk as NixValue>::from(inner, self.state.clone())
|
||||
<NixThunk as NixValue>::from(inner, &self.state)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,8 @@ pub use path::NixPath;
|
|||
pub use string::NixString;
|
||||
pub use thunk::NixThunk;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
|
|
@ -40,12 +38,12 @@ use crate::sys::{
|
|||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
pub trait NixValue: Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
|
||||
pub trait NixValue: Clone + Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
|
||||
/// TODO
|
||||
fn type_id(&self) -> sys::ValueType;
|
||||
|
||||
/// TODO
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self;
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self;
|
||||
}
|
||||
|
||||
/// A Nix value
|
||||
|
|
@ -111,22 +109,12 @@ pub enum Value {
|
|||
// Failed(NixFailed),
|
||||
}
|
||||
|
||||
impl
|
||||
From<(
|
||||
NonNull<sys::nix_value>,
|
||||
Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
)> for Value
|
||||
{
|
||||
fn from(
|
||||
value: (
|
||||
NonNull<sys::nix_value>,
|
||||
Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
),
|
||||
) -> Self {
|
||||
impl From<(NonNull<sys::nix_value>, &EvalState)> for Value {
|
||||
fn from(value: (NonNull<sys::nix_value>, &EvalState)) -> Self {
|
||||
let (inner, state) = value;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_force(ctx.as_ptr(), state.borrow().as_ptr(), inner.as_ptr())
|
||||
sys::nix_value_force(ctx.as_ptr(), state.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
|
|
@ -197,13 +185,3 @@ impl Debug for Value {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// macro_rules! is_type {
|
||||
// ($expr:expr, $tt:tt) => {{
|
||||
// match $expr {
|
||||
// $tt => true,
|
||||
// _ => false,
|
||||
// }
|
||||
// }};
|
||||
// }
|
||||
// pub(self) use is_type;
|
||||
|
|
|
|||
|
|
@ -1,16 +1,33 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
pub struct NixNull {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixNull {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixNull {
|
||||
|
|
@ -57,7 +74,10 @@ impl NixValue for NixNull {
|
|||
sys::ValueType_NIX_TYPE_NULL
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,39 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::CCharPtrExt;
|
||||
use crate::sys;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixPath {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
value: PathBuf,
|
||||
}
|
||||
|
||||
impl Clone for NixPath {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixPath {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -62,7 +78,7 @@ impl NixValue for NixPath {
|
|||
sys::ValueType_NIX_TYPE_PATH
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let value = wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_path_string(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -72,7 +88,7 @@ impl NixValue for NixPath {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
state: state.clone(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,37 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::NixValue;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, sys};
|
||||
|
||||
pub struct NixString {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl Clone for NixString {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixString {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -61,7 +76,7 @@ impl NixValue for NixString {
|
|||
sys::ValueType_NIX_TYPE_STRING
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
let value = wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_string(
|
||||
|
|
@ -76,7 +91,7 @@ impl NixValue for NixString {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state,
|
||||
state: state.clone(),
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::c_void;
|
||||
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{NixValue, Value};
|
||||
use crate::EvalState;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -11,7 +11,23 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixThunk {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixThunk {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixThunk {
|
||||
|
|
@ -58,26 +74,21 @@ impl NixValue for NixThunk {
|
|||
sys::ValueType_NIX_TYPE_THUNK
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl NixThunk {
|
||||
// fn to_inner(self) -> NonNull<sys::nix_value> {
|
||||
// self.inner
|
||||
// }
|
||||
|
||||
pub fn eval(self) -> Value {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_force(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.inner.as_ptr(),
|
||||
)
|
||||
sys::nix_value_force(ctx.as_ptr(), self.state.as_ptr(), self.inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((self.inner, self.state.to_owned()))
|
||||
Value::from((self.inner, &self.state))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
use super::FlakeSettings;
|
||||
use crate::{EvalStateBuilder, NixideError};
|
||||
|
||||
pub trait EvalStateBuilderExt {
|
||||
/// Configures the eval state to provide flakes features such as `builtins.getFlake`.
|
||||
fn flakes(self, settings: &FlakeSettings) -> Result<EvalStateBuilder, NixideError>;
|
||||
}
|
||||
|
||||
impl EvalStateBuilderExt for EvalStateBuilder {
|
||||
/// Configures the eval state to provide flakes features such as `builtins.getFlake`.
|
||||
fn flakes(mut self, settings: &FlakeSettings) -> Result<EvalStateBuilder, NixideError> {
|
||||
settings.add_to_eval_state_builder(&mut self).map(|_| self)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,39 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
|
||||
pub(super) struct FetchersSettings {
|
||||
pub(super) ptr: NonNull<sys::nix_fetchers_settings>,
|
||||
pub struct FetchersSettings {
|
||||
inner: NonNull<sys::nix_fetchers_settings>,
|
||||
}
|
||||
|
||||
impl FetchersSettings {
|
||||
pub fn new() -> Result<Self, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
let ptr = unsafe { sys::nix_fetchers_settings_new(ctx.as_ptr()) };
|
||||
Ok(FetchersSettings {
|
||||
ptr: NonNull::new(ptr).ok_or(new_nixide_error!(NullPtr))?,
|
||||
})
|
||||
}
|
||||
pub fn new() -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_new(ctx.as_ptr())
|
||||
})?;
|
||||
|
||||
pub(crate) unsafe fn as_ptr(&self) -> *mut sys::nix_fetchers_settings {
|
||||
self.ptr.as_ptr()
|
||||
Ok(Self { inner })
|
||||
}
|
||||
}
|
||||
|
||||
// impl Clone for FetchersSettings {
|
||||
// fn clone(&self) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner: self.inner.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Drop for FetchersSettings {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
|
@ -31,6 +42,23 @@ impl Drop for FetchersSettings {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_fetchers_settings> for FetchersSettings {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_fetchers_settings {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_fetchers_settings {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_fetchers_settings {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
use std::ffi::CString;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::{FlakeReference, FlakeSettings};
|
||||
use crate::errors::new_nixide_error;
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FlakeLockMode {
|
||||
/// Configures [LockedFlake::lock] to make incremental changes to the lock file as needed. Changes are written to file.
|
||||
///
|
||||
WriteAsNeeded,
|
||||
|
||||
/// Like [FlakeLockMode::WriteAsNeeded], but does not write to the lock file.
|
||||
///
|
||||
Virtual,
|
||||
|
||||
/// Make [LockedFlake::lock] check if the lock file is up to date. If not, an error is returned.
|
||||
///
|
||||
Check,
|
||||
}
|
||||
|
||||
|
|
@ -24,6 +28,20 @@ pub enum FlakeLockMode {
|
|||
pub struct FlakeLockFlags {
|
||||
pub(crate) inner: NonNull<sys::nix_flake_lock_flags>,
|
||||
}
|
||||
|
||||
// impl Clone for FlakeLockFlags {
|
||||
// fn clone(&self) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner: self.inner.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Drop for FlakeLockFlags {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
|
@ -31,69 +49,49 @@ impl Drop for FlakeLockFlags {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl FlakeLockFlags {
|
||||
// XXX: TODO: what is the default FlakeLockMode?
|
||||
pub fn new(settings: &FlakeSettings) -> Result<Self, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
NonNull::new(unsafe { sys::nix_flake_lock_flags_new(ctx.as_ptr(), settings.as_ptr()) })
|
||||
.ok_or(new_nixide_error!(NullPtr))
|
||||
.map(|inner| FlakeLockFlags { inner })
|
||||
}
|
||||
|
||||
pub(crate) fn as_ptr(&self) -> *mut sys::nix_flake_lock_flags {
|
||||
impl AsInnerPtr<sys::nix_flake_lock_flags> for FlakeLockFlags {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_lock_flags {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
pub fn set_lock_mode(&mut self, mode: &FlakeLockMode) -> Result<(), NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
match mode {
|
||||
FlakeLockMode::WriteAsNeeded => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_write_as_needed(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
FlakeLockMode::Virtual => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_virtual(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
FlakeLockMode::Check => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_check(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
};
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_flake_lock_flags {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
/// Configures [LockedFlake::lock] to make incremental changes to the lock file as needed. Changes are written to file.
|
||||
// pub fn set_mode_write_as_needed(&mut self) -> Result<(), NixideError> {
|
||||
// ErrorContext::new().and_then(|ctx| {
|
||||
// NixideError::from(
|
||||
// unsafe {
|
||||
// sys::nix_flake_lock_flags_set_mode_write_as_needed(ctx.as_ptr(), self.as_ptr())
|
||||
// },
|
||||
// "nix_flake_lock_flags_set_mode_write_as_needed",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_flake_lock_flags {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Make [LockedFlake::lock] check if the lock file is up to date. If not, an error is returned.
|
||||
// pub fn set_mode_check(&mut self) -> Result<(), NixideError> {
|
||||
// ErrorContext::new().and_then(|ctx| {
|
||||
// NixideError::from(
|
||||
// unsafe { sys::nix_flake_lock_flags_set_mode_check(ctx.as_ptr(), self.as_ptr()) },
|
||||
// "nix_flake_lock_flags_set_mode_check",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
impl FlakeLockFlags {
|
||||
// XXX: TODO: what is the default FlakeLockMode?
|
||||
pub fn new(settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_new(ctx.as_ptr(), settings.as_ptr())
|
||||
})?;
|
||||
|
||||
/// Like `set_mode_write_as_needed`, but does not write to the lock file.
|
||||
// pub fn set_mode_virtual(&mut self) -> Result<(), NixideError> {
|
||||
// ErrorContext::new().and_then(|ctx| {
|
||||
// NixideError::from(
|
||||
// unsafe { sys::nix_flake_lock_flags_set_mode_virtual(ctx.as_ptr(), self.as_ptr()) },
|
||||
// "nix_flake_lock_flags_set_mode_virtual",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
Ok(FlakeLockFlags { inner })
|
||||
}
|
||||
|
||||
pub fn set_mode(&mut self, mode: &FlakeLockMode) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| {
|
||||
match mode {
|
||||
FlakeLockMode::WriteAsNeeded => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_write_as_needed(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
FlakeLockMode::Virtual => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_virtual(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
FlakeLockMode::Check => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_check(ctx.as_ptr(), self.as_ptr())
|
||||
},
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds an input override to the lock file that will be produced.
|
||||
/// The [LockedFlake::lock] operation will not write to the lock file.
|
||||
|
|
@ -106,26 +104,17 @@ impl FlakeLockFlags {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `path` - The input name/path to override (must not be empty)
|
||||
/// * `flake_ref` - The flake reference to use as the override
|
||||
pub fn override_input(
|
||||
&mut self,
|
||||
path: &str,
|
||||
flakeref: &FlakeReference,
|
||||
) -> Result<(), NixideError> {
|
||||
let input_path = CString::new(path).or_else(|_| Err(new_nixide_error!(StringNulByte)));
|
||||
/// * `flakeref` - The flake reference to use as the override
|
||||
pub fn override_input(&mut self, path: &str, flakeref: &FlakeReference) -> NixideResult<()> {
|
||||
let input_path = path.as_c_ptr()?;
|
||||
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_add_input_override(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
input_path.as_ptr(),
|
||||
input_path,
|
||||
flakeref.as_ptr(),
|
||||
)
|
||||
};
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,58 +1,99 @@
|
|||
use std::ffi::c_void;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr::{null_mut, NonNull};
|
||||
use std::ptr::{NonNull, null_mut};
|
||||
|
||||
use super::{FetchersSettings, FlakeReferenceParseFlags, FlakeSettings};
|
||||
use crate::errors::new_nixide_error;
|
||||
use crate::sys;
|
||||
use crate::util::bindings::wrap_nix_string_callback;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
// XXX: TODO: rename FlakeReference -> FlakeRef
|
||||
pub struct FlakeReference {
|
||||
pub(crate) ptr: NonNull<sys::nix_flake_reference>,
|
||||
inner: NonNull<sys::nix_flake_reference>,
|
||||
fragment: String,
|
||||
}
|
||||
|
||||
// impl Clone for FlakeReference {
|
||||
// fn clone(&self) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner: self.inner.clone(),
|
||||
// fragment: self.fragment.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Drop for FlakeReference {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_flake_reference_free(self.ptr.as_ptr());
|
||||
sys::nix_flake_reference_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_flake_reference> for FlakeReference {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_reference {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_flake_reference {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_flake_reference {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl FlakeReference {
|
||||
pub fn as_ptr(&self) -> *mut sys::nix_flake_reference {
|
||||
self.ptr.as_ptr()
|
||||
}
|
||||
|
||||
/// Parse a flake reference from a string.
|
||||
/// The string must be a valid flake reference, such as `github:owner/repo`.
|
||||
/// It may also be suffixed with a `#` and a fragment, such as `github:owner/repo#something`,
|
||||
/// in which case, the returned string will contain the fragment.
|
||||
pub fn parse_with_fragment(
|
||||
pub fn parse(
|
||||
fetch_settings: &FetchersSettings,
|
||||
flake_settings: &FlakeSettings,
|
||||
flags: &FlakeReferenceParseFlags,
|
||||
reference: &str,
|
||||
) -> Result<(FlakeReference, String), NixideError> {
|
||||
) -> Result<FlakeReference, NixideError> {
|
||||
let mut ptr: *mut sys::nix_flake_reference = null_mut();
|
||||
let result = wrap_nix_string_callback(|ctx, callback, user_data| unsafe {
|
||||
sys::nix_flake_reference_and_fragment_from_string(
|
||||
ctx.as_ptr(),
|
||||
fetch_settings.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
flags.as_ptr(),
|
||||
reference.as_ptr() as *const c_char,
|
||||
reference.len(),
|
||||
&mut ptr,
|
||||
Some(callback),
|
||||
user_data,
|
||||
)
|
||||
});
|
||||
let fragment = wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_reference_and_fragment_from_string(
|
||||
ctx.as_ptr(),
|
||||
fetch_settings.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
flags.as_ptr(),
|
||||
reference.as_ptr() as *const c_char,
|
||||
reference.len(),
|
||||
&mut ptr,
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
}
|
||||
)?;
|
||||
|
||||
match NonNull::new(ptr) {
|
||||
Some(ptr) => result.map(|s| (FlakeReference { ptr }, s)),
|
||||
Some(inner) => Ok(FlakeReference { inner, fragment }),
|
||||
None => Err(new_nixide_error!(NullPtr)),
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: TODO: is it possible to get the URI string itself? (minus the fragment part?)
|
||||
/// Get a shared reference to the URI fragment part.
|
||||
///
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn fragment(&self) -> &str {
|
||||
&self.fragment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,58 +1,77 @@
|
|||
use std::ffi::c_void;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::FlakeSettings;
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
|
||||
/// Parameters for parsing a flake reference.
|
||||
#[derive(Debug)]
|
||||
pub struct FlakeReferenceParseFlags {
|
||||
pub(crate) ptr: NonNull<sys::nix_flake_reference_parse_flags>,
|
||||
inner: NonNull<sys::nix_flake_reference_parse_flags>,
|
||||
}
|
||||
|
||||
// impl Clone for FlakeReferenceParseFlags {
|
||||
// fn clone(&self) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner: self.inner.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Drop for FlakeReferenceParseFlags {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_flake_reference_parse_flags_free(self.ptr.as_ptr());
|
||||
sys::nix_flake_reference_parse_flags_free(self.inner.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_flake_reference_parse_flags> for FlakeReferenceParseFlags {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_reference_parse_flags {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_flake_reference_parse_flags {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_flake_reference_parse_flags {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl FlakeReferenceParseFlags {
|
||||
pub fn new(settings: &FlakeSettings) -> Result<Self, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
let ptr =
|
||||
unsafe { sys::nix_flake_reference_parse_flags_new(ctx.as_ptr(), settings.as_ptr()) };
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => NonNull::new(ptr).map_or(Err(new_nixide_error!(NullPtr)), |ptr| {
|
||||
Ok(FlakeReferenceParseFlags { ptr })
|
||||
}),
|
||||
}
|
||||
pub fn new(settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_reference_parse_flags_new(ctx.as_ptr(), settings.as_ptr())
|
||||
})?;
|
||||
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
/// Sets the [base directory](https://nix.dev/manual/nix/latest/glossary#gloss-base-directory)
|
||||
/// for resolving local flake references.
|
||||
pub fn set_base_directory(&mut self, base_directory: &str) -> Result<(), NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
pub fn set_base_directory(&mut self, base_directory: &str) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_reference_parse_flags_set_base_directory(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
base_directory.as_ptr() as *const c_char,
|
||||
base_directory.len(),
|
||||
)
|
||||
};
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut sys::nix_flake_reference_parse_flags {
|
||||
self.ptr.as_ptr()
|
||||
);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,15 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalStateBuilder, NixideError};
|
||||
|
||||
/// Store settings for the flakes feature.
|
||||
pub struct FlakeSettings {
|
||||
pub(crate) inner: NonNull<sys::nix_flake_settings>,
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_flake_settings> for FlakeSettings {
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_settings {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl FlakeSettings {
|
||||
pub fn new() -> Result<Self, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
let opt = NonNull::new(unsafe { sys::nix_flake_settings_new(ctx.as_ptr()) });
|
||||
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => match opt {
|
||||
Some(inner) => Ok(FlakeSettings { inner }),
|
||||
None => Err(new_nixide_error!(NullPtr)),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_to_eval_state_builder(
|
||||
&self,
|
||||
builder: &mut EvalStateBuilder,
|
||||
) -> Result<(), NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_flake_settings_add_to_eval_state_builder(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
builder.as_ptr(),
|
||||
)
|
||||
};
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
inner: NonNull<sys::nix_flake_settings>,
|
||||
}
|
||||
|
||||
impl Drop for FlakeSettings {
|
||||
|
|
@ -56,3 +19,43 @@ impl Drop for FlakeSettings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl Clone for FlakeSettings {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
//
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self { inner }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl AsInnerPtr<sys::nix_flake_settings> for FlakeSettings {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_settings {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_flake_settings {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_flake_settings {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl FlakeSettings {
|
||||
pub fn new() -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_settings_new(ctx.as_ptr())
|
||||
})?;
|
||||
|
||||
Ok(Self { inner })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,145 +1,184 @@
|
|||
// XXX: TODO: find a way to read directly from FlakeSettings and FetchersSettings (the C++ classes)
|
||||
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::{FetchersSettings, FlakeLockFlags, FlakeReference, FlakeSettings};
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, NixideError, Value};
|
||||
use crate::{EvalState, NixideResult, Value};
|
||||
|
||||
pub struct LockedFlake {
|
||||
pub(crate) ptr: NonNull<sys::nix_locked_flake>,
|
||||
inner: NonNull<sys::nix_locked_flake>,
|
||||
|
||||
flakeref: FlakeReference,
|
||||
state: EvalState,
|
||||
flags: FlakeLockFlags,
|
||||
fetch_settings: FetchersSettings,
|
||||
flake_settings: FlakeSettings,
|
||||
}
|
||||
|
||||
// impl Clone for LockedFlake {
|
||||
// fn clone(&self) -> Self {
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self {
|
||||
// inner: self.inner.clone(),
|
||||
// flakeref: self.flakeref.clone(),
|
||||
// state: self.state.clone(),
|
||||
// flags: self.flags.clone(),
|
||||
// fetch_settings: self.fetch_settings.clone(),
|
||||
// flake_settings: self.flake_settings.clone(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Drop for LockedFlake {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_locked_flake_free(self.ptr.as_ptr());
|
||||
sys::nix_locked_flake_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_locked_flake> for LockedFlake {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_locked_flake {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_locked_flake {
|
||||
unsafe { self.inner.as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::nix_locked_flake {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl LockedFlake {
|
||||
pub fn lock(
|
||||
fetch_settings: &FetchersSettings,
|
||||
flake_settings: &FlakeSettings,
|
||||
eval_state: &EvalState,
|
||||
state: &EvalState,
|
||||
flags: &FlakeLockFlags,
|
||||
flake_ref: &FlakeReference,
|
||||
) -> Result<LockedFlake, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
|
||||
let ptr = NonNull::new(unsafe {
|
||||
flakeref: &FlakeReference,
|
||||
) -> NixideResult<LockedFlake> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock(
|
||||
ctx.as_ptr(),
|
||||
fetch_settings.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
eval_state.as_ptr(),
|
||||
state.as_ptr(),
|
||||
flags.as_ptr(),
|
||||
flake_ref.as_ptr(),
|
||||
flakeref.as_ptr(),
|
||||
)
|
||||
});
|
||||
})?;
|
||||
|
||||
match ptr {
|
||||
Some(ptr) => Ok(LockedFlake { ptr }),
|
||||
None => Err(new_nixide_error!(NullPtr)),
|
||||
}
|
||||
Ok(Self {
|
||||
inner,
|
||||
flakeref: flakeref.clone(),
|
||||
state: state.clone(),
|
||||
flags: flags.clone(),
|
||||
fetch_settings: fetch_settings.clone(),
|
||||
flake_settings: flake_settings.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the outputs of the flake - the result of calling the `outputs` attribute.
|
||||
pub fn outputs(
|
||||
&self,
|
||||
flake_settings: &FlakeSettings,
|
||||
eval_state: &mut EvalState,
|
||||
) -> Result<Value, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
|
||||
let r = unsafe {
|
||||
pub fn outputs(&self) -> NixideResult<Value> {
|
||||
let value = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_locked_flake_get_output_attrs(
|
||||
ctx.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
eval_state.as_ptr(),
|
||||
self.ptr.as_ptr(),
|
||||
self.flake_settings.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.inner.as_ptr(),
|
||||
)
|
||||
};
|
||||
Ok(nix_bindings_expr::value::__private::raw_value_new(r))
|
||||
})?;
|
||||
|
||||
Ok(Value::from((value, &self.state)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// use nix_bindings_expr::eval_state::{gc_register_my_thread, EvalStateBuilder};
|
||||
|
||||
use crate::flake::{FlakeLockMode, FlakeReferenceParseFlags};
|
||||
use crate::{EvalStateBuilder, Store};
|
||||
|
||||
use super::*;
|
||||
use std::fs;
|
||||
use std::sync::Once;
|
||||
|
||||
use super::{FetchersSettings, FlakeLockFlags, FlakeReference, FlakeSettings, LockedFlake};
|
||||
use crate::flake::{FlakeLockMode, FlakeReferenceParseFlags};
|
||||
use crate::{EvalStateBuilder, Store, Value, set_global_setting};
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
fn init() {
|
||||
// Only set experimental-features once to minimize the window where
|
||||
// concurrent Nix operations might read the setting while it's being modified
|
||||
INIT.call_once(|| {
|
||||
nix_bindings_expr::eval_state::init().unwrap();
|
||||
nix_bindings_util::settings::set("experimental-features", "flakes").unwrap();
|
||||
INIT.call_once(|| unsafe {
|
||||
set_global_setting("experimental-features", "flakes").unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flake_settings_getflake_exists() {
|
||||
init();
|
||||
let gc_registration = gc_register_my_thread();
|
||||
let store = Store::open(None, []).unwrap();
|
||||
let mut eval_state = EvalStateBuilder::new(store)
|
||||
|
||||
let store = Store::default().expect("Failed to open store connection");
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
.unwrap()
|
||||
.flakes(&FlakeSettings::new().unwrap())
|
||||
.flakes()
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let v = eval_state
|
||||
.eval_from_string("builtins?getFlake", "<test>")
|
||||
.unwrap();
|
||||
let value = state.interpret("builtins?getFlake", "<test>").unwrap();
|
||||
|
||||
let b = eval_state.require_bool(&v).unwrap();
|
||||
|
||||
assert!(b);
|
||||
|
||||
drop(gc_registration);
|
||||
assert!(matches!(value, Value::Bool(_)));
|
||||
if let Value::Bool(v) = value {
|
||||
assert!(v.as_bool());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flake_lock_load_flake() {
|
||||
init();
|
||||
let gc_registration = gc_register_my_thread();
|
||||
let store = Store::open(None, []).unwrap();
|
||||
let fetchers_settings = FetchersSettings::new().unwrap();
|
||||
let flake_settings = FlakeSettings::new().unwrap();
|
||||
let mut eval_state = EvalStateBuilder::new(store)
|
||||
.unwrap()
|
||||
.flakes(&flake_settings)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let tmp_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
// Create flake.nix
|
||||
let tmp_dir = tempfile::tempdir().unwrap();
|
||||
let flake_nix = tmp_dir.path().join("flake.nix");
|
||||
std::fs::write(
|
||||
fs::write(
|
||||
&flake_nix,
|
||||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "potato";
|
||||
hello = "world";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let store = Store::default().unwrap();
|
||||
let flake_settings = FlakeSettings::new().unwrap();
|
||||
|
||||
let mut eval_state = EvalStateBuilder::new(&store)
|
||||
.unwrap()
|
||||
.set_flake_settings(&flake_settings)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let fetchers_settings = FetchersSettings::new().unwrap();
|
||||
let flake_lock_flags = FlakeLockFlags::new(&flake_settings).unwrap();
|
||||
|
||||
let (flake_ref, fragment) = FlakeReference::parse_with_fragment(
|
||||
let flakeref = FlakeReference::parse(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&FlakeReferenceParseFlags::new(&flake_settings).unwrap(),
|
||||
|
|
@ -147,41 +186,40 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(fragment, "subthing");
|
||||
assert_eq!(flakeref.fragment(), "subthing");
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref,
|
||||
&flakeref,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert_eq!(hello, "potato");
|
||||
|
||||
drop(fetchers_settings);
|
||||
drop(tmp_dir);
|
||||
drop(gc_registration);
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "world");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flake_lock_load_flake_with_flags() {
|
||||
init();
|
||||
let gc_registration = gc_register_my_thread();
|
||||
let store = Store::open(None, []).unwrap();
|
||||
|
||||
let store = Store::default().unwrap();
|
||||
let fetchers_settings = FetchersSettings::new().unwrap();
|
||||
let flake_settings = FlakeSettings::new().unwrap();
|
||||
let mut eval_state = EvalStateBuilder::new(store)
|
||||
let mut eval_state = EvalStateBuilder::new(&store)
|
||||
.unwrap()
|
||||
.flakes(&flake_settings)
|
||||
.set_flake_settings(&flake_settings)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
|
@ -222,7 +260,7 @@ mod tests {
|
|||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "BOB";
|
||||
hello = "ALICE";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
|
|
@ -251,7 +289,7 @@ mod tests {
|
|||
.set_base_directory(tmp_dir.path().to_str().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let (flake_ref_a, fragment) = FlakeReference::parse_with_fragment(
|
||||
let flakeref_a = FlakeReference::parse(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&flake_reference_parse_flags,
|
||||
|
|
@ -259,20 +297,17 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(fragment, "");
|
||||
assert_eq!(flakeref_a.fragment(), "");
|
||||
|
||||
// Step 1: Do not update (check), fails
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
);
|
||||
// Has not been locked and would need to write a lock file.
|
||||
assert!(locked_flake.is_err());
|
||||
|
|
@ -282,54 +317,50 @@ mod tests {
|
|||
};
|
||||
|
||||
// Step 2: Update but do not write, succeeds
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Virtual)
|
||||
.unwrap();
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Virtual).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert_eq!(hello, "BOB");
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: The lock was not written, so Step 1 would fail again
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
);
|
||||
// Has not been locked and would need to write a lock file.
|
||||
assert!(locked_flake.is_err());
|
||||
match locked_flake {
|
||||
Ok(_) => panic!("Expected error, but got Ok"),
|
||||
Err(e) => {
|
||||
assert_eq!(e.to_string(), saved_err.to_string());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Step 4: Update and write, succeeds
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.set_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
|
|
@ -337,100 +368,110 @@ mod tests {
|
|||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert_eq!(hello, "BOB");
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Lock was written, so Step 1 succeeds
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert_eq!(hello, "BOB");
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Lock with override, do not write
|
||||
|
||||
// This shouldn't matter; write_as_needed will be overridden
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.set_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.unwrap();
|
||||
|
||||
let (flake_ref_c, fragment) = FlakeReference::parse_with_fragment(
|
||||
let flakeref_c = FlakeReference::parse(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&flake_reference_parse_flags,
|
||||
&format!("path:{}", &flake_dir_c_str),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(fragment, "");
|
||||
assert_eq!(flakeref_c.fragment(), "");
|
||||
|
||||
flake_lock_flags.override_input("b", &flake_ref_c).unwrap();
|
||||
flake_lock_flags.override_input("b", &flakeref_c).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert_eq!(hello, "Claire");
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "Claire");
|
||||
}
|
||||
}
|
||||
|
||||
// Can't delete overrides, so trash it
|
||||
let mut flake_lock_flags = FlakeLockFlags::new(&flake_settings).unwrap();
|
||||
|
||||
// Step 7: Override was not written; lock still points to b
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
assert_eq!(hello, "BOB");
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
drop(fetchers_settings);
|
||||
drop(tmp_dir);
|
||||
drop(gc_registration);
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ mod flake_reference_parse_flags;
|
|||
mod flake_settings;
|
||||
mod locked_flake;
|
||||
|
||||
pub(self) use fetchers_settings::FetchersSettings;
|
||||
pub(self) use flake_lock_flags::{FlakeLockFlags, FlakeLockMode};
|
||||
pub(self) use flake_reference::FlakeReference;
|
||||
pub(self) use flake_reference_parse_flags::FlakeReferenceParseFlags;
|
||||
use fetchers_settings::FetchersSettings;
|
||||
use flake_lock_flags::{FlakeLockFlags, FlakeLockMode};
|
||||
use flake_reference::FlakeReference;
|
||||
use flake_reference_parse_flags::FlakeReferenceParseFlags;
|
||||
pub use flake_settings::FlakeSettings;
|
||||
pub use locked_flake::LockedFlake;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@ use super::util::wrappers::AsInnerPtr as _;
|
|||
|
||||
pub(crate) static mut LIBNIX_INIT_STATUS: Option<NixideResult<()>> = None;
|
||||
|
||||
/// Initialises the Nix `libutil` library's global state.
|
||||
/// This function **should not be run directly!** `#[ctor]` ensures it runs at init-time.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// `sys::nix_libexpr_init` internally runs `sys::nix_libutil_init` and `sys::nix_libstore_init`.
|
||||
/// Hence this method isn't registered via `#[ctor]` if the `exprs` feature is enabled.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
|
|
@ -16,7 +24,7 @@ pub(crate) static mut LIBNIX_INIT_STATUS: Option<NixideResult<()>> = None;
|
|||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
#[cfg(not(feature = "exprs"))]
|
||||
fn init_libutil() {
|
||||
pub(crate) fn init_libutil() {
|
||||
unsafe {
|
||||
if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) {
|
||||
LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
|
|
@ -26,6 +34,14 @@ fn init_libutil() {
|
|||
}
|
||||
}
|
||||
|
||||
/// Initialises the Nix `libstore` library's global state.
|
||||
/// This function **should not be run directly!** `#[ctor]` ensures it runs at init-time.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// `sys::nix_libexpr_init` internally runs `sys::nix_libutil_init` and `sys::nix_libstore_init`.
|
||||
/// Hence this method isn't registered via `#[ctor]` if the `exprs` feature is enabled.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
|
|
@ -35,7 +51,7 @@ fn init_libutil() {
|
|||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
#[cfg(all(feature = "store", not(feature = "exprs")))]
|
||||
fn init_libstore() {
|
||||
pub(crate) fn init_libstore() {
|
||||
// XXX: TODO: how do I support `sys::nix_libstore_init_no_load_config(context)`?
|
||||
unsafe {
|
||||
if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) {
|
||||
|
|
@ -46,7 +62,12 @@ fn init_libstore() {
|
|||
}
|
||||
}
|
||||
|
||||
/// `sys::nix_libexpr_init` internally runs
|
||||
/// Initialises the Nix `libexpr` library's global state.
|
||||
/// This function **should not be run directly!** `#[ctor]` ensures it runs at init-time.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// `sys::nix_libexpr_init` internally runs `sys::nix_libutil_init` and `sys::nix_libstore_init`.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
|
|
@ -57,7 +78,7 @@ fn init_libstore() {
|
|||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
#[cfg(feature = "exprs")]
|
||||
fn init_libexpr() {
|
||||
pub(crate) fn init_libexpr() {
|
||||
unsafe {
|
||||
if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) {
|
||||
LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ pub extern crate nixide_sys as sys;
|
|||
|
||||
pub(crate) mod errors;
|
||||
mod init;
|
||||
mod nix_settings;
|
||||
mod stdext;
|
||||
pub(crate) mod util;
|
||||
mod verbosity;
|
||||
|
|
@ -21,6 +22,7 @@ mod flake;
|
|||
mod store;
|
||||
|
||||
pub use errors::{NixError, NixideError, NixideResult};
|
||||
pub use nix_settings::{get_global_setting, set_global_setting};
|
||||
pub use verbosity::{NixVerbosity, set_verbosity};
|
||||
pub use version::NixVersion;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
use std::ffi::c_void;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr as _;
|
||||
|
||||
/// # Note
|
||||
/// This function is intentionally marked unsafe to discourage its use.
|
||||
/// Please prefer [nixide::FlakeSettings] and [nixide::FetchersSettings].
|
||||
///
|
||||
pub unsafe fn get_global_setting<S: AsRef<str>>(key: S) -> NixideResult<String> {
|
||||
let key = key.as_c_ptr()?;
|
||||
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_setting_get(ctx.as_ptr(), key, Some(callback), userdata as *mut c_void);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// # Note
|
||||
/// This function is intentionally marked unsafe to discourage its use.
|
||||
/// Please prefer [nixide::FlakeSettings] and [nixide::FetchersSettings].
|
||||
///
|
||||
pub unsafe fn set_global_setting<S: AsRef<str>, T: AsRef<str>>(
|
||||
key: S,
|
||||
value: T,
|
||||
) -> NixideResult<()> {
|
||||
let key = key.as_c_ptr()?;
|
||||
let value = value.as_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_setting_set(ctx.as_ptr(), key, value);
|
||||
})
|
||||
}
|
||||
|
|
@ -1,13 +1,4 @@
|
|||
// XXX: TODO: should I add support for `nix_libstore_init_no_load_config`
|
||||
// XXX: TODO: add support for nix_realised_string_* family of functions
|
||||
// nix_realised_string_get_store_path
|
||||
// nix_realised_string_get_store_path_count
|
||||
// # nix_store_real_path
|
||||
// # nix_store_is_valid_path
|
||||
// # nix_store_get_version
|
||||
// # nix_store_get_uri
|
||||
// # nix_store_get_storedir
|
||||
// # nix_store_copy_closure
|
||||
// nix_libstore_init_no_load_config
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
@ -16,25 +7,38 @@ mod tests;
|
|||
mod path;
|
||||
pub use path::*;
|
||||
|
||||
use std::ffi::{c_char, c_void, CString};
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::{null, null_mut, NonNull};
|
||||
use std::result::Result;
|
||||
use std::ptr::{NonNull, null, null_mut};
|
||||
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::stdext::CCharPtrExt;
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::{AsCPtr as _, CCharPtrExt as _};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{NixideError, NixideResult};
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
/// Nix store for managing packages and derivations.
|
||||
///
|
||||
/// The store provides access to Nix packages, derivations, and store paths.
|
||||
///
|
||||
pub struct Store {
|
||||
pub(crate) inner: NonNull<sys::Store>,
|
||||
inner: NonNull<sys::Store>,
|
||||
}
|
||||
|
||||
// impl Clone for Store {
|
||||
// fn clone(&self) -> Self {
|
||||
// let inner = self.inner.clone();
|
||||
//
|
||||
// wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// sys::nix_gc_incref(ctx.as_ptr(), self.as_ptr() as *mut c_void);
|
||||
// })
|
||||
// .unwrap();
|
||||
//
|
||||
// Self { inner }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl AsInnerPtr<sys::Store> for Store {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::Store {
|
||||
|
|
@ -63,13 +67,19 @@ impl Store {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the store cannot be opened.
|
||||
pub fn open(uri: Option<&str>) -> Result<Self, NixideError> {
|
||||
let uri_ptr = match uri.map(CString::new) {
|
||||
Some(Ok(c_uri)) => c_uri.as_ptr(),
|
||||
Some(Err(_)) => Err(new_nixide_error!(StringNulByte))?,
|
||||
None => null(),
|
||||
};
|
||||
///
|
||||
pub fn open(uri: &str) -> NixideResult<Self> {
|
||||
Self::open_ptr(uri.as_c_ptr()?)
|
||||
}
|
||||
|
||||
/// Opens a connection to the default Nix store.
|
||||
///
|
||||
pub fn default() -> NixideResult<Self> {
|
||||
Self::open_ptr(null())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn open_ptr(uri_ptr: *const c_char) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// XXX: TODO: allow args to be parsed instead of just `null_mut`
|
||||
sys::nix_store_open(ctx.as_ptr(), uri_ptr, null_mut())
|
||||
|
|
@ -95,6 +105,7 @@ impl Store {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the path cannot be realized.
|
||||
///
|
||||
pub fn realise<F>(
|
||||
&self,
|
||||
path: &StorePath,
|
||||
|
|
@ -107,11 +118,11 @@ impl Store {
|
|||
-> Vec<(String, StorePath)> {
|
||||
// XXX: TODO: test to see if this is ever null ("out" as a default feels unsafe...)
|
||||
// NOTE: this also ensures `output_name_ptr` isn't null
|
||||
let output_name = output_name_ptr.to_utf8_string().expect("IDK1");
|
||||
let output_name = output_name_ptr.to_utf8_string().unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let inner = wrap::nix_ptr_fn!(|ctx| unsafe {
|
||||
sys::nix_store_path_clone(output_path_ptr as *mut sys::StorePath)
|
||||
}).expect("IDK2");
|
||||
}).unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
let store_path = StorePath { inner };
|
||||
|
||||
let callback = unsafe { (*userdata).inner };
|
||||
|
|
@ -161,14 +172,16 @@ impl Store {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn store_path(&self, path: &str) -> Result<StorePath, NixideError> {
|
||||
///
|
||||
pub fn store_path(&self, path: &str) -> NixideResult<StorePath> {
|
||||
StorePath::parse(self, path)
|
||||
}
|
||||
|
||||
/// Get the version of a Nix store
|
||||
///
|
||||
/// If the store doesn't have a version (like the dummy store), returns None
|
||||
pub fn version(&self) -> Result<String, NixideError> {
|
||||
///
|
||||
pub fn version(&self) -> NixideResult<String> {
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_version(
|
||||
|
|
@ -182,7 +195,8 @@ impl Store {
|
|||
}
|
||||
|
||||
/// Get the URI of a Nix store
|
||||
pub fn uri(&self) -> Result<String, NixideError> {
|
||||
///
|
||||
pub fn uri(&self) -> NixideResult<String> {
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_uri(
|
||||
|
|
@ -195,7 +209,7 @@ impl Store {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn store_dir(&self) -> Result<PathBuf, NixideError> {
|
||||
pub fn store_dir(&self) -> NixideResult<PathBuf> {
|
||||
wrap::nix_pathbuf_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_storedir(
|
||||
|
|
@ -208,34 +222,26 @@ impl Store {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn copy_closure_to(
|
||||
&self,
|
||||
dst_store: &Store,
|
||||
store_path: &StorePath,
|
||||
) -> Result<(), NixideError> {
|
||||
pub fn copy_closure_to(&self, dst_store: &Store, store_path: &StorePath) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_copy_closure(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
dst_store.as_ptr(),
|
||||
store_path.as_ptr(),
|
||||
); // semi-colon to return () and not i32
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn copy_closure_from(
|
||||
&self,
|
||||
src_store: &Store,
|
||||
store_path: &StorePath,
|
||||
) -> Result<(), NixideError> {
|
||||
pub fn copy_closure_from(&self, src_store: &Store, store_path: &StorePath) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_copy_closure(
|
||||
ctx.as_ptr(),
|
||||
src_store.as_ptr(),
|
||||
self.as_ptr(),
|
||||
store_path.inner.as_ptr(),
|
||||
store_path.as_ptr(),
|
||||
);
|
||||
}) // semi-colon to return () and not i32
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,7 +252,3 @@ impl Drop for Store {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Store can be shared between threads
|
||||
unsafe impl Send for Store {}
|
||||
unsafe impl Sync for Store {}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use std::ffi::{c_void, CString};
|
||||
use std::ffi::{CString, c_void};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::Store;
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::sys;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideResult;
|
||||
|
||||
/// A path in the Nix store.
|
||||
///
|
||||
|
|
@ -18,6 +18,25 @@ pub struct StorePath {
|
|||
pub(crate) inner: NonNull<sys::StorePath>,
|
||||
}
|
||||
|
||||
impl Clone for StorePath {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = wrap::nix_ptr_fn!(|_| unsafe { sys::nix_store_path_clone(self.as_ptr()) })
|
||||
.unwrap_or_else(|_| {
|
||||
panic_issue_call_failed!("nix_store_path_clone returned None for valid path")
|
||||
});
|
||||
|
||||
StorePath { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StorePath {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_store_path_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::StorePath> for StorePath {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::StorePath {
|
||||
|
|
@ -127,26 +146,3 @@ impl StorePath {
|
|||
.is_ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for StorePath {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = wrap::nix_ptr_fn!(|_| unsafe { sys::nix_store_path_clone(self.as_ptr()) })
|
||||
.unwrap_or_else(|_| {
|
||||
panic_issue_call_failed!("nix_store_path_clone returned None for valid path")
|
||||
});
|
||||
|
||||
StorePath { inner }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StorePath {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_store_path_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: StorePath can be shared between threads
|
||||
unsafe impl Send for StorePath {}
|
||||
unsafe impl Sync for StorePath {}
|
||||
|
|
|
|||
|
|
@ -2,39 +2,24 @@ use serial_test::serial;
|
|||
|
||||
use super::{Store, StorePath};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::init::LIBNIX_INIT_STATUS;
|
||||
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");
|
||||
};
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
|
||||
let _store = Store::open(None).expect("Failed to open store");
|
||||
let _store = Store::default().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");
|
||||
};
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
|
||||
let store = Store::open(None).expect("Failed to open store");
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
|
||||
// Try parsing a well-formed store path
|
||||
let result = StorePath::fake_path(&store);
|
||||
|
|
@ -44,17 +29,9 @@ fn test_store_path_parse() {
|
|||
#[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");
|
||||
};
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
|
||||
let store = Store::open(None).expect("Failed to open store");
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
|
||||
// Try to get a valid store path by parsing
|
||||
let path = StorePath::fake_path(&store).expect("Failed to create `StorePath::fake_path`");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue