Compare commits
No commits in common. "18fcc93c369391ecd6b82e441a8e46ef42a4e875" and "f834bcfaa92314687f8eb59aa9dead29d1aaadf9" have entirely different histories.
18fcc93c36
...
f834bcfaa9
32 changed files with 762 additions and 1438 deletions
356
Cargo.lock
generated
356
Cargo.lock
generated
|
|
@ -11,12 +11,6 @@ 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"
|
||||
|
|
@ -124,40 +118,12 @@ 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"
|
||||
|
|
@ -193,64 +159,12 @@ 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"
|
||||
|
|
@ -260,18 +174,6 @@ 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"
|
||||
|
|
@ -288,12 +190,6 @@ 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"
|
||||
|
|
@ -330,7 +226,6 @@ dependencies = [
|
|||
"nixide-sys",
|
||||
"serial_test",
|
||||
"stdext",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -395,16 +290,6 @@ 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"
|
||||
|
|
@ -423,12 +308,6 @@ 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"
|
||||
|
|
@ -473,19 +352,6 @@ 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"
|
||||
|
|
@ -507,54 +373,6 @@ 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"
|
||||
|
|
@ -616,194 +434,20 @@ 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,7 +23,6 @@ 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,19 +67,6 @@ 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 {
|
||||
|
|
@ -196,6 +183,7 @@ 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;
|
||||
|
|
@ -230,9 +218,11 @@ impl ErrorContext {
|
|||
/// This function **never fails**.
|
||||
///
|
||||
fn get_err(&self) -> Option<sys::nix_err> {
|
||||
match unsafe { sys::nix_err_code(self.as_ptr()) } {
|
||||
let err = unsafe { sys::nix_err_code(self.as_ptr()) };
|
||||
|
||||
match err {
|
||||
sys::nix_err_NIX_OK => None,
|
||||
err => Some(err),
|
||||
_ => Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,17 +257,13 @@ impl ErrorContext {
|
|||
/// and avoid passing in a [sys::nix_c_context] struct.
|
||||
///
|
||||
fn get_msg(&self) -> Option<String> {
|
||||
// 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 {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
// NOTE: an Err here only occurs when `self.get_code() == Ok(())`
|
||||
let mut n: c_uint = 0;
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -319,18 +305,19 @@ impl ErrorContext {
|
|||
/// ```
|
||||
///
|
||||
fn get_nix_err_name(&self) -> Option<String> {
|
||||
// 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 {
|
||||
#[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| {
|
||||
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.
|
||||
|
|
@ -371,16 +358,19 @@ impl ErrorContext {
|
|||
/// ```
|
||||
///
|
||||
fn get_nix_err_info_msg(&self) -> Option<String> {
|
||||
// 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()
|
||||
#[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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
use std::ffi::{CString, c_void};
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::errors::new_nixide_error;
|
||||
|
||||
|
|
@ -15,56 +18,46 @@ use crate::{NixideResult, Store};
|
|||
/// This provides the main interface for evaluating Nix expressions
|
||||
/// and creating values.
|
||||
pub struct EvalState {
|
||||
inner: NonNull<sys::EvalState>,
|
||||
inner: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
|
||||
store: Store,
|
||||
// XXX: TODO: is an `Arc<Store>` necessary or just a `Store`
|
||||
store: Arc<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.as_ptr()
|
||||
self.inner.borrow().as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::EvalState {
|
||||
unsafe { self.inner.as_ref() }
|
||||
unsafe { self.inner.borrow().as_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_mut(&mut self) -> &mut sys::EvalState {
|
||||
unsafe { self.inner.as_mut() }
|
||||
unsafe { self.inner.borrow_mut().as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
impl EvalState {
|
||||
/// Construct a new EvalState directly from its attributes
|
||||
///
|
||||
pub(super) fn new(inner: NonNull<sys::EvalState>, store: &Store) -> Self {
|
||||
pub(super) fn new(inner: NonNull<sys::EvalState>, store: Arc<Store>) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
store: store.clone(),
|
||||
inner: Rc::new(RefCell::new(inner)),
|
||||
store,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store_ref(&self) -> &Store {
|
||||
&self.store
|
||||
#[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()
|
||||
}
|
||||
|
||||
/// Evaluate a Nix expression from a string.
|
||||
|
|
@ -77,7 +70,7 @@ impl EvalState {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if evaluation fails.
|
||||
pub fn interpret(&self, expr: &str, path: &str) -> NixideResult<Value> {
|
||||
pub fn eval_from_string(&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)))?;
|
||||
|
||||
|
|
@ -99,7 +92,7 @@ impl EvalState {
|
|||
);
|
||||
value
|
||||
})
|
||||
.map(|ptr| Value::from((ptr, self)))
|
||||
.map(|ptr| Value::from((ptr, self.inner_ref())))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::ffi::{CString, c_char, c_void};
|
||||
use std::ffi::{CString, c_char};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::sync::Arc;
|
||||
|
||||
use super::EvalState;
|
||||
#[cfg(feature = "flakes")]
|
||||
|
|
@ -14,28 +15,11 @@ 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: Store,
|
||||
store: Arc<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 {
|
||||
|
|
@ -63,15 +47,17 @@ impl EvalStateBuilder {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the builder cannot be created.
|
||||
///
|
||||
pub fn new(store: &Store) -> NixideResult<Self> {
|
||||
pub fn new(store: &Arc<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: store.clone(),
|
||||
store: Arc::clone(store),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -80,20 +66,18 @@ 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))
|
||||
Ok(EvalState::new(inner, self.store.clone()))
|
||||
}
|
||||
|
||||
// XXX: TODO: use `flakes()` instead
|
||||
#[deprecated]
|
||||
// XXX: TODO
|
||||
#[cfg(feature = "flakes")]
|
||||
pub fn set_flake_settings(self, settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
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(),
|
||||
|
|
@ -105,13 +89,7 @@ impl EvalStateBuilder {
|
|||
Ok(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> {
|
||||
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());
|
||||
})?;
|
||||
|
|
@ -119,7 +97,7 @@ impl EvalStateBuilder {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn set_lookup_path<P: AsRef<str>>(self, paths: Vec<P>) -> NixideResult<Self> {
|
||||
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, c_void};
|
||||
use std::ffi::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::expr::values::NixString;
|
||||
use crate::stdext::CCharPtrExt;
|
||||
use crate::sys;
|
||||
use crate::util::LazyArray;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::LazyArray;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{EvalState, NixideResult, StorePath};
|
||||
|
||||
|
|
@ -17,23 +17,6 @@ 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 {
|
||||
|
|
@ -98,7 +81,7 @@ impl<'a> RealisedString<'a> {
|
|||
path: Self::parse_path(inner.as_ptr(), state),
|
||||
children: LazyArray::new(
|
||||
size,
|
||||
Box::new(|_| StorePath::fake_path(state.store_ref()).unwrap()),
|
||||
Box::new(|_| StorePath::fake_path(unsafe { state.store_ref() }).unwrap()),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
|
@ -115,7 +98,7 @@ impl<'a> RealisedString<'a> {
|
|||
err
|
||||
)
|
||||
});
|
||||
StorePath::parse(state.store_ref(), &path_str).unwrap_or_else(|err| {
|
||||
StorePath::parse(unsafe { 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::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use serial_test::serial;
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ use crate::Store;
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_eval_state_builder() {
|
||||
let store = Rc::new(Store::default().expect("Failed to open store"));
|
||||
let store = Arc::new(Store::open(None).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 = Rc::new(Store::default().expect("Failed to open store"));
|
||||
let store = Arc::new(Store::open(None).expect("Failed to open store"));
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
.expect("Failed to create builder")
|
||||
.build()
|
||||
.expect("Failed to build state");
|
||||
|
||||
let result = state
|
||||
.interpret("1 + 2", "<eval>")
|
||||
.eval_from_string("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 = Store::default().expect("Failed to open store");
|
||||
let store = Arc::new(Store::open(None).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
|
||||
.interpret("42", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("true", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("\"hello\"", "<eval>")
|
||||
.eval_from_string("\"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 = Store::default().expect("Failed to open store");
|
||||
let store = Arc::new(Store::open(None).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
|
||||
.interpret("42", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("true", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("false", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("\"hello world\"", "<eval>")
|
||||
.eval_from_string("\"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
|
||||
.interpret("\"say \\\"hello\\\"\"", "<eval>")
|
||||
.eval_from_string("\"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
|
||||
.interpret("null", "<eval>")
|
||||
.eval_from_string("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
|
||||
.interpret("{ a = 1; }", "<eval>")
|
||||
.eval_from_string("{ 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
|
||||
.interpret("[ 1 2 3 ]", "<eval>")
|
||||
.eval_from_string("[ 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,37 +1,22 @@
|
|||
use std::cell::RefCell;
|
||||
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: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
len: u32,
|
||||
}
|
||||
|
||||
impl Clone for NixAttrs {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixAttrs {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -76,17 +61,13 @@ impl NixValue for NixAttrs {
|
|||
sys::ValueType_NIX_TYPE_ATTRS
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::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: state.clone(),
|
||||
len,
|
||||
}
|
||||
Self { inner, state, len }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +88,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
|
|
@ -118,7 +99,7 @@ impl NixAttrs {
|
|||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = Value::from((inner, &self.state));
|
||||
let value = Value::from((inner, self.state.clone()));
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
|
@ -134,7 +115,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
index,
|
||||
name_ptr,
|
||||
)
|
||||
|
|
@ -145,7 +126,7 @@ impl NixAttrs {
|
|||
.to_utf8_string()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
let value = <NixThunk as NixValue>::from(inner, &self.state);
|
||||
let value = <NixThunk as NixValue>::from(inner, self.state.clone());
|
||||
|
||||
Some((name, value))
|
||||
}
|
||||
|
|
@ -156,7 +137,12 @@ 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.as_ptr(), index)
|
||||
sys::nix_get_attr_name_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
|
|
@ -175,7 +161,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byname(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
|
|
@ -183,7 +169,7 @@ impl NixAttrs {
|
|||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(Value::from((inner, &self.state))),
|
||||
Ok(inner) => Some(Value::from((inner, self.state.clone()))),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
|
|
@ -201,7 +187,7 @@ impl NixAttrs {
|
|||
sys::nix_get_attr_byname_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.state.borrow_mut().as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
|
|
@ -209,7 +195,7 @@ impl NixAttrs {
|
|||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, &self.state)),
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, self.state.clone())),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
|
|
|
|||
|
|
@ -1,36 +1,21 @@
|
|||
use std::cell::RefCell;
|
||||
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: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: bool,
|
||||
}
|
||||
|
||||
impl Clone for NixBool {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixBool {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -75,7 +60,7 @@ impl NixValue for NixBool {
|
|||
sys::ValueType_NIX_TYPE_BOOL
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
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_bool(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -85,7 +70,7 @@ impl NixValue for NixBool {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
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;
|
||||
|
|
@ -10,27 +11,10 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixFloat {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: f64,
|
||||
}
|
||||
|
||||
impl Clone for NixFloat {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixFloat {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -75,7 +59,7 @@ impl NixValue for NixFloat {
|
|||
sys::ValueType_NIX_TYPE_FLOAT
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
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_float(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -85,7 +69,7 @@ impl NixValue for NixFloat {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,19 @@
|
|||
use std::cell::RefCell;
|
||||
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: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixFunction {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
impl Drop for NixFunction {
|
||||
|
|
@ -73,10 +60,16 @@ impl NixValue for NixFunction {
|
|||
sys::ValueType_NIX_TYPE_FUNCTION
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
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));
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -87,14 +80,14 @@ impl NixFunction {
|
|||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr())
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().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.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.as_ptr(),
|
||||
arg.as_ptr(),
|
||||
inner.as_ptr(),
|
||||
|
|
@ -102,7 +95,7 @@ impl NixFunction {
|
|||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, &self.state))
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
|
||||
pub fn call_many<T>(&self, args: &[&T]) -> Value
|
||||
|
|
@ -110,14 +103,14 @@ impl NixFunction {
|
|||
T: NixValue,
|
||||
{
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.as_ptr())
|
||||
sys::nix_alloc_value(ctx.as_ptr(), self.state.borrow().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.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.as_ptr(),
|
||||
args.len(),
|
||||
args.into_c_array(),
|
||||
|
|
@ -126,7 +119,7 @@ impl NixFunction {
|
|||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, &self.state))
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
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;
|
||||
|
|
@ -10,27 +11,10 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixInt {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: i64,
|
||||
}
|
||||
|
||||
impl Clone for NixInt {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixInt {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -75,7 +59,7 @@ impl NixValue for NixInt {
|
|||
sys::ValueType_NIX_TYPE_INT
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
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())
|
||||
})
|
||||
|
|
@ -83,7 +67,7 @@ impl NixValue for NixInt {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
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;
|
||||
|
|
@ -10,23 +11,7 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixList {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixList {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
}
|
||||
|
||||
impl Drop for NixList {
|
||||
|
|
@ -73,11 +58,8 @@ impl NixValue for NixList {
|
|||
sys::ValueType_NIX_TYPE_LIST
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,19 +98,29 @@ 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.as_ptr(), index)
|
||||
sys::nix_get_list_byidx(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((inner, &self.state))
|
||||
Value::from((inner, self.state.clone()))
|
||||
}
|
||||
|
||||
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.as_ptr(), index)
|
||||
sys::nix_get_list_byidx_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
index,
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
<NixThunk as NixValue>::from(inner, &self.state)
|
||||
<NixThunk as NixValue>::from(inner, self.state.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ 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;
|
||||
|
|
@ -38,12 +40,12 @@ use crate::sys::{
|
|||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
||||
pub trait NixValue: Clone + Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
|
||||
pub trait NixValue: Drop + Display + Debug + AsInnerPtr<sys::nix_value> {
|
||||
/// TODO
|
||||
fn type_id(&self) -> sys::ValueType;
|
||||
|
||||
/// TODO
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self;
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self;
|
||||
}
|
||||
|
||||
/// A Nix value
|
||||
|
|
@ -109,12 +111,22 @@ pub enum Value {
|
|||
// Failed(NixFailed),
|
||||
}
|
||||
|
||||
impl From<(NonNull<sys::nix_value>, &EvalState)> for Value {
|
||||
fn from(value: (NonNull<sys::nix_value>, &EvalState)) -> Self {
|
||||
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 {
|
||||
let (inner, state) = value;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_force(ctx.as_ptr(), state.as_ptr(), inner.as_ptr())
|
||||
sys::nix_value_force(ctx.as_ptr(), state.borrow().as_ptr(), inner.as_ptr())
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
|
|
@ -185,3 +197,13 @@ impl Debug for Value {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// macro_rules! is_type {
|
||||
// ($expr:expr, $tt:tt) => {{
|
||||
// match $expr {
|
||||
// $tt => true,
|
||||
// _ => false,
|
||||
// }
|
||||
// }};
|
||||
// }
|
||||
// pub(self) use is_type;
|
||||
|
|
|
|||
|
|
@ -1,32 +1,16 @@
|
|||
use std::cell::RefCell;
|
||||
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: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixNull {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
}
|
||||
|
||||
impl Drop for NixNull {
|
||||
|
|
@ -73,10 +57,7 @@ impl NixValue for NixNull {
|
|||
sys::ValueType_NIX_TYPE_NULL
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,23 @@
|
|||
use std::cell::RefCell;
|
||||
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: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: PathBuf,
|
||||
}
|
||||
|
||||
impl Clone for NixPath {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixPath {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -77,7 +62,7 @@ impl NixValue for NixPath {
|
|||
sys::ValueType_NIX_TYPE_PATH
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
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_path_string(ctx.as_ptr(), inner.as_ptr())
|
||||
})
|
||||
|
|
@ -87,7 +72,7 @@ impl NixValue for NixPath {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,22 @@
|
|||
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: EvalState,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl Clone for NixString {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
value: self.value.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for NixString {
|
||||
fn drop(&mut self) {
|
||||
let ctx = ErrorContext::new();
|
||||
|
|
@ -75,7 +61,7 @@ impl NixValue for NixString {
|
|||
sys::ValueType_NIX_TYPE_STRING
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
let value = wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_string(
|
||||
|
|
@ -90,7 +76,7 @@ impl NixValue for NixString {
|
|||
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
state,
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::cell::RefCell;
|
||||
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;
|
||||
|
|
@ -10,23 +11,7 @@ use crate::util::{panic_issue_call_failed, wrap};
|
|||
|
||||
pub struct NixThunk {
|
||||
inner: NonNull<sys::nix_value>,
|
||||
state: EvalState,
|
||||
}
|
||||
|
||||
impl Clone for NixThunk {
|
||||
fn clone(&self) -> Self {
|
||||
let inner = self.inner.clone();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_value_incref(ctx.as_ptr(), self.as_ptr());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
inner,
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
}
|
||||
|
||||
impl Drop for NixThunk {
|
||||
|
|
@ -73,21 +58,26 @@ impl NixValue for NixThunk {
|
|||
sys::ValueType_NIX_TYPE_THUNK
|
||||
}
|
||||
|
||||
fn from(inner: NonNull<sys::nix_value>, state: &EvalState) -> Self {
|
||||
Self {
|
||||
inner,
|
||||
state: state.clone(),
|
||||
}
|
||||
fn from(inner: NonNull<sys::nix_value>, state: Rc<RefCell<NonNull<sys::EvalState>>>) -> Self {
|
||||
Self { inner, state }
|
||||
}
|
||||
}
|
||||
|
||||
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.as_ptr(), self.inner.as_ptr())
|
||||
sys::nix_value_force(
|
||||
ctx.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
self.inner.as_ptr(),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
|
||||
Value::from((self.inner, &self.state))
|
||||
Value::from((self.inner, self.state.to_owned()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
nixide/src/flake/eval_state_builder_ext.rs
Normal file
14
nixide/src/flake/eval_state_builder_ext.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
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,39 +1,28 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
|
||||
pub struct FetchersSettings {
|
||||
inner: NonNull<sys::nix_fetchers_settings>,
|
||||
pub(super) struct FetchersSettings {
|
||||
pub(super) ptr: NonNull<sys::nix_fetchers_settings>,
|
||||
}
|
||||
|
||||
impl FetchersSettings {
|
||||
pub fn new() -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_new(ctx.as_ptr())
|
||||
})?;
|
||||
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))?,
|
||||
})
|
||||
}
|
||||
|
||||
Ok(Self { inner })
|
||||
pub(crate) unsafe fn as_ptr(&self) -> *mut sys::nix_fetchers_settings {
|
||||
self.ptr.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
|
@ -42,23 +31,6 @@ 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,26 +1,22 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ffi::CString;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::{FlakeReference, FlakeSettings};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::new_nixide_error;
|
||||
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, Copy)]
|
||||
#[derive(Debug, Clone)]
|
||||
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,
|
||||
}
|
||||
|
||||
|
|
@ -28,20 +24,6 @@ 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 {
|
||||
|
|
@ -49,49 +31,69 @@ 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 })
|
||||
}
|
||||
|
||||
impl AsInnerPtr<sys::nix_flake_lock_flags> for FlakeLockFlags {
|
||||
#[inline]
|
||||
unsafe fn as_ptr(&self) -> *mut sys::nix_flake_lock_flags {
|
||||
pub(crate) fn as_ptr(&self) -> *mut sys::nix_flake_lock_flags {
|
||||
self.inner.as_ptr()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_ref(&self) -> &sys::nix_flake_lock_flags {
|
||||
unsafe { self.inner.as_ref() }
|
||||
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_mut(&mut self) -> &mut sys::nix_flake_lock_flags {
|
||||
unsafe { self.inner.as_mut() }
|
||||
}
|
||||
}
|
||||
/// 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",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
|
||||
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())
|
||||
})?;
|
||||
/// 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",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
|
||||
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())
|
||||
},
|
||||
};
|
||||
})
|
||||
}
|
||||
/// 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",
|
||||
// )
|
||||
// })
|
||||
// }
|
||||
|
||||
/// Adds an input override to the lock file that will be produced.
|
||||
/// The [LockedFlake::lock] operation will not write to the lock file.
|
||||
|
|
@ -104,17 +106,26 @@ impl FlakeLockFlags {
|
|||
/// # Arguments
|
||||
///
|
||||
/// * `path` - The input name/path to override (must not be empty)
|
||||
/// * `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()?;
|
||||
/// * `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)));
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
let ctx = ErrorContext::new();
|
||||
unsafe {
|
||||
sys::nix_flake_lock_flags_add_input_override(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
input_path,
|
||||
input_path.as_ptr(),
|
||||
flakeref.as_ptr(),
|
||||
);
|
||||
})
|
||||
)
|
||||
};
|
||||
match ctx.peak() {
|
||||
Some(err) => Err(err),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,99 +1,58 @@
|
|||
use std::ffi::c_void;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr::{NonNull, null_mut};
|
||||
use std::ptr::{null_mut, NonNull};
|
||||
|
||||
use super::{FetchersSettings, FlakeReferenceParseFlags, FlakeSettings};
|
||||
use crate::NixideError;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::errors::new_nixide_error;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::bindings::wrap_nix_string_callback;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::NixideError;
|
||||
|
||||
// XXX: TODO: rename FlakeReference -> FlakeRef
|
||||
pub struct FlakeReference {
|
||||
inner: NonNull<sys::nix_flake_reference>,
|
||||
fragment: String,
|
||||
pub(crate) ptr: NonNull<sys::nix_flake_reference>,
|
||||
}
|
||||
|
||||
// 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.as_ptr());
|
||||
sys::nix_flake_reference_free(self.ptr.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(
|
||||
pub fn parse_with_fragment(
|
||||
fetch_settings: &FetchersSettings,
|
||||
flake_settings: &FlakeSettings,
|
||||
flags: &FlakeReferenceParseFlags,
|
||||
reference: &str,
|
||||
) -> Result<FlakeReference, NixideError> {
|
||||
) -> Result<(FlakeReference, String), NixideError> {
|
||||
let mut ptr: *mut sys::nix_flake_reference = null_mut();
|
||||
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,
|
||||
)
|
||||
}
|
||||
)?;
|
||||
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,
|
||||
)
|
||||
});
|
||||
|
||||
match NonNull::new(ptr) {
|
||||
Some(inner) => Ok(FlakeReference { inner, fragment }),
|
||||
Some(ptr) => result.map(|s| (FlakeReference { ptr }, s)),
|
||||
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,77 +1,58 @@
|
|||
use std::ffi::c_void;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::FlakeSettings;
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::errors::{new_nixide_error, 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 {
|
||||
inner: NonNull<sys::nix_flake_reference_parse_flags>,
|
||||
pub(crate) ptr: 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.inner.as_ptr());
|
||||
sys::nix_flake_reference_parse_flags_free(self.ptr.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) -> 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 })
|
||||
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 })
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
pub fn set_base_directory(&mut self, base_directory: &str) -> Result<(), NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
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,15 +1,52 @@
|
|||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
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 {
|
||||
inner: NonNull<sys::nix_flake_settings>,
|
||||
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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FlakeSettings {
|
||||
|
|
@ -19,43 +56,3 @@ 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,184 +1,145 @@
|
|||
// 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::ErrorContext;
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{EvalState, NixideResult, Value};
|
||||
use crate::{EvalState, NixideError, Value};
|
||||
|
||||
pub struct LockedFlake {
|
||||
inner: NonNull<sys::nix_locked_flake>,
|
||||
|
||||
flakeref: FlakeReference,
|
||||
state: EvalState,
|
||||
flags: FlakeLockFlags,
|
||||
fetch_settings: FetchersSettings,
|
||||
flake_settings: FlakeSettings,
|
||||
pub(crate) ptr: NonNull<sys::nix_locked_flake>,
|
||||
}
|
||||
|
||||
// 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.as_ptr());
|
||||
sys::nix_locked_flake_free(self.ptr.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,
|
||||
state: &EvalState,
|
||||
eval_state: &EvalState,
|
||||
flags: &FlakeLockFlags,
|
||||
flakeref: &FlakeReference,
|
||||
) -> NixideResult<LockedFlake> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
flake_ref: &FlakeReference,
|
||||
) -> Result<LockedFlake, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
|
||||
let ptr = NonNull::new(unsafe {
|
||||
sys::nix_flake_lock(
|
||||
ctx.as_ptr(),
|
||||
fetch_settings.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
state.as_ptr(),
|
||||
eval_state.as_ptr(),
|
||||
flags.as_ptr(),
|
||||
flakeref.as_ptr(),
|
||||
flake_ref.as_ptr(),
|
||||
)
|
||||
})?;
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
inner,
|
||||
flakeref: flakeref.clone(),
|
||||
state: state.clone(),
|
||||
flags: flags.clone(),
|
||||
fetch_settings: fetch_settings.clone(),
|
||||
flake_settings: flake_settings.clone(),
|
||||
})
|
||||
match ptr {
|
||||
Some(ptr) => Ok(LockedFlake { ptr }),
|
||||
None => Err(new_nixide_error!(NullPtr)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the outputs of the flake - the result of calling the `outputs` attribute.
|
||||
pub fn outputs(&self) -> NixideResult<Value> {
|
||||
let value = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
pub fn outputs(
|
||||
&self,
|
||||
flake_settings: &FlakeSettings,
|
||||
eval_state: &mut EvalState,
|
||||
) -> Result<Value, NixideError> {
|
||||
let ctx = ErrorContext::new();
|
||||
|
||||
let r = unsafe {
|
||||
sys::nix_locked_flake_get_output_attrs(
|
||||
ctx.as_ptr(),
|
||||
self.flake_settings.as_ptr(),
|
||||
self.state.as_ptr(),
|
||||
self.inner.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
eval_state.as_ptr(),
|
||||
self.ptr.as_ptr(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(Value::from((value, &self.state)))
|
||||
};
|
||||
Ok(nix_bindings_expr::value::__private::raw_value_new(r))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fs;
|
||||
use std::sync::Once;
|
||||
// use nix_bindings_expr::eval_state::{gc_register_my_thread, EvalStateBuilder};
|
||||
|
||||
use super::{FetchersSettings, FlakeLockFlags, FlakeReference, FlakeSettings, LockedFlake};
|
||||
use crate::flake::{FlakeLockMode, FlakeReferenceParseFlags};
|
||||
use crate::{EvalStateBuilder, Store, Value, set_global_setting};
|
||||
use crate::{EvalStateBuilder, Store};
|
||||
|
||||
use super::*;
|
||||
use std::sync::Once;
|
||||
|
||||
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(|| unsafe {
|
||||
set_global_setting("experimental-features", "flakes").unwrap();
|
||||
INIT.call_once(|| {
|
||||
nix_bindings_expr::eval_state::init().unwrap();
|
||||
nix_bindings_util::settings::set("experimental-features", "flakes").unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flake_settings_getflake_exists() {
|
||||
init();
|
||||
|
||||
let store = Store::default().expect("Failed to open store connection");
|
||||
let state = EvalStateBuilder::new(&store)
|
||||
let gc_registration = gc_register_my_thread();
|
||||
let store = Store::open(None, []).unwrap();
|
||||
let mut eval_state = EvalStateBuilder::new(store)
|
||||
.unwrap()
|
||||
.flakes()
|
||||
.flakes(&FlakeSettings::new().unwrap())
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let value = state.interpret("builtins?getFlake", "<test>").unwrap();
|
||||
let v = eval_state
|
||||
.eval_from_string("builtins?getFlake", "<test>")
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(value, Value::Bool(_)));
|
||||
if let Value::Bool(v) = value {
|
||||
assert!(v.as_bool());
|
||||
}
|
||||
let b = eval_state.require_bool(&v).unwrap();
|
||||
|
||||
assert!(b);
|
||||
|
||||
drop(gc_registration);
|
||||
}
|
||||
|
||||
#[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");
|
||||
fs::write(
|
||||
std::fs::write(
|
||||
&flake_nix,
|
||||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "world";
|
||||
hello = "potato";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.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 flakeref = FlakeReference::parse(
|
||||
let (flake_ref, fragment) = FlakeReference::parse_with_fragment(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&FlakeReferenceParseFlags::new(&flake_settings).unwrap(),
|
||||
|
|
@ -186,40 +147,41 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(flakeref.fragment(), "subthing");
|
||||
assert_eq!(fragment, "subthing");
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref,
|
||||
&flake_ref,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "world");
|
||||
}
|
||||
}
|
||||
assert_eq!(hello, "potato");
|
||||
|
||||
drop(fetchers_settings);
|
||||
drop(tmp_dir);
|
||||
drop(gc_registration);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flake_lock_load_flake_with_flags() {
|
||||
init();
|
||||
|
||||
let store = Store::default().unwrap();
|
||||
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)
|
||||
let mut eval_state = EvalStateBuilder::new(store)
|
||||
.unwrap()
|
||||
.set_flake_settings(&flake_settings)
|
||||
.flakes(&flake_settings)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
|
@ -260,7 +222,7 @@ mod tests {
|
|||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "ALICE";
|
||||
hello = "BOB";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
|
|
@ -289,7 +251,7 @@ mod tests {
|
|||
.set_base_directory(tmp_dir.path().to_str().unwrap())
|
||||
.unwrap();
|
||||
|
||||
let flakeref_a = FlakeReference::parse(
|
||||
let (flake_ref_a, fragment) = FlakeReference::parse_with_fragment(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&flake_reference_parse_flags,
|
||||
|
|
@ -297,17 +259,20 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(flakeref_a.fragment(), "");
|
||||
assert_eq!(fragment, "");
|
||||
|
||||
// Step 1: Do not update (check), fails
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
&flake_ref_a,
|
||||
);
|
||||
// Has not been locked and would need to write a lock file.
|
||||
assert!(locked_flake.is_err());
|
||||
|
|
@ -317,50 +282,8 @@ mod tests {
|
|||
};
|
||||
|
||||
// Step 2: Update but do not write, succeeds
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Virtual).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
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 3: The lock was not written, so Step 1 would fail again
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
);
|
||||
// Has not been locked and would need to write a lock file.
|
||||
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_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.set_lock_mode(&FlakeLockMode::Virtual)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
|
|
@ -368,110 +291,146 @@ mod tests {
|
|||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
&flake_ref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
let outputs = locked_flake
|
||||
.outputs(&flake_settings, &mut eval_state)
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
let hello = eval_state.require_attrs_select(&outputs, "hello").unwrap();
|
||||
let hello = eval_state.require_string(&hello).unwrap();
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
assert_eq!(hello, "BOB");
|
||||
|
||||
// Step 5: Lock was written, so Step 1 succeeds
|
||||
flake_lock_flags.set_mode(&FlakeLockMode::Check).unwrap();
|
||||
// Step 3: The lock was not written, so Step 1 would fail again
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
&flake_ref_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)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake.outputs().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");
|
||||
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
// Step 5: Lock was written, so Step 1 succeeds
|
||||
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flake_ref_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");
|
||||
|
||||
// Step 6: Lock with override, do not write
|
||||
|
||||
// This shouldn't matter; write_as_needed will be overridden
|
||||
flake_lock_flags
|
||||
.set_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.set_lock_mode(&FlakeLockMode::WriteAsNeeded)
|
||||
.unwrap();
|
||||
|
||||
let flakeref_c = FlakeReference::parse(
|
||||
let (flake_ref_c, fragment) = FlakeReference::parse_with_fragment(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&flake_reference_parse_flags,
|
||||
&format!("path:{}", &flake_dir_c_str),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(flakeref_c.fragment(), "");
|
||||
assert_eq!(fragment, "");
|
||||
|
||||
flake_lock_flags.override_input("b", &flakeref_c).unwrap();
|
||||
flake_lock_flags.override_input("b", &flake_ref_c).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
&flake_ref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
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");
|
||||
|
||||
// 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_mode(&FlakeLockMode::Check).unwrap();
|
||||
|
||||
flake_lock_flags
|
||||
.set_lock_mode(&FlakeLockMode::Check)
|
||||
.unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(
|
||||
&fetchers_settings,
|
||||
&flake_settings,
|
||||
&eval_state,
|
||||
&flake_lock_flags,
|
||||
&flakeref_a,
|
||||
&flake_ref_a,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let outputs = locked_flake.outputs().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");
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
drop(fetchers_settings);
|
||||
drop(tmp_dir);
|
||||
drop(gc_registration);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ mod flake_reference_parse_flags;
|
|||
mod flake_settings;
|
||||
mod locked_flake;
|
||||
|
||||
use fetchers_settings::FetchersSettings;
|
||||
use flake_lock_flags::{FlakeLockFlags, FlakeLockMode};
|
||||
use flake_reference::FlakeReference;
|
||||
use flake_reference_parse_flags::FlakeReferenceParseFlags;
|
||||
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;
|
||||
pub use flake_settings::FlakeSettings;
|
||||
pub use locked_flake::LockedFlake;
|
||||
|
|
|
|||
|
|
@ -1,89 +0,0 @@
|
|||
use ctor::ctor;
|
||||
|
||||
use super::NixideResult;
|
||||
use super::errors::ErrorContext;
|
||||
use super::util::wrap;
|
||||
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)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - 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"))]
|
||||
pub(crate) fn init_libutil() {
|
||||
unsafe {
|
||||
if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) {
|
||||
LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_libutil_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - 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")))]
|
||||
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(_))) {
|
||||
LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_libstore_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
#[cfg(feature = "exprs")]
|
||||
pub(crate) fn init_libexpr() {
|
||||
unsafe {
|
||||
if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) {
|
||||
LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_libexpr_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ pub extern crate libc;
|
|||
pub extern crate nixide_sys as sys;
|
||||
|
||||
pub(crate) mod errors;
|
||||
mod init;
|
||||
mod nix_settings;
|
||||
mod stdext;
|
||||
pub(crate) mod util;
|
||||
mod verbosity;
|
||||
|
|
@ -22,7 +20,6 @@ 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;
|
||||
|
||||
|
|
@ -32,3 +29,63 @@ pub use expr::{EvalState, EvalStateBuilder, Value};
|
|||
pub use flake::{FlakeSettings, LockedFlake};
|
||||
#[cfg(feature = "store")]
|
||||
pub use store::{Store, StorePath};
|
||||
|
||||
use ctor::ctor;
|
||||
use util::wrappers::AsInnerPtr as _;
|
||||
|
||||
pub(crate) static mut INIT_LIBUTIL_STATUS: Option<NixideResult<()>> = None;
|
||||
#[cfg(feature = "store")]
|
||||
pub(crate) static mut INIT_LIBSTORE_STATUS: Option<NixideResult<()>> = None;
|
||||
#[cfg(feature = "exprs")]
|
||||
pub(crate) static mut INIT_LIBEXPR_STATUS: Option<NixideResult<()>> = None;
|
||||
|
||||
/// # Warning
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
fn init_libutil() {
|
||||
unsafe {
|
||||
INIT_LIBUTIL_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe {
|
||||
sys::nix_libutil_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// # Warning
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings)
|
||||
#[ctor]
|
||||
#[cfg(feature = "store")]
|
||||
fn init_libstore() {
|
||||
// XXX: TODO: how do I support `sys::nix_libstore_init_no_load_config(context)`?
|
||||
unsafe {
|
||||
INIT_LIBSTORE_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe {
|
||||
sys::nix_libutil_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// # Warning
|
||||
///
|
||||
/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor)
|
||||
/// > explicitly subverts that. The code that runs in `ctor` functions
|
||||
/// > should be careful to limit itself to libc functions and code
|
||||
/// > that does not rely on Rust's stdlib services.
|
||||
/// > - 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() {
|
||||
unsafe {
|
||||
INIT_LIBEXPR_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe {
|
||||
sys::nix_libexpr_init(ctx.as_ptr());
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
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,4 +1,13 @@
|
|||
// 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)]
|
||||
|
|
@ -7,38 +16,25 @@ mod tests;
|
|||
mod path;
|
||||
pub use path::*;
|
||||
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::ffi::{c_char, c_void, CString};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::{NonNull, null, null_mut};
|
||||
use std::ptr::{null, null_mut, NonNull};
|
||||
use std::result::Result;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::{AsCPtr as _, CCharPtrExt as _};
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
use crate::stdext::CCharPtrExt;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
use crate::{NixideError, NixideResult};
|
||||
|
||||
/// Nix store for managing packages and derivations.
|
||||
///
|
||||
/// The store provides access to Nix packages, derivations, and store paths.
|
||||
///
|
||||
pub struct Store {
|
||||
inner: NonNull<sys::Store>,
|
||||
pub(crate) 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 {
|
||||
|
|
@ -67,19 +63,13 @@ impl Store {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the store cannot be opened.
|
||||
///
|
||||
pub fn open(uri: &str) -> NixideResult<Self> {
|
||||
Self::open_ptr(uri.as_c_ptr()?)
|
||||
}
|
||||
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(),
|
||||
};
|
||||
|
||||
/// 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())
|
||||
|
|
@ -105,7 +95,6 @@ impl Store {
|
|||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the path cannot be realized.
|
||||
///
|
||||
pub fn realise<F>(
|
||||
&self,
|
||||
path: &StorePath,
|
||||
|
|
@ -118,11 +107,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().unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
let output_name = output_name_ptr.to_utf8_string().expect("IDK1");
|
||||
|
||||
let inner = wrap::nix_ptr_fn!(|ctx| unsafe {
|
||||
sys::nix_store_path_clone(output_path_ptr as *mut sys::StorePath)
|
||||
}).unwrap_or_else(|err| panic_issue_call_failed!("{}", err));
|
||||
}).expect("IDK2");
|
||||
let store_path = StorePath { inner };
|
||||
|
||||
let callback = unsafe { (*userdata).inner };
|
||||
|
|
@ -172,16 +161,14 @@ impl Store {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
pub fn store_path(&self, path: &str) -> NixideResult<StorePath> {
|
||||
pub fn store_path(&self, path: &str) -> Result<StorePath, NixideError> {
|
||||
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) -> NixideResult<String> {
|
||||
pub fn version(&self) -> Result<String, NixideError> {
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_version(
|
||||
|
|
@ -195,8 +182,7 @@ impl Store {
|
|||
}
|
||||
|
||||
/// Get the URI of a Nix store
|
||||
///
|
||||
pub fn uri(&self) -> NixideResult<String> {
|
||||
pub fn uri(&self) -> Result<String, NixideError> {
|
||||
wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_uri(
|
||||
|
|
@ -209,7 +195,7 @@ impl Store {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn store_dir(&self) -> NixideResult<PathBuf> {
|
||||
pub fn store_dir(&self) -> Result<PathBuf, NixideError> {
|
||||
wrap::nix_pathbuf_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_get_storedir(
|
||||
|
|
@ -222,26 +208,34 @@ impl Store {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn copy_closure_to(&self, dst_store: &Store, store_path: &StorePath) -> NixideResult<()> {
|
||||
pub fn copy_closure_to(
|
||||
&self,
|
||||
dst_store: &Store,
|
||||
store_path: &StorePath,
|
||||
) -> Result<(), NixideError> {
|
||||
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) -> NixideResult<()> {
|
||||
pub fn copy_closure_from(
|
||||
&self,
|
||||
src_store: &Store,
|
||||
store_path: &StorePath,
|
||||
) -> Result<(), NixideError> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_store_copy_closure(
|
||||
ctx.as_ptr(),
|
||||
src_store.as_ptr(),
|
||||
self.as_ptr(),
|
||||
store_path.as_ptr(),
|
||||
store_path.inner.as_ptr(),
|
||||
);
|
||||
})
|
||||
}) // semi-colon to return () and not i32
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,3 +246,7 @@ 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::{CString, c_void};
|
||||
use std::ffi::{c_void, CString};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::Store;
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::errors::{new_nixide_error, ErrorContext};
|
||||
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,25 +18,6 @@ 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 {
|
||||
|
|
@ -146,3 +127,26 @@ 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,24 +2,39 @@ 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() {
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
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");
|
||||
};
|
||||
|
||||
let _store = Store::default().expect("Failed to open store");
|
||||
let _store = Store::open(None).expect("Failed to open store");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_store_path_parse() {
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
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");
|
||||
};
|
||||
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
let store = Store::open(None).expect("Failed to open store");
|
||||
|
||||
// Try parsing a well-formed store path
|
||||
let result = StorePath::fake_path(&store);
|
||||
|
|
@ -29,9 +44,17 @@ fn test_store_path_parse() {
|
|||
#[test]
|
||||
#[serial]
|
||||
fn test_store_path_clone() {
|
||||
assert!(unsafe { matches!(LIBNIX_INIT_STATUS, Some(Ok(_))) });
|
||||
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");
|
||||
};
|
||||
|
||||
let store = Store::default().expect("Failed to open store");
|
||||
let store = Store::open(None).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