Compare commits
No commits in common. "cb2ac77f1edd7ecf4dac1d5de680d0674452bb37" and "f6de1d7b208d5b5396265e87c8bfce2c68c2b0f0" have entirely different histories.
cb2ac77f1e
...
f6de1d7b20
25 changed files with 604 additions and 596 deletions
18
flake.lock
generated
18
flake.lock
generated
|
|
@ -8,11 +8,11 @@
|
|||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776025235,
|
||||
"narHash": "sha256-zZIrW6G6GiFkpfFrOVjxYAVcXoKBMHv06kaUTOiqOq0=",
|
||||
"lastModified": 1774682177,
|
||||
"narHash": "sha256-OVbuJnJLlbHE28eRMudjtA6NXz/ifuXSho79gvh6GHY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "dfe3f197bf8f3e95d705b7323b46e3a087c88972",
|
||||
"rev": "e0f515387df77b9fdbaaf81e7f866f0365474c18",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -23,11 +23,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1775710090,
|
||||
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
||||
"lastModified": 1775036866,
|
||||
"narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
||||
"rev": "6201e203d09599479a3b3450ed24fa81537ebc4e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -47,11 +47,11 @@
|
|||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1775939146,
|
||||
"narHash": "sha256-YI8Hkuc2PSEJNwC8Qj3/DlMt1JfRv0MqzrnH/Mh9i5s=",
|
||||
"lastModified": 1774569884,
|
||||
"narHash": "sha256-E8iWEPzg7OnE0XXXjo75CX7xFauqzJuGZ5wSO9KS8Ek=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "09dc7aca674f53032f9d819f6fea01046e3d473f",
|
||||
"rev": "443ddcddd0c73b07b799d052f5ef3b448c2f3508",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
201
flake.nix
201
flake.nix
|
|
@ -24,6 +24,7 @@
|
|||
allowUnfree = false;
|
||||
allowBroken = false;
|
||||
overlays = builtins.attrValues self.overlays or {};
|
||||
# config.replaceStdenv = {pkgs}: with pkgs; llvmPackages_21.stdenv;
|
||||
};
|
||||
|
||||
forAllSystems = f:
|
||||
|
|
@ -35,6 +36,9 @@
|
|||
});
|
||||
in {
|
||||
overlays = {
|
||||
default = self: super: {
|
||||
libclang = super.llvmPackages_21.libclang;
|
||||
};
|
||||
fenix = inputs.fenix.overlays.default;
|
||||
};
|
||||
|
||||
|
|
@ -43,126 +47,129 @@
|
|||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
nixForBindings = pkgs.nixVersions.nix_2_34;
|
||||
inherit (pkgs.rustc) llvmPackages;
|
||||
in {
|
||||
default = pkgs.mkShell rec {
|
||||
name = "nixide";
|
||||
shell = "${pkgs.bash}/bin/bash";
|
||||
strictDeps = true;
|
||||
}: {
|
||||
default = let
|
||||
nixForBindings = pkgs.nixVersions.nix_2_34;
|
||||
inherit (pkgs.rustc) llvmPackages;
|
||||
in
|
||||
pkgs.mkShell rec {
|
||||
name = "nixide";
|
||||
shell = "${pkgs.bash}/bin/bash";
|
||||
strictDeps = true;
|
||||
|
||||
# packages we need at runtime
|
||||
packages = with pkgs; [
|
||||
rustc
|
||||
llvmPackages.lld
|
||||
llvmPackages.lldb
|
||||
# lldb
|
||||
# packages we need at runtime
|
||||
packages = with pkgs; [
|
||||
rustc
|
||||
llvmPackages.lld
|
||||
llvmPackages.lldb
|
||||
# lldb
|
||||
|
||||
cargo
|
||||
cargo-c
|
||||
cargo-llvm-cov
|
||||
cargo-nextest
|
||||
cargo
|
||||
cargo-c
|
||||
cargo-llvm-cov
|
||||
cargo-nextest
|
||||
|
||||
clang
|
||||
clang-tools
|
||||
clang # DEBUG
|
||||
clang-tools # DEBUG
|
||||
|
||||
libcxx
|
||||
libcxx
|
||||
|
||||
rust-analyzer-unwrapped
|
||||
(rustfmt.override {asNightly = true;})
|
||||
clippy
|
||||
taplo
|
||||
];
|
||||
rust-analyzer-unwrapped
|
||||
(rustfmt.override {asNightly = true;})
|
||||
clippy
|
||||
taplo
|
||||
];
|
||||
|
||||
# packages we need at build time
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pkg-config
|
||||
glibc.dev
|
||||
nixForBindings.dev
|
||||
# packages we need at build time
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pkg-config
|
||||
glibc.dev
|
||||
nixForBindings.dev
|
||||
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
# packages we link against
|
||||
buildInputs = [
|
||||
# pkgs.stdenv.cc
|
||||
# packages we link against
|
||||
buildInputs = with pkgs; [
|
||||
stdenv.cc
|
||||
|
||||
nixForBindings
|
||||
];
|
||||
nixForBindings
|
||||
];
|
||||
|
||||
env = {
|
||||
LD_LIBRARY_PATH = builtins.toString (lib.makeLibraryPath buildInputs);
|
||||
LIBCLANG_PATH = "${llvmPackages.libclang.lib}/lib";
|
||||
env = let
|
||||
inherit (llvmPackages) llvm libclang;
|
||||
in {
|
||||
LD_LIBRARY_PATH = builtins.toString (lib.makeLibraryPath buildInputs);
|
||||
LIBCLANG_PATH = "${libclang.lib}/lib";
|
||||
|
||||
RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
|
||||
BINDGEN_EXTRA_CLANG_ARGS = "--sysroot=${pkgs.glibc.dev}";
|
||||
RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
|
||||
BINDGEN_EXTRA_CLANG_ARGS = "--sysroot=${pkgs.glibc.dev}";
|
||||
|
||||
# `cargo-llvm-cov` reads these environment variables to find these binaries,
|
||||
# which are needed to run the tests
|
||||
LLVM_COV = "${llvmPackages.llvm}/bin/llvm-cov";
|
||||
LLVM_PROFDATA = "${llvmPackages.llvm}/bin/llvm-profdata";
|
||||
# `cargo-llvm-cov` reads these environment variables to find these binaries,
|
||||
# which are needed to run the tests
|
||||
LLVM_COV = "${llvm}/bin/llvm-cov";
|
||||
LLVM_PROFDATA = "${llvm}/bin/llvm-profdata";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# nightly = let
|
||||
# nixForBindings = pkgs.nixVersions.nix_2_34;
|
||||
# inherit (pkgs.rustc) llvmPackages;
|
||||
# in
|
||||
# pkgs.mkShell rec {
|
||||
# name = "nixide";
|
||||
# shell = "${pkgs.bash}/bin/bash";
|
||||
# strictDeps = true;
|
||||
nightly = let
|
||||
nixForBindings = pkgs.nixVersions.nix_2_34;
|
||||
inherit (pkgs.rustc) llvmPackages;
|
||||
in
|
||||
pkgs.mkShell rec {
|
||||
name = "nixide";
|
||||
shell = "${pkgs.bash}/bin/bash";
|
||||
strictDeps = true;
|
||||
|
||||
# # packages we need at runtime
|
||||
# packages = with pkgs; [
|
||||
# llvmPackages.lld
|
||||
# lldb
|
||||
# (pkgs.fenix.complete.withComponents [
|
||||
# "cargo"
|
||||
# "clippy"
|
||||
# "rust-src"
|
||||
# "rustc"
|
||||
# "rustfmt"
|
||||
# ])
|
||||
# rust-analyzer-nightly
|
||||
# packages we need at runtime
|
||||
packages = with pkgs; [
|
||||
llvmPackages.lld
|
||||
lldb
|
||||
(pkgs.fenix.complete.withComponents [
|
||||
"cargo"
|
||||
"clippy"
|
||||
"rust-src"
|
||||
"rustc"
|
||||
"rustfmt"
|
||||
])
|
||||
rust-analyzer-nightly
|
||||
|
||||
# # cargo-c
|
||||
# # cargo-llvm-cov
|
||||
# # cargo-nextest
|
||||
# ];
|
||||
# cargo-c
|
||||
# cargo-llvm-cov
|
||||
# cargo-nextest
|
||||
];
|
||||
|
||||
# # packages we need at build time
|
||||
# nativeBuildInputs = with pkgs; [
|
||||
# pkg-config
|
||||
# glibc.dev
|
||||
# nixForBindings.dev
|
||||
# packages we need at build time
|
||||
nativeBuildInputs = with pkgs; [
|
||||
pkg-config
|
||||
glibc.dev
|
||||
nixForBindings.dev
|
||||
|
||||
# rustPlatform.bindgenHook
|
||||
# ];
|
||||
rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
# # packages we link against
|
||||
# buildInputs = with pkgs; [
|
||||
# stdenv.cc
|
||||
# packages we link against
|
||||
buildInputs = with pkgs; [
|
||||
stdenv.cc
|
||||
|
||||
# nixForBindings
|
||||
# ];
|
||||
nixForBindings
|
||||
];
|
||||
|
||||
# env = let
|
||||
# inherit (llvmPackages) llvm libclang;
|
||||
# in {
|
||||
# LD_LIBRARY_PATH = builtins.toString (lib.makeLibraryPath buildInputs);
|
||||
# LIBCLANG_PATH = "${libclang.lib}/lib";
|
||||
env = let
|
||||
inherit (llvmPackages) llvm libclang;
|
||||
in {
|
||||
LD_LIBRARY_PATH = builtins.toString (lib.makeLibraryPath buildInputs);
|
||||
LIBCLANG_PATH = "${libclang.lib}/lib";
|
||||
|
||||
# RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
|
||||
# BINDGEN_EXTRA_CLANG_ARGS = "--sysroot=${pkgs.glibc.dev}";
|
||||
RUST_SRC_PATH = "${pkgs.rustPlatform.rustLibSrc}";
|
||||
BINDGEN_EXTRA_CLANG_ARGS = "--sysroot=${pkgs.glibc.dev}";
|
||||
|
||||
# # `cargo-llvm-cov` reads these environment variables to find these binaries,
|
||||
# # which are needed to run the tests
|
||||
# LLVM_COV = "${llvm}/bin/llvm-cov";
|
||||
# LLVM_PROFDATA = "${llvm}/bin/llvm-profdata";
|
||||
# };
|
||||
# };
|
||||
# `cargo-llvm-cov` reads these environment variables to find these binaries,
|
||||
# which are needed to run the tests
|
||||
LLVM_COV = "${llvm}/bin/llvm-cov";
|
||||
LLVM_PROFDATA = "${llvm}/bin/llvm-profdata";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ fn main() {
|
|||
// .cargo_debug(cfg!(debug_assertions))
|
||||
.cpp(true)
|
||||
.std("c++23") // libnix compiles against `-std=c++23`
|
||||
.cpp_link_stdlib("c++") // libstdc++ for GNU, c++ for Clang
|
||||
.opt_level((!cfg!(debug_assertions)) as u32 * 3)
|
||||
.files(FEATURES.iter().map(|&feature| format!("libnixide-c/nixide_api_{feature}.cc")))
|
||||
.includes(&include_paths)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ nix_err nix_register_plugin(nix_c_context * context, char * plugin)
|
|||
context->last_err_code = NIX_OK;
|
||||
if (plugin == nullptr) {
|
||||
// TODO: should this be `NIX_ERR_RECOVERABLE` or `NIX_ERR_UNKNOWN`?
|
||||
return nix_set_err_msg(context, NIX_ERR_UNKNOWN, "Plugin is null");
|
||||
return nix_set_err_msg(context, NIX_ERR_RECOVERABLE, "Plugin is null");
|
||||
}
|
||||
|
||||
void * handle = dlopen("libnixmainc.so", RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
|
|
|||
|
|
@ -21,15 +21,14 @@
|
|||
// static std::optional<std::string> programName;
|
||||
// };
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::ffi::c_uint;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::{NixError, NixideResult};
|
||||
use crate::errors::ToNixideResult as _;
|
||||
use crate::stdext::CCharPtrExt as _;
|
||||
use crate::stdext::{AsCPtr as _, CCharPtrExt as _};
|
||||
use crate::sys;
|
||||
use crate::util::panic_issue_call_failed;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
|
|
@ -101,7 +100,7 @@ impl Into<NixideResult<()>> for &ErrorContext {
|
|||
};
|
||||
let msg = match self.get_msg() {
|
||||
Some(msg) => msg,
|
||||
None => String::new(),
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let err = match inner {
|
||||
|
|
@ -110,8 +109,13 @@ impl Into<NixideResult<()>> for &ErrorContext {
|
|||
sys::NixErr::Overflow => NixError::Overflow,
|
||||
sys::NixErr::Key => NixError::KeyNotFound(None),
|
||||
sys::NixErr::NixError => NixError::ExprEval {
|
||||
name: self.get_nix_err_name().unwrap(),
|
||||
info_msg: self.get_nix_err_info_msg().unwrap_or_else(|| String::new()),
|
||||
name: self
|
||||
.get_nix_err_name()
|
||||
.unwrap_or_else(|| panic_issue_call_failed!()),
|
||||
|
||||
info_msg: self
|
||||
.get_nix_err_info_msg()
|
||||
.unwrap_or_else(|| panic_issue_call_failed!()),
|
||||
},
|
||||
|
||||
// XXX: WARNING: Recoverable only exists in later version of Nix
|
||||
|
|
@ -190,11 +194,11 @@ impl ErrorContext {
|
|||
///
|
||||
#[allow(unused)]
|
||||
pub fn set_err(&self, err: NixError, msg: &str) -> NixideResult<()> {
|
||||
let ctx = unsafe { self.as_ptr() };
|
||||
let c_msg = CString::new(msg).to_nixide_result()?;
|
||||
let ptr = unsafe { self.as_ptr() };
|
||||
assert!(!ptr.is_null(), "");
|
||||
|
||||
unsafe {
|
||||
sys::nix_set_err_msg(ctx, err.err_code(), c_msg.as_ptr());
|
||||
sys::nix_set_err_msg(ptr, err.err_code(), msg.as_c_ptr()?);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -213,7 +217,7 @@ impl ErrorContext {
|
|||
///
|
||||
/// This function **never fails**.
|
||||
///
|
||||
pub fn get_err(&self) -> Option<sys::NixErr> {
|
||||
fn get_err(&self) -> Option<sys::NixErr> {
|
||||
match unsafe { sys::nix_err_code(self.as_ptr()) } {
|
||||
sys::NixErr::Ok => None,
|
||||
err => Some(err),
|
||||
|
|
@ -250,7 +254,7 @@ impl ErrorContext {
|
|||
/// Hence we can just test whether the returned pointer is a `NULL` pointer,
|
||||
/// and avoid passing in a [NixCContext] struct.
|
||||
///
|
||||
pub fn get_msg(&self) -> Option<String> {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -5,16 +5,6 @@ use crate::sys;
|
|||
|
||||
pub type NixideResult<T> = Result<T, NixideError>;
|
||||
|
||||
pub(crate) trait ToNixideResult<T> {
|
||||
fn to_nixide_result(self) -> NixideResult<T>;
|
||||
}
|
||||
|
||||
impl<T> ToNixideResult<T> for Result<T, std::ffi::NulError> {
|
||||
fn to_nixide_result(self) -> NixideResult<T> {
|
||||
Err(new_nixide_error!(StringNulByte))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum NixideError {
|
||||
/// # Warning
|
||||
|
|
@ -144,3 +134,16 @@ impl Display for NixideError {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pub trait AsErr<T> {
|
||||
// fn as_err(self) -> Result<(), T>;
|
||||
// }
|
||||
|
||||
// impl AsErr<NixideError> for Option<NixideError> {
|
||||
// fn as_err(self) -> Result<(), NixideError> {
|
||||
// match self {
|
||||
// Some(err) => Err(err),
|
||||
// None => Ok(()),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@ mod context;
|
|||
mod nix_error;
|
||||
|
||||
pub(crate) use context::ErrorContext;
|
||||
pub(crate) use error::new_nixide_error;
|
||||
pub use error::{NixideError, NixideResult};
|
||||
pub(crate) use error::{ToNixideResult, new_nixide_error};
|
||||
pub use nix_error::NixError;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::stdext::AsCPtr as _;
|
||||
|
||||
use super::Value;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::util::{panic_issue_call_failed, wrap};
|
||||
|
|
@ -21,6 +22,22 @@ pub struct EvalState {
|
|||
store: Rc<RefCell<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 {
|
||||
|
|
@ -70,8 +87,8 @@ impl EvalState {
|
|||
/// Returns an error if evaluation fails.
|
||||
///
|
||||
pub fn interpret(&self, expr: &str, path: &str) -> NixideResult<Value> {
|
||||
let c_expr = CString::new(expr).to_nixide_result()?;
|
||||
let c_path = CString::new(path).to_nixide_result()?;
|
||||
let expr = expr.as_c_ptr()?;
|
||||
let path = path.as_c_ptr()?;
|
||||
|
||||
// Allocate value for result
|
||||
// XXX: TODO: create a method for this (``)
|
||||
|
|
@ -82,15 +99,10 @@ impl EvalState {
|
|||
|
||||
// Evaluate expression
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_expr_eval_from_string(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_expr.as_ptr(),
|
||||
c_path.as_ptr(),
|
||||
value.as_ptr(),
|
||||
);
|
||||
Value::from((value, self.inner_ref().clone()))
|
||||
sys::nix_expr_eval_from_string(ctx.as_ptr(), self.as_ptr(), expr, path, value.as_ptr());
|
||||
value
|
||||
})
|
||||
.map(|ptr| Value::from((ptr, self.inner_ref().clone())))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,15 @@
|
|||
use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
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::errors::{ErrorContext, NixideError, ToNixideResult as _};
|
||||
use crate::stdext::CCharPtrExt;
|
||||
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::{NixError, NixideResult};
|
||||
|
||||
pub struct NixAttrs {
|
||||
inner: NonNull<sys::NixValue>,
|
||||
|
|
@ -171,58 +170,55 @@ impl NixAttrs {
|
|||
Some(name)
|
||||
}
|
||||
|
||||
pub fn get<T>(&self, name: T) -> NixideResult<Option<Value>>
|
||||
pub fn get<T>(&self, name: T) -> Option<Value>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
let c_name = CString::new(name.as_ref()).to_nixide_result()?;
|
||||
|
||||
let result = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byname(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
c_name.as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Ok(Some(Value::from((inner, self.state.clone())))),
|
||||
Ok(inner) => Some(Value::from((inner, self.state.clone()))),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
..
|
||||
}) => Ok(None),
|
||||
Err(err) => Err(err),
|
||||
}) => None,
|
||||
Err(err) => panic_issue_call_failed!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lazy<T>(&self, name: T) -> NixideResult<Option<NixThunk>>
|
||||
pub fn get_lazy<T>(&self, name: T) -> Option<NixThunk>
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
let c_name = CString::new(name.as_ref()).to_nixide_result()?;
|
||||
|
||||
let result = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_get_attr_byname_lazy(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
self.state.borrow().as_ptr(),
|
||||
c_name.as_ptr(),
|
||||
name.as_ref()
|
||||
.into_c_ptr()
|
||||
.unwrap_or_else(|err| panic_issue_call_failed!("{}", err)),
|
||||
)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(inner) => Ok(Some(<NixThunk as NixValue>::from(
|
||||
inner,
|
||||
self.state.clone(),
|
||||
))),
|
||||
Ok(inner) => Some(<NixThunk as NixValue>::from(inner, self.state.clone())),
|
||||
|
||||
Err(NixideError::NixError {
|
||||
err: NixError::KeyNotFound(_),
|
||||
..
|
||||
}) => Ok(None),
|
||||
Err(err) => Err(err),
|
||||
}) => None,
|
||||
Err(err) => panic_issue_call_failed!("{}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::ffi::{CString, c_char};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -11,6 +11,19 @@ pub struct FetchersSettings {
|
|||
inner: NonNull<sys::NixFetchersSettings>,
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
|
@ -37,13 +50,12 @@ impl AsInnerPtr<sys::NixFetchersSettings> for FetchersSettings {
|
|||
}
|
||||
|
||||
impl FetchersSettings {
|
||||
pub fn new() -> Self {
|
||||
pub fn new() -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_new(ctx.as_ptr())
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
|
||||
Self { inner }
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
|
|
@ -55,22 +67,22 @@ impl FetchersSettings {
|
|||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
#[allow(unused)]
|
||||
pub fn add_access_token(&self, token_name: &str, token_value: &str) -> NixideResult<()> {
|
||||
pub fn add_access_token(self, token_name: &str, token_value: &str) -> NixideResult<Self> {
|
||||
// XXX: TODO: have a dedicated `self.access_tokens: HashMap<String, String>` instead
|
||||
let c_name = CString::new(token_name).to_nixide_result()?;
|
||||
let c_value = CString::new(token_value).to_nixide_result()?;
|
||||
let name_ptr = token_name.into_c_ptr()?;
|
||||
let value_ptr = token_value.into_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_add_access_token(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_name.as_ptr() as *mut c_char,
|
||||
c_value.as_ptr() as *mut c_char,
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
|
|
@ -82,20 +94,16 @@ impl FetchersSettings {
|
|||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
#[allow(unused)]
|
||||
pub fn remove_access_token(&self, token_name: &str) -> NixideResult<()> {
|
||||
pub fn remove_access_token(self, token_name: &str) -> NixideResult<Self> {
|
||||
// XXX: TODO: have a dedicated `self.access_tokens: HashMap<String, String>` instead
|
||||
let c_name = CString::new(token_name).to_nixide_result()?;
|
||||
let name_ptr = token_name.into_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_remove_access_token(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_name.as_ptr() as *mut c_char,
|
||||
);
|
||||
sys::nix_fetchers_settings_remove_access_token(ctx.as_ptr(), self.as_ptr(), name_ptr);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -103,11 +111,14 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn allow_dirty(&self, value: bool) {
|
||||
#[allow(unused)]
|
||||
pub fn allow_dirty(self, value: bool) -> Self {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_allow_dirty(ctx.as_ptr(), self.as_ptr(), value);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -115,11 +126,14 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn warn_dirty(&self, value: bool) {
|
||||
#[allow(unused)]
|
||||
pub fn warn_dirty(self, value: bool) -> Self {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_warn_dirty(ctx.as_ptr(), self.as_ptr(), value);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -127,11 +141,14 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn allow_dirty_locks(&self, value: bool) {
|
||||
#[allow(unused)]
|
||||
pub fn allow_dirty_locks(self, value: bool) -> Self {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_allow_dirty_locks(ctx.as_ptr(), self.as_ptr(), value);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -139,7 +156,8 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn trust_tarballs_from_git_forges(&self, value: bool) {
|
||||
#[allow(unused)]
|
||||
pub fn trust_tarballs_from_git_forges(self, value: bool) -> Self {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_trust_tarballs_from_git_forges(
|
||||
ctx.as_ptr(),
|
||||
|
|
@ -148,6 +166,8 @@ impl FetchersSettings {
|
|||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -155,15 +175,17 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn tarball_ttl(&self, ttl: u32) {
|
||||
#[allow(unused)]
|
||||
pub fn tarball_ttl(self, ttl: u32) -> Self {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_tarball_ttl(ctx.as_ptr(), self.as_ptr(), ttl);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
///
|
||||
/// Fails if the given `registry` contains a NUL byte.
|
||||
///
|
||||
/// # Nix C API Internals
|
||||
|
|
@ -171,19 +193,20 @@ impl FetchersSettings {
|
|||
/// This binding is **not provided by the Nix C API.**
|
||||
/// It is instead **exposed by the Nixide C API extensions.**
|
||||
///
|
||||
pub fn global_flake_registry(&self, registry: &str) -> NixideResult<()> {
|
||||
let c_registry = CString::new(registry).to_nixide_result()?;
|
||||
#[allow(unused)]
|
||||
pub fn global_flake_registry(self, registry: &str) -> NixideResult<Self> {
|
||||
let registry_ptr = registry.into_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_fetchers_settings_set_global_flake_registry(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_registry.as_ptr() as *mut c_char,
|
||||
registry_ptr,
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +216,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn fetchers_settings_new() {
|
||||
let _ = FetchersSettings::new();
|
||||
let _ = FetchersSettings::new().unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
use std::ffi::{CString, c_char};
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ffi::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use super::FlakeRef;
|
||||
use super::{FlakeRef, FlakeSettings};
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum LockMode {
|
||||
pub enum FlakeLockMode {
|
||||
/// Configures [LockedFlake::lock] to make incremental changes to the lock file as needed. Changes are written to file.
|
||||
///
|
||||
/// This is the default mode.
|
||||
|
|
@ -27,7 +28,7 @@ pub enum LockMode {
|
|||
|
||||
/// Parameters that affect the locking of a flake.
|
||||
pub struct FlakeLockFlags {
|
||||
inner: NonNull<sys::NixFlakeLockFlags>,
|
||||
pub(crate) inner: NonNull<sys::NixFlakeLockFlags>,
|
||||
}
|
||||
|
||||
// impl Clone for FlakeLockFlags {
|
||||
|
|
@ -69,38 +70,12 @@ impl AsInnerPtr<sys::NixFlakeLockFlags> for FlakeLockFlags {
|
|||
}
|
||||
|
||||
impl FlakeLockFlags {
|
||||
pub fn new(mode: LockMode) -> Self {
|
||||
// NOTE: `nix_flake_lock_flags_new` is a simple initialisation
|
||||
// NOTE: and will only fail if out of memory (hence we can "safely" unwrap).
|
||||
pub fn new(settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// NOTE: `nix_flake_lock_flags_new` currently never uses the `settings`
|
||||
// NOTE: parameter, hence providing a null pointer is fine.
|
||||
sys::nix_flake_lock_flags_new(ctx.as_ptr(), ptr::null_mut())
|
||||
})
|
||||
.unwrap();
|
||||
sys::nix_flake_lock_flags_new(ctx.as_ptr(), settings.as_ptr())
|
||||
})?;
|
||||
|
||||
let self_ = FlakeLockFlags { inner };
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| {
|
||||
match mode {
|
||||
LockMode::WriteAsNeeded => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_write_as_needed(ctx.as_ptr(), self_.as_ptr())
|
||||
},
|
||||
LockMode::Virtual => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_virtual(ctx.as_ptr(), self_.as_ptr())
|
||||
},
|
||||
LockMode::Check => unsafe {
|
||||
sys::nix_flake_lock_flags_set_mode_check(ctx.as_ptr(), self_.as_ptr())
|
||||
},
|
||||
};
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
self_
|
||||
}
|
||||
|
||||
pub fn default() -> Self {
|
||||
Self::new(LockMode::WriteAsNeeded)
|
||||
Ok(FlakeLockFlags { inner })
|
||||
}
|
||||
|
||||
/// Adds an input override to the lock file that will be produced.
|
||||
|
|
@ -119,13 +94,13 @@ impl FlakeLockFlags {
|
|||
#[allow(unused)]
|
||||
pub fn override_input(self, input: &str, flakeref: &FlakeRef) -> NixideResult<Self> {
|
||||
// XXX: TODO: should `input` be wrapped as `format!("inputs.{input}")`?
|
||||
let c_input = CString::new(input).to_nixide_result()?;
|
||||
let input_path = input.as_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_add_input_override(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_input.as_ptr(),
|
||||
input_path,
|
||||
flakeref.as_ptr(),
|
||||
);
|
||||
})?;
|
||||
|
|
@ -147,14 +122,29 @@ impl FlakeLockFlags {
|
|||
#[allow(unused)]
|
||||
pub fn update_input(self, input: &str) -> NixideResult<Self> {
|
||||
// XXX: TODO: should `input` be wrapped as `format!("inputs.{input}")`?
|
||||
let c_input = CString::new(input).to_nixide_result()?;
|
||||
let input_path = input.as_c_ptr()?;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_add_input_update(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_input.as_ptr(),
|
||||
);
|
||||
sys::nix_flake_lock_flags_add_input_update(ctx.as_ptr(), self.as_ptr(), input_path);
|
||||
})?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn set_mode(self, mode: FlakeLockMode) -> NixideResult<Self> {
|
||||
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())
|
||||
},
|
||||
};
|
||||
})?;
|
||||
|
||||
Ok(self)
|
||||
|
|
@ -290,13 +280,13 @@ impl FlakeLockFlags {
|
|||
///
|
||||
#[allow(unused)]
|
||||
pub fn input_lock_file_path(self, path: &str) -> NixideResult<Self> {
|
||||
let c_path = CString::new(path).to_nixide_result()?;
|
||||
let path_ptr = path.as_c_ptr()? as *mut c_char;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_set_reference_lock_file_path(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_path.as_ptr() as *mut c_char,
|
||||
path_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
|
@ -314,13 +304,13 @@ impl FlakeLockFlags {
|
|||
///
|
||||
#[allow(unused)]
|
||||
pub fn output_lock_file_path(self, path: &str) -> NixideResult<Self> {
|
||||
let c_path = CString::new(path).to_nixide_result()?;
|
||||
let path_ptr = path.as_c_ptr()? as *mut c_char;
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_lock_flags_set_output_lock_file_path(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_path.as_ptr() as *mut c_char,
|
||||
path_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::ffi::CString;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -86,12 +86,12 @@ impl FlakeSettings {
|
|||
///
|
||||
#[allow(unused)]
|
||||
pub fn commit_lock_file_summary(self, summary: &str) -> NixideResult<Self> {
|
||||
let c_summary = CString::new(summary).to_nixide_result()?;
|
||||
let summary_ptr = summary.into_c_ptr()?;
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_settings_set_commit_lock_file_summary(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_summary.as_ptr().cast_mut(),
|
||||
summary_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,35 @@
|
|||
use std::ptr::NonNull;
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::ptr::{NonNull, null_mut};
|
||||
|
||||
use super::{FetchersSettings, FlakeRefParseFlags, FlakeSettings};
|
||||
use crate::NixideError;
|
||||
use crate::errors::{ErrorContext, new_nixide_error};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
pub struct FlakeRef {
|
||||
inner: NonNull<sys::NixFlakeReference>,
|
||||
fragment: String,
|
||||
|
||||
fetch_settings: FetchersSettings,
|
||||
flake_settings: FlakeSettings,
|
||||
}
|
||||
|
||||
// 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 FlakeRef {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
|
@ -33,13 +55,45 @@ impl AsInnerPtr<sys::NixFlakeReference> for FlakeRef {
|
|||
}
|
||||
}
|
||||
|
||||
// XXX: TODO: is it possible to get the URI string itself? (minus the fragment part?)
|
||||
impl FlakeRef {
|
||||
#[inline]
|
||||
pub(crate) fn new(inner: NonNull<sys::NixFlakeReference>, fragment: String) -> Self {
|
||||
Self { inner, fragment }
|
||||
/// 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<S: AsRef<str>>(reference: S) -> Result<FlakeRef, NixideError> {
|
||||
let fetch_settings = FetchersSettings::new()?;
|
||||
let flake_settings = FlakeSettings::new()?;
|
||||
let parse_flags = FlakeRefParseFlags::new(&flake_settings)?;
|
||||
|
||||
let mut ptr: *mut sys::NixFlakeReference = 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(),
|
||||
parse_flags.as_ptr(),
|
||||
reference.as_ref().as_ptr() as *const c_char,
|
||||
reference.as_ref().len(),
|
||||
&mut ptr,
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
}
|
||||
)?;
|
||||
|
||||
match NonNull::new(ptr) {
|
||||
Some(inner) => Ok(FlakeRef {
|
||||
inner,
|
||||
fragment,
|
||||
fetch_settings,
|
||||
flake_settings,
|
||||
}),
|
||||
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]
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
use std::ffi::{CString, c_void};
|
||||
use std::path::Path;
|
||||
use std::ptr::{self, NonNull, null_mut};
|
||||
|
||||
use super::{FetchersSettings, FlakeRef, FlakeRefParseFlags};
|
||||
use crate::errors::{ErrorContext, NixideResult, ToNixideResult as _, new_nixide_error};
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
||||
pub struct FlakeRefBuilder {
|
||||
reference: String,
|
||||
fetch_settings: FetchersSettings,
|
||||
parse_flags: FlakeRefParseFlags,
|
||||
}
|
||||
|
||||
impl FlakeRefBuilder {
|
||||
/// 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 new<S: AsRef<str>>(reference: S) -> Self {
|
||||
Self {
|
||||
reference: reference.as_ref().to_string(),
|
||||
fetch_settings: FetchersSettings::new(),
|
||||
parse_flags: FlakeRefParseFlags::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(&self) -> NixideResult<FlakeRef> {
|
||||
let c_reference = CString::new(self.reference.as_str()).to_nixide_result()?;
|
||||
|
||||
let mut ptr: *mut sys::NixFlakeReference = null_mut();
|
||||
let fragment = wrap::nix_string_callback!(
|
||||
|callback, userdata: *mut __UserData, ctx: &ErrorContext| unsafe {
|
||||
// NOTE: `nix_flake_reference_and_fragment_from_string` currently
|
||||
// NOTE: never uses the `flake_settings` parameter, hence providing
|
||||
// NOTE: a null pointer instead is fine.
|
||||
sys::nix_flake_reference_and_fragment_from_string(
|
||||
ctx.as_ptr(),
|
||||
self.fetch_settings.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
self.parse_flags.as_ptr(),
|
||||
c_reference.as_ptr(),
|
||||
self.reference.len(),
|
||||
&mut ptr,
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
)
|
||||
}
|
||||
)?;
|
||||
|
||||
match NonNull::new(ptr) {
|
||||
Some(inner) => Ok(FlakeRef::new(inner, fragment)),
|
||||
None => Err(new_nixide_error!(NullPtr)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base_directory<P: AsRef<Path>>(mut self, path: P) -> NixideResult<Self> {
|
||||
self.parse_flags
|
||||
.base_directory(&path.as_ref().to_string_lossy())?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn global_flake_registry(self, registry: &str) -> NixideResult<Self> {
|
||||
self.fetch_settings.global_flake_registry(registry)?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn allow_dirty(self, value: bool) -> Self {
|
||||
self.fetch_settings.allow_dirty(value);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn warn_dirty(self, value: bool) -> Self {
|
||||
self.fetch_settings.warn_dirty(value);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn allow_dirty_locks(self, value: bool) -> Self {
|
||||
self.fetch_settings.allow_dirty_locks(value);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn trust_tarballs_from_git_forges(self, value: bool) -> Self {
|
||||
self.fetch_settings.trust_tarballs_from_git_forges(value);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn tarball_ttl(self, ttl: u32) -> Self {
|
||||
self.fetch_settings.tarball_ttl(ttl);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,36 @@
|
|||
use std::ffi::CString;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ffi::c_char;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use super::FlakeSettings;
|
||||
use crate::NixideResult;
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
use crate::{NixideResult, sys};
|
||||
|
||||
/// Parameters for parsing a flake reference.
|
||||
///
|
||||
/// # Nix C API Internals
|
||||
///
|
||||
/// Currently the Nix C API only uses this for storing
|
||||
/// a base directory... Kinda overkill no? ;w;
|
||||
///
|
||||
#[derive(Debug)]
|
||||
// pub(super) struct FlakeRefParseFlags {
|
||||
pub struct FlakeRefParseFlags {
|
||||
// DEBUG (go back to pub(super) soon)
|
||||
inner: NonNull<sys::NixFlakeReferenceParseFlags>,
|
||||
}
|
||||
|
||||
// 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 FlakeRefParseFlags {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
sys::nix_flake_reference_parse_flags_free(self.as_ptr());
|
||||
sys::nix_flake_reference_parse_flags_free(self.inner.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,40 +53,24 @@ impl AsInnerPtr<sys::NixFlakeReferenceParseFlags> for FlakeRefParseFlags {
|
|||
}
|
||||
|
||||
impl FlakeRefParseFlags {
|
||||
pub fn new() -> Self {
|
||||
// NOTE: `nix_flake_reference_parse_flags_new` is a simple initialisation
|
||||
// NOTE: and will only fail if out of memory (hence we can "safely" unwrap).
|
||||
pub fn new(settings: &FlakeSettings) -> NixideResult<Self> {
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// NOTE: `nix_flake_reference_parse_flags_new` currently never uses the `settings`
|
||||
// NOTE: parameter, hence providing a null pointer is fine.
|
||||
sys::nix_flake_reference_parse_flags_new(ctx.as_ptr(), ptr::null_mut())
|
||||
})
|
||||
.unwrap();
|
||||
sys::nix_flake_reference_parse_flags_new(ctx.as_ptr(), settings.as_ptr())
|
||||
})?;
|
||||
|
||||
Self { inner }
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
/// Sets the [base directory](https://nix.dev/manual/nix/latest/glossary#gloss-base-directory)
|
||||
/// for resolving local flake references.
|
||||
///
|
||||
/// # Nix C API Internals
|
||||
///
|
||||
/// If `set_base_directory` is never called, the base directory defaults
|
||||
/// to the current working directory (see `libutil/filesystem.cc:absPath`).
|
||||
///
|
||||
pub fn base_directory(&mut self, base_directory: &str) -> NixideResult<()> {
|
||||
let c_base_directory = CString::new(base_directory).to_nixide_result()?;
|
||||
|
||||
pub fn set_base_directory(&mut self, base_directory: &str) -> NixideResult<()> {
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_flake_reference_parse_flags_set_base_directory(
|
||||
ctx.as_ptr(),
|
||||
self.as_ptr(),
|
||||
c_base_directory.as_ptr(),
|
||||
base_directory.as_ptr() as *const c_char,
|
||||
base_directory.len(),
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// XXX: TODO: find a way to read directly from FlakeSettings and FetchersSettings (the C++ classes)
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::ptr::NonNull;
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::{FlakeLockFlags, FlakeRef, FlakeRefBuilder, FlakeSettings};
|
||||
use super::{FetchersSettings, FlakeLockFlags, FlakeLockMode, FlakeRef, FlakeSettings};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
|
|
@ -15,6 +17,7 @@ pub struct LockedFlake {
|
|||
flakeref: FlakeRef,
|
||||
state: Rc<RefCell<NonNull<sys::EvalState>>>,
|
||||
lock_flags: FlakeLockFlags,
|
||||
fetch_settings: FetchersSettings,
|
||||
flake_settings: FlakeSettings,
|
||||
}
|
||||
|
||||
|
|
@ -45,19 +48,19 @@ impl AsInnerPtr<sys::NixLockedFlake> for LockedFlake {
|
|||
|
||||
impl LockedFlake {
|
||||
pub fn lock(
|
||||
lock_flags: FlakeLockFlags,
|
||||
mode: FlakeLockMode,
|
||||
flakeref: FlakeRef,
|
||||
state: &EvalState,
|
||||
) -> NixideResult<LockedFlake> {
|
||||
let state_inner = state.inner_ref();
|
||||
let fetch_settings = FetchersSettings::new()?;
|
||||
let flake_settings = FlakeSettings::new()?;
|
||||
let lock_flags = FlakeLockFlags::new(&flake_settings)?.set_mode(mode)?;
|
||||
|
||||
let inner = wrap::nix_ptr_fn!(|ctx: &ErrorContext| unsafe {
|
||||
// NOTE: `nix_flake_lock` currently never uses the `fetchSettings`
|
||||
// NOTE: parameter, hence providing a null pointer instead is fine.
|
||||
sys::nix_flake_lock(
|
||||
ctx.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
fetch_settings.as_ptr(),
|
||||
flake_settings.as_ptr(),
|
||||
state_inner.borrow().as_ptr(),
|
||||
lock_flags.as_ptr(),
|
||||
|
|
@ -70,6 +73,7 @@ impl LockedFlake {
|
|||
flakeref,
|
||||
state: state_inner.clone(),
|
||||
lock_flags,
|
||||
fetch_settings,
|
||||
flake_settings,
|
||||
})
|
||||
}
|
||||
|
|
@ -94,8 +98,8 @@ mod tests {
|
|||
use std::fs;
|
||||
use std::sync::Once;
|
||||
|
||||
use super::{FlakeLockFlags, FlakeRefBuilder, FlakeSettings, LockedFlake};
|
||||
use crate::flake::LockMode;
|
||||
use super::{FetchersSettings, FlakeLockFlags, FlakeRef, FlakeSettings, LockedFlake};
|
||||
use crate::flake::{FlakeLockMode, FlakeRefParseFlags};
|
||||
use crate::{EvalStateBuilder, Store, Value, set_global_setting};
|
||||
|
||||
static INIT: Once = Once::new();
|
||||
|
|
@ -157,16 +161,12 @@ mod tests {
|
|||
.build()
|
||||
.unwrap();
|
||||
|
||||
// let flakeref = FlakeRefBuilder::new(format!("path:{}#subthing", tmp_dir.path().display())) // DEBUG
|
||||
let flakeref = FlakeRefBuilder::new(format!("{}#subthing", tmp_dir.path().display()))
|
||||
.build()
|
||||
.unwrap();
|
||||
let flakeref =
|
||||
FlakeRef::parse(&format!("path:{}#subthing", tmp_dir.path().display())).unwrap();
|
||||
|
||||
assert_eq!(flakeref.fragment(), "subthing");
|
||||
|
||||
let flake_lock_flags = FlakeLockFlags::new(LockMode::WriteAsNeeded);
|
||||
|
||||
let outputs = LockedFlake::lock(flake_lock_flags, flakeref, &eval_state)
|
||||
let outputs = LockedFlake::lock(FlakeLockMode::WriteAsNeeded, flakeref, &eval_state)
|
||||
.unwrap()
|
||||
.outputs()
|
||||
.unwrap();
|
||||
|
|
@ -175,203 +175,215 @@ mod tests {
|
|||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
assert!(matches!(value, Some(Value::String(_))));
|
||||
if let Some(Value::String(value)) = value {
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "world");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #[test] # DEBUG (too lazy to keep fixing this function...)
|
||||
// fn flake_lock_load_flake_with_flags() {
|
||||
// init();
|
||||
#[test]
|
||||
fn flake_lock_load_flake_with_flags() {
|
||||
init();
|
||||
|
||||
// let store_ref = Store::default().unwrap();
|
||||
// let flake_settings = FlakeSettings::new().unwrap();
|
||||
// let eval_state = EvalStateBuilder::new(store_ref.clone())
|
||||
// .unwrap()
|
||||
// .set_flake_settings(&flake_settings)
|
||||
// .unwrap()
|
||||
// .build()
|
||||
// .unwrap();
|
||||
let store_ref = Store::default().unwrap();
|
||||
let fetchers_settings = FetchersSettings::new().unwrap();
|
||||
let flake_settings = FlakeSettings::new().unwrap();
|
||||
let eval_state = EvalStateBuilder::new(store_ref.clone())
|
||||
.unwrap()
|
||||
.set_flake_settings(&flake_settings)
|
||||
.unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// let tmp_dir = tempfile::tempdir().unwrap();
|
||||
let tmp_dir = tempfile::tempdir().unwrap();
|
||||
|
||||
// let flake_dir_a = tmp_dir.path().join("a");
|
||||
// let flake_dir_b = tmp_dir.path().join("b");
|
||||
// let flake_dir_c = tmp_dir.path().join("c");
|
||||
let flake_dir_a = tmp_dir.path().join("a");
|
||||
let flake_dir_b = tmp_dir.path().join("b");
|
||||
let flake_dir_c = tmp_dir.path().join("c");
|
||||
|
||||
// std::fs::create_dir_all(&flake_dir_a).unwrap();
|
||||
// std::fs::create_dir_all(&flake_dir_b).unwrap();
|
||||
// std::fs::create_dir_all(&flake_dir_c).unwrap();
|
||||
std::fs::create_dir_all(&flake_dir_a).unwrap();
|
||||
std::fs::create_dir_all(&flake_dir_b).unwrap();
|
||||
std::fs::create_dir_all(&flake_dir_c).unwrap();
|
||||
|
||||
// let flake_dir_a_str = flake_dir_a.to_str().unwrap();
|
||||
// let flake_dir_c_str = flake_dir_c.to_str().unwrap();
|
||||
// assert!(!flake_dir_a_str.is_empty());
|
||||
// assert!(!flake_dir_c_str.is_empty());
|
||||
let flake_dir_a_str = flake_dir_a.to_str().unwrap();
|
||||
let flake_dir_c_str = flake_dir_c.to_str().unwrap();
|
||||
assert!(!flake_dir_a_str.is_empty());
|
||||
assert!(!flake_dir_c_str.is_empty());
|
||||
|
||||
// // a
|
||||
// std::fs::write(
|
||||
// tmp_dir.path().join("a/flake.nix"),
|
||||
// r#"
|
||||
// {
|
||||
// inputs.b.url = "@flake_dir_b@";
|
||||
// outputs = { b, ... }: {
|
||||
// hello = b.hello;
|
||||
// };
|
||||
// }
|
||||
// "#
|
||||
// .replace("@flake_dir_b@", flake_dir_b.to_str().unwrap()),
|
||||
// )
|
||||
// .unwrap();
|
||||
// a
|
||||
std::fs::write(
|
||||
tmp_dir.path().join("a/flake.nix"),
|
||||
r#"
|
||||
{
|
||||
inputs.b.url = "@flake_dir_b@";
|
||||
outputs = { b, ... }: {
|
||||
hello = b.hello;
|
||||
};
|
||||
}
|
||||
"#
|
||||
.replace("@flake_dir_b@", flake_dir_b.to_str().unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// // b
|
||||
// std::fs::write(
|
||||
// tmp_dir.path().join("b/flake.nix"),
|
||||
// r#"
|
||||
// {
|
||||
// outputs = { ... }: {
|
||||
// hello = "ALICE";
|
||||
// };
|
||||
// }
|
||||
// "#,
|
||||
// )
|
||||
// .unwrap();
|
||||
// b
|
||||
std::fs::write(
|
||||
tmp_dir.path().join("b/flake.nix"),
|
||||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "ALICE";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// // c
|
||||
// std::fs::write(
|
||||
// tmp_dir.path().join("c/flake.nix"),
|
||||
// r#"
|
||||
// {
|
||||
// outputs = { ... }: {
|
||||
// hello = "Claire";
|
||||
// };
|
||||
// }
|
||||
// "#,
|
||||
// )
|
||||
// .unwrap();
|
||||
// c
|
||||
std::fs::write(
|
||||
tmp_dir.path().join("c/flake.nix"),
|
||||
r#"
|
||||
{
|
||||
outputs = { ... }: {
|
||||
hello = "Claire";
|
||||
};
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// let flakeref_a = FlakeRefBuilder::new(format!("path:{}", &flake_dir_a_str))
|
||||
// .build()
|
||||
// .unwrap();
|
||||
let mut flake_lock_flags = FlakeLockFlags::new(&flake_settings).unwrap();
|
||||
|
||||
// assert_eq!(flakeref_a.fragment(), "");
|
||||
let mut flake_reference_parse_flags = FlakeRefParseFlags::new(&flake_settings).unwrap();
|
||||
|
||||
// // Step 1: Do not update (check), fails
|
||||
// let mut flake_lock_flags = FlakeLockFlags::new(LockMode::Check);
|
||||
flake_reference_parse_flags
|
||||
.set_base_directory(tmp_dir.path().to_str().unwrap())
|
||||
.unwrap();
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state);
|
||||
// // Has not been locked and would need to write a lock file.
|
||||
// assert!(locked_flake.is_err());
|
||||
// let saved_err = match locked_flake {
|
||||
// Ok(_) => panic!("Expected error, but got Ok"),
|
||||
// Err(e) => e,
|
||||
// };
|
||||
let flakeref_a = FlakeRef::parse(&format!("path:{}", &flake_dir_a_str)).unwrap();
|
||||
|
||||
// // Step 2: Update but do not write, succeeds
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::Virtual);
|
||||
assert_eq!(flakeref_a.fragment(), "");
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
// Step 1: Do not update (check), fails
|
||||
flake_lock_flags.set_mode(FlakeLockMode::Check).unwrap();
|
||||
|
||||
// let outputs = locked_flake.outputs().unwrap();
|
||||
let locked_flake = LockedFlake::lock(FlakeLockMode::Check, flakeref_a, &eval_state);
|
||||
// Has not been locked and would need to write a lock file.
|
||||
assert!(locked_flake.is_err());
|
||||
let saved_err = match locked_flake {
|
||||
Ok(_) => panic!("Expected error, but got Ok"),
|
||||
Err(e) => e,
|
||||
};
|
||||
|
||||
// assert!(matches!(outputs, Value::Attrs(_)));
|
||||
// if let Value::Attrs(outputs) = outputs {
|
||||
// let value = outputs.get("hello").unwrap();
|
||||
// Step 2: Update but do not write, succeeds
|
||||
flake_lock_flags.set_mode(FlakeLockMode::Virtual).unwrap();
|
||||
|
||||
// assert!(matches!(value, Value::String(_)));
|
||||
// if let Value::String(value) = value {
|
||||
// assert_eq!(value.as_string(), "ALICE");
|
||||
// }
|
||||
// }
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
|
||||
// // Step 3: The lock was not written, so Step 1 would fail again
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::Check);
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state);
|
||||
// // 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());
|
||||
// },
|
||||
// };
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
// // Step 4: Update and write, succeeds
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::WriteAsNeeded);
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
// Step 3: The lock was not written, so Step 1 would fail again
|
||||
flake_lock_flags.set_mode(FlakeLockMode::Check).unwrap();
|
||||
|
||||
// let outputs = locked_flake.outputs().unwrap();
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state);
|
||||
// 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());
|
||||
},
|
||||
};
|
||||
|
||||
// assert!(matches!(outputs, Value::Attrs(_)));
|
||||
// if let Value::Attrs(outputs) = outputs {
|
||||
// let value = outputs.get("hello").unwrap();
|
||||
// Step 4: Update and write, succeeds
|
||||
flake_lock_flags
|
||||
.set_mode(FlakeLockMode::WriteAsNeeded)
|
||||
.unwrap();
|
||||
|
||||
// assert!(matches!(value, Value::String(_)));
|
||||
// if let Value::String(value) = value {
|
||||
// assert_eq!(value.as_string(), "ALICE");
|
||||
// }
|
||||
// }
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
|
||||
// // Step 5: Lock was written, so Step 1 succeeds
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::Check);
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
// let outputs = locked_flake.outputs().unwrap();
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
flake_lock_flags.set_mode(FlakeLockMode::Check).unwrap();
|
||||
|
||||
// assert!(matches!(value, Value::String(_)));
|
||||
// if let Value::String(value) = value {
|
||||
// assert_eq!(value.as_string(), "ALICE");
|
||||
// }
|
||||
// }
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
|
||||
// // Step 6: Lock with override, do not write
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
// // This shouldn't matter; write_as_needed will be overridden
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::WriteAsNeeded);
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
// let flakeref_c = FlakeRefBuilder::new(format!("path:{}", &flake_dir_c_str))
|
||||
// .build()
|
||||
// .unwrap();
|
||||
// assert_eq!(flakeref_c.fragment(), "");
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "ALICE");
|
||||
}
|
||||
}
|
||||
|
||||
// flake_lock_flags.override_input("b", &flakeref_c).unwrap();
|
||||
// Step 6: Lock with override, do not write
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
// This shouldn't matter; write_as_needed will be overridden
|
||||
flake_lock_flags
|
||||
.set_mode(FlakeLockMode::WriteAsNeeded)
|
||||
.unwrap();
|
||||
|
||||
// let outputs = locked_flake.outputs().unwrap();
|
||||
let flakeref_c = FlakeRef::parse(&format!("path:{}", &flake_dir_c_str)).unwrap();
|
||||
assert_eq!(flakeref_c.fragment(), "");
|
||||
|
||||
// assert!(matches!(outputs, Value::Attrs(_)));
|
||||
// if let Value::Attrs(outputs) = outputs {
|
||||
// let value = outputs.get("hello").unwrap();
|
||||
flake_lock_flags.override_input("b", &flakeref_c).unwrap();
|
||||
|
||||
// assert!(matches!(value, Value::String(_)));
|
||||
// if let Value::String(value) = value {
|
||||
// assert_eq!(value.as_string(), "Claire");
|
||||
// }
|
||||
// }
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
|
||||
// // Step 7: Override was not written; lock still points to b
|
||||
// let flake_lock_flags = FlakeLockFlags::new(LockMode::Check);
|
||||
let outputs = locked_flake.outputs().unwrap();
|
||||
|
||||
// let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).unwrap();
|
||||
assert!(matches!(outputs, Value::Attrs(_)));
|
||||
if let Value::Attrs(outputs) = outputs {
|
||||
let value = outputs.get("hello").unwrap();
|
||||
|
||||
// let outputs = locked_flake.outputs().unwrap();
|
||||
assert!(matches!(value, Value::String(_)));
|
||||
if let Value::String(value) = value {
|
||||
assert_eq!(value.as_string(), "Claire");
|
||||
}
|
||||
}
|
||||
|
||||
// assert!(matches!(outputs, Value::Attrs(_)));
|
||||
// if let Value::Attrs(outputs) = outputs {
|
||||
// let value = outputs.get("hello").unwrap();
|
||||
// Can't delete overrides, so trash it
|
||||
let mut flake_lock_flags = FlakeLockFlags::new(&flake_settings).unwrap();
|
||||
|
||||
// assert!(matches!(value, Value::String(_)));
|
||||
// if let Value::String(value) = value {
|
||||
// assert_eq!(value.as_string(), "ALICE");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// Step 7: Override was not written; lock still points to b
|
||||
flake_lock_flags.set_mode(FlakeLockMode::Check).unwrap();
|
||||
|
||||
let locked_flake = LockedFlake::lock(flake_lock_flags, flakeref_a, &eval_state).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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ mod fetchers_settings;
|
|||
mod flake_lock_flags;
|
||||
mod flake_settings;
|
||||
mod flakeref;
|
||||
mod flakeref_builder;
|
||||
mod flakeref_parse_flags;
|
||||
mod locked_flake;
|
||||
|
||||
pub use fetchers_settings::FetchersSettings;
|
||||
pub use flake_lock_flags::{FlakeLockFlags, LockMode};
|
||||
use fetchers_settings::FetchersSettings;
|
||||
use flake_lock_flags::{FlakeLockFlags, FlakeLockMode};
|
||||
pub use flake_settings::FlakeSettings;
|
||||
pub use flakeref::FlakeRef;
|
||||
pub use flakeref_builder::FlakeRefBuilder;
|
||||
pub use flakeref_parse_flags::FlakeRefParseFlags;
|
||||
use flakeref::FlakeRef;
|
||||
use flakeref_parse_flags::FlakeRefParseFlags;
|
||||
pub use locked_flake::LockedFlake;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,6 @@ pub use version::NixVersion;
|
|||
#[cfg(feature = "exprs")]
|
||||
pub use expr::{EvalState, EvalStateBuilder, Value};
|
||||
#[cfg(feature = "flakes")]
|
||||
pub use flake::{FlakeRef, FlakeRefBuilder, FlakeSettings, LockedFlake};
|
||||
pub use flake::{FlakeSettings, LockedFlake};
|
||||
#[cfg(feature = "store")]
|
||||
pub use store::{Store, StorePath};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use std::ffi::CString;
|
||||
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr as _;
|
||||
|
|
@ -70,10 +69,8 @@ impl ToString for LogFormat {
|
|||
/// modified without nixide updating to account for this.
|
||||
///
|
||||
pub fn set_log_format(format: LogFormat) {
|
||||
let c_format = CString::new(format.to_string()).to_nixide_result().unwrap();
|
||||
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_set_log_format(ctx.as_ptr(), c_format.as_ptr());
|
||||
sys::nix_set_log_format(ctx.as_ptr(), format.to_string().as_c_ptr().unwrap());
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,21 @@
|
|||
use std::ffi::{CString, c_void};
|
||||
use std::ffi::c_void;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr as _;
|
||||
|
||||
// DEBUG: should this really be unsafe?
|
||||
/// # Note
|
||||
/// This function is intentionally marked unsafe to discourage its use.
|
||||
/// Please prefer [nixide::FlakeSettings] and [nixide::FetchersSettings].
|
||||
///
|
||||
pub unsafe fn get_global_setting(key: &str) -> NixideResult<String> {
|
||||
let c_key = CString::new(key).to_nixide_result()?;
|
||||
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(),
|
||||
c_key.as_ptr(),
|
||||
Some(callback),
|
||||
userdata as *mut c_void,
|
||||
);
|
||||
sys::nix_setting_get(ctx.as_ptr(), key, Some(callback), userdata as *mut c_void);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -29,11 +24,14 @@ pub unsafe fn get_global_setting(key: &str) -> NixideResult<String> {
|
|||
/// This function is intentionally marked unsafe to discourage its use.
|
||||
/// Please prefer [nixide::FlakeSettings] and [nixide::FetchersSettings].
|
||||
///
|
||||
pub unsafe fn set_global_setting(key: &str, value: &str) -> NixideResult<()> {
|
||||
let c_key = CString::new(key).to_nixide_result()?;
|
||||
let c_value = CString::new(value).to_nixide_result()?;
|
||||
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(), c_key.as_ptr(), c_value.as_ptr());
|
||||
sys::nix_setting_set(ctx.as_ptr(), key, value);
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::ffi::CString;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr as _;
|
||||
|
||||
|
|
@ -12,8 +11,8 @@ pub fn load_plugins() -> NixideResult<()> {
|
|||
}
|
||||
|
||||
pub fn register_plugin<S: AsRef<str>>(path: S) -> NixideResult<()> {
|
||||
let c_path = CString::new(path.as_ref()).to_nixide_result()?;
|
||||
let path_ptr = path.as_ref().into_c_ptr()?;
|
||||
wrap::nix_fn!(|ctx: &ErrorContext| unsafe {
|
||||
sys::nix_register_plugin(ctx.as_ptr(), c_path.as_ptr().cast_mut());
|
||||
sys::nix_register_plugin(ctx.as_ptr(), path_ptr);
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,33 @@ use std::str::from_utf8;
|
|||
use crate::NixideResult;
|
||||
use crate::errors::new_nixide_error;
|
||||
|
||||
pub trait AsCPtr<T> {
|
||||
#[allow(unused)]
|
||||
fn as_c_ptr(&self) -> NixideResult<*const T>;
|
||||
|
||||
#[allow(unused)]
|
||||
fn into_c_ptr(self) -> NixideResult<*mut T>;
|
||||
}
|
||||
|
||||
impl<T> AsCPtr<c_char> for T
|
||||
where
|
||||
T: AsRef<str>,
|
||||
{
|
||||
fn as_c_ptr(&self) -> NixideResult<*const c_char> {
|
||||
match CStr::from_bytes_until_nul(self.as_ref().as_bytes()) {
|
||||
Ok(s) => Ok(s.as_ptr()),
|
||||
Err(_) => Err(new_nixide_error!(StringNulByte)),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_c_ptr(self) -> NixideResult<*mut c_char> {
|
||||
match CStr::from_bytes_until_nul(self.as_ref().as_bytes()) {
|
||||
Ok(s) => Ok(s.as_ptr().cast_mut()),
|
||||
Err(_) => Err(new_nixide_error!(StringNulByte)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CCharPtrExt {
|
||||
#[allow(unused)]
|
||||
fn to_utf8_string(self) -> NixideResult<String>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
mod cchar_ptr;
|
||||
mod slice;
|
||||
|
||||
pub(crate) use cchar_ptr::CCharPtrExt;
|
||||
pub(crate) use cchar_ptr::{AsCPtr, CCharPtrExt};
|
||||
pub(crate) use slice::SliceExt;
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@ mod path;
|
|||
pub use path::*;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::ffi::{CString, c_char, c_void};
|
||||
use std::ffi::{c_char, c_void};
|
||||
use std::path::PathBuf;
|
||||
use std::ptr::{NonNull, null, null_mut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::NixideResult;
|
||||
use crate::errors::{ErrorContext, ToNixideResult as _};
|
||||
use crate::errors::ErrorContext;
|
||||
use crate::stdext::AsCPtr as _;
|
||||
use crate::sys;
|
||||
use crate::util::wrap;
|
||||
use crate::util::wrappers::AsInnerPtr;
|
||||
|
|
@ -57,8 +58,7 @@ impl Store {
|
|||
/// Returns an error if the store cannot be opened.
|
||||
///
|
||||
pub fn open(uri: &str) -> NixideResult<Rc<RefCell<Self>>> {
|
||||
let c_uri = CString::new(uri).to_nixide_result()?;
|
||||
unsafe { Self::open_ptr(c_uri.as_ptr()) }
|
||||
unsafe { Self::open_ptr(uri.as_c_ptr()?) }
|
||||
}
|
||||
|
||||
/// Opens a connection to the default Nix store.
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ impl StorePath {
|
|||
/// use nixide::{Store, StorePath};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let storeref = Store::default().unwrap();
|
||||
/// let path = StorePath::new(storeref, "/nix/store/f7gmvzd74wc1vlxzjdqy0af2381g8wr6-nix-manual-2.31.2-man").unwrap();
|
||||
/// let store_ref = Store::default().unwrap();
|
||||
/// let path = StorePath::new("/nix/store/f7gmvzd74wc1vlxzjdqy0af2381g8wr6-nix-manual-2.31.2-man").unwrap();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue