difftreelog
build enable gc debugging
in: trunk
9 files changed
Cargo.lockdiffbeforeafterboth125 "memchr",125 "memchr",126]126]127128[[package]]129name = "alejandra"130version = "4.0.0"131source = "git+https://github.com/kamadorueda/alejandra#c68bef57c1db3add865493d9cb741a14618bdc28"132dependencies = [133 "mimalloc",134 "rnix",135 "rowan",136 "serde",137]138127139[[package]]128[[package]]140name = "android-tzdata"129name = "android-tzdata"674source = "registry+https://github.com/rust-lang/crates.io-index"663source = "registry+https://github.com/rust-lang/crates.io-index"675checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"664checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"676677[[package]]678name = "countme"679version = "3.0.1"680source = "registry+https://github.com/rust-lang/crates.io-index"681checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"682665683[[package]]666[[package]]684name = "cpufeatures"667name = "cpufeatures"1353source = "registry+https://github.com/rust-lang/crates.io-index"1336source = "registry+https://github.com/rust-lang/crates.io-index"1354checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"1337checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"13551356[[package]]1357name = "hashbrown"1358version = "0.14.5"1359source = "registry+https://github.com/rust-lang/crates.io-index"1360checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"136113381362[[package]]1339[[package]]1363name = "hashbrown"1340name = "hashbrown"1794source = "registry+https://github.com/rust-lang/crates.io-index"1771source = "registry+https://github.com/rust-lang/crates.io-index"1795checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"1772checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"17961797[[package]]1798name = "libmimalloc-sys"1799version = "0.1.44"1800source = "registry+https://github.com/rust-lang/crates.io-index"1801checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870"1802dependencies = [1803 "cc",1804 "libc",1805]180617731807[[package]]1774[[package]]1808name = "link-cplusplus"1775name = "link-cplusplus"1874source = "registry+https://github.com/rust-lang/crates.io-index"1841source = "registry+https://github.com/rust-lang/crates.io-index"1875checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"1842checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"18761877[[package]]1878name = "memoffset"1879version = "0.9.1"1880source = "registry+https://github.com/rust-lang/crates.io-index"1881checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"1882dependencies = [1883 "autocfg",1884]18851886[[package]]1887name = "mimalloc"1888version = "0.1.48"1889source = "registry+https://github.com/rust-lang/crates.io-index"1890checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8"1891dependencies = [1892 "libmimalloc-sys",1893]189418431895[[package]]1844[[package]]1896name = "mime"1845name = "mime"1969name = "nixlike"1918name = "nixlike"1970version = "0.1.0"1919version = "0.1.0"1971dependencies = [1920dependencies = [1972 "alejandra",1973 "linked-hash-map",1921 "linked-hash-map",1974 "peg",1922 "peg",1975 "ron",1923 "ron",2571 "serde",2519 "serde",2572]2520]25732574[[package]]2575name = "rnix"2576version = "0.12.0"2577source = "registry+https://github.com/rust-lang/crates.io-index"2578checksum = "6f15e00b0ab43abd70d50b6f8cd021290028f9b7fdd7cdfa6c35997173bc1ba9"2579dependencies = [2580 "rowan",2581]258225212583[[package]]2522[[package]]2584name = "ron"2523name = "ron"2593 "unicode-ident",2532 "unicode-ident",2594]2533]25952596[[package]]2597name = "rowan"2598version = "0.15.17"2599source = "registry+https://github.com/rust-lang/crates.io-index"2600checksum = "d4f1e4a001f863f41ea8d0e6a0c34b356d5b733db50dadab3efef640bafb779b"2601dependencies = [2602 "countme",2603 "hashbrown 0.14.5",2604 "memoffset",2605 "rustc-hash 1.1.0",2606 "text-size",2607]260825342609[[package]]2535[[package]]2610name = "rsa"2536name = "rsa"3156 "unicode-width 0.2.1",3082 "unicode-width 0.2.1",3157]3083]31583159[[package]]3160name = "text-size"3161version = "1.1.1"3162source = "registry+https://github.com/rust-lang/crates.io-index"3163checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"316430843165[[package]]3085[[package]]3166name = "tf-provider"3086name = "tf-provider"cmds/fleet/src/main.rsdiffbeforeafterboth27use tracing::{Instrument, error, info, info_span};27use tracing::{Instrument, error, info, info_span};28#[cfg(feature = "indicatif")]28#[cfg(feature = "indicatif")]29use tracing_indicatif::IndicatifLayer;29use tracing_indicatif::IndicatifLayer;30use tracing_subscriber::{EnvFilter, prelude::*};30use tracing_subscriber::{fmt::format::Format, prelude::*, EnvFilter};313132#[derive(Parser)]32#[derive(Parser)]33struct Prefetch {}33struct Prefetch {}crates/fleet-base/src/opts.rsdiffbeforeafterboth9use anyhow::{Context, Result, bail};9use anyhow::{Context, Result, bail};10use nix_eval::{10use nix_eval::{11 FetchSettings, FlakeLockFlags, FlakeReference, FlakeReferenceParseFlags, FlakeSettings, Value,11 FetchSettings, FlakeLockFlags, FlakeReference, FlakeReferenceParseFlags, FlakeSettings, Value,12 nix_go, util::assert_warn,12 gc_now, nix_go, util::assert_warn,13};13};14use nom::{14use nom::{15 Parser,15 Parser,260 system: self.local_system.clone(),260 system: self.local_system.clone(),261 }));261 }));262263 if cfg!(debug_assertions) {264 gc_now();265 }262266263 Ok(Config(Arc::new(FleetConfigInternals {267 Ok(Config(Arc::new(FleetConfigInternals {264 directory,268 directory,crates/nix-eval/src/lib.rsdiffbeforeafterboth1use std::alloc::{GlobalAlloc, Layout};1use std::borrow::Cow;2use std::borrow::Cow;2use std::cell::RefCell;3use std::cell::RefCell;3use std::ffi::{CStr, CString, c_char, c_int, c_uint, c_void};4use std::ffi::{CStr, CString, c_char, c_int, c_uint, c_void};4use std::fmt;5use std::mem::forget;5use std::ptr::null_mut;6use std::ptr::null_mut;6use std::sync::LazyLock;7use std::sync::LazyLock;7use std::{collections::HashMap, path::PathBuf};8use std::{collections::HashMap, path::PathBuf};9use std::{fmt, slice};8109use anyhow::{Context, anyhow, bail};11use anyhow::{Context, anyhow, bail};10use serde::Serialize;12use serde::Serialize;11use serde::de::DeserializeOwned;13use serde::de::DeserializeOwned;121413pub use anyhow::Result;15pub use anyhow::Result;14use tracing::instrument;16use tracing::{info, instrument};151716use self::logging::nix_logging_cxx;18use self::logging::nix_logging_cxx;17use self::nix_cxx::set_fetcher_setting;19use self::nix_cxx::set_fetcher_setting;18use self::nix_raw::{20use self::nix_raw::{21 BindingsBuilder as c_bindings_builder, EvalState as c_eval_state, GC_SUCCESS,22 GC_allow_register_threads, GC_free, GC_get_stack_base, GC_init, GC_malloc, GC_realloc,23 GC_register_my_thread, GC_stack_base, GC_thread_is_registered, GC_unregister_my_thread,19 alloc_value, c_context, c_context_create, err_code, err_info_msg, eval_state_build,24 Store as c_store, alloc_value, bindings_builder_free, bindings_builder_insert, c_context,25 c_context_create, c_context_free, clear_err, err_code, err_info_msg, err_msg, eval_state_build,20 eval_state_builder_new, expr_eval_from_string, fetchers_settings, fetchers_settings_free,26 eval_state_builder_load, eval_state_builder_new, eval_state_builder_set_eval_setting,21 fetchers_settings_new, flake_lock, flake_lock_flags, flake_lock_flags_free,27 expr_eval_from_string, fetchers_settings, fetchers_settings_free, fetchers_settings_new,22 flake_lock_flags_new, flake_reference_parse_flags, flake_reference_parse_flags_free,28 flake_lock, flake_lock_flags, flake_lock_flags_free, flake_lock_flags_new, flake_reference,29 flake_reference_and_fragment_from_string, flake_reference_parse_flags,23 flake_reference_parse_flags_new, flake_reference_parse_flags_set_base_directory,30 flake_reference_parse_flags_free, flake_reference_parse_flags_new,24 flake_settings, flake_settings_free, flake_settings_new, get_string, init_bool, init_int,31 flake_reference_parse_flags_set_base_directory, flake_settings, flake_settings_free,32 flake_settings_new, get_attr_byname, get_attr_name_byidx, get_attrs_size, get_list_byidx,25 init_string, locked_flake_free, locked_flake_get_output_attrs, set_err_msg, setting_set,33 get_list_size, get_string, get_type, has_attr_byname, init_bool, init_int, init_string,34 libexpr_init, libstore_init, libutil_init, locked_flake, locked_flake_free,35 locked_flake_get_output_attrs, make_attrs, make_bindings_builder, realised_string,36 realised_string_free, realised_string_get_buffer_size, realised_string_get_buffer_start,37 realised_string_get_store_path, realised_string_get_store_path_count, set_err_msg, setting_set,26 state_free, value_decref, value_incref,38 state_free, store_open, store_path_name, string_realise, value, value_call, value_decref,39 value_incref,27};40};2841117 }130 }118}131}132133pub fn gc_now() {134 unsafe { nix_raw::gc_now() };135}119136120pub fn gc_register_my_thread() {137pub fn gc_register_my_thread() {121 assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 0);138 assert_eq!(unsafe { GC_thread_is_registered() }, 0);122139123 let mut sb = nix_raw::GC_stack_base {140 let mut sb = GC_stack_base {124 mem_base: null_mut(),141 mem_base: null_mut(),125 };142 };126 let r = unsafe { nix_raw::GC_get_stack_base(&mut sb) };143 let r = unsafe { GC_get_stack_base(&mut sb) };127 if r as u32 != nix_raw::GC_SUCCESS {144 if r as u32 != GC_SUCCESS {128 panic!("failed to get thread stack base");145 panic!("failed to get thread stack base");129 }146 }130 unsafe { nix_raw::GC_register_my_thread(&sb) };147 unsafe { GC_register_my_thread(&sb) };131}148}132pub fn gc_unregister_my_thread() {149pub fn gc_unregister_my_thread() {133 assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 1);150 assert_eq!(unsafe { GC_thread_is_registered() }, 1);134151135 unsafe { nix_raw::GC_unregister_my_thread() };152 unsafe { GC_unregister_my_thread() };136}153}137154138pub struct ThreadRegisterGuard {}155pub struct ThreadRegisterGuard {}178195179 // TODO: Can throw error (resulting in panic) if unable to retrieve error. Should be able to resolve by passing context as a first argument,196 // TODO: Can throw error (resulting in panic) if unable to retrieve error. Should be able to resolve by passing context as a first argument,180 // but it looks ugly197 // but it looks ugly181 let str = unsafe { nix_raw::err_msg(null_mut(), self.0, null_mut()) };198 let str = unsafe { err_msg(null_mut(), self.0, null_mut()) };182 Some(unsafe { CStr::from_ptr(str) }.to_string_lossy())199 Some(unsafe { CStr::from_ptr(str) }.to_string_lossy())183 }200 }184 fn clean_err(&mut self) {201 fn clean_err(&mut self) {185 unsafe {202 unsafe {186 nix_raw::clear_err(self.0);203 clear_err(self.0);187 }204 }188 }205 }189206211impl Drop for NixContext {228impl Drop for NixContext {212 fn drop(&mut self) {229 fn drop(&mut self) {213 unsafe {230 unsafe {214 nix_raw::c_context_free(self.0);231 c_context_free(self.0);215 }232 }216 }233 }217}234}225 fn new() -> Result<Self> {242 fn new() -> Result<Self> {226 let mut ctx = NixContext::new();243 let mut ctx = NixContext::new();227 let store = ctx244 let store = ctx228 .run_in_context(|c| unsafe { nix_raw::store_open(c, c"auto".as_ptr(), null_mut()) })245 .run_in_context(|c| unsafe { store_open(c, c"auto".as_ptr(), null_mut()) })229 .map(Store)?;246 .map(Store)?;230247231 let builder = ctx.run_in_context(|c| unsafe { eval_state_builder_new(c, store.0) })?;248 let builder = ctx.run_in_context(|c| unsafe { eval_state_builder_new(c, store.0) })?;232 ctx.run_in_context(|c| {249 ctx.run_in_context(|c| unsafe { eval_state_builder_load(c, builder) })?;233 unsafe { nix_raw::eval_state_builder_load(c, builder) }234 // eval_s235 })?;236 ctx.run_in_context(|c| {250 ctx.run_in_context(|c| unsafe {237 unsafe {238 nix_raw::eval_state_builder_set_eval_setting(251 eval_state_builder_set_eval_setting(239 c,252 c,240 builder,253 builder,241 c"lazy-trees".as_ptr(),254 c"lazy-trees".as_ptr(),242 c"true".as_ptr(),255 c"true".as_ptr(),243 )256 )244 }257 })?;245 // eval_s246 })?;247 ctx.run_in_context(|c| {258 ctx.run_in_context(|c| unsafe {248 unsafe {249 nix_raw::eval_state_builder_set_eval_setting(259 eval_state_builder_set_eval_setting(250 c,260 c,251 builder,261 builder,252 c"lazy-locks".as_ptr(),262 c"lazy-locks".as_ptr(),253 c"true".as_ptr(),263 c"true".as_ptr(),254 )264 )255 }265 })?;256 // eval_s257 })?;258 let state = ctx266 let state = ctx259 .run_in_context(|c| unsafe { eval_state_build(c, builder) })267 .run_in_context(|c| unsafe { eval_state_build(c, builder) })260 .map(EvalState)?;268 .map(EvalState)?;280thread_local! {288thread_local! {281 static THREAD_STATE: RefCell<ThreadState> = RefCell::new(ThreadState::new().expect("thread state init shouldn't fail"));289 static THREAD_STATE: RefCell<ThreadState> = RefCell::new(ThreadState::new().expect("thread state init shouldn't fail"));282}290}283fn with_default_context<T>(291fn with_default_context<T>(f: impl FnOnce(*mut c_context, *mut c_eval_state) -> T) -> Result<T> {284 f: impl FnOnce(*mut c_context, *mut nix_raw::EvalState) -> T,285) -> Result<T> {286 let global = &GLOBAL_STATE.state;292 let global = &GLOBAL_STATE.state;287 let (ctx, state) = THREAD_STATE.with_borrow_mut(|w| (w.ctx.0, global.0));293 let (ctx, state) = THREAD_STATE.with_borrow_mut(|w| (w.ctx.0, global.0));385}391}386392387unsafe extern "C" fn copy_nix_str(start: *const c_char, n: c_uint, user_data: *mut c_void) {393unsafe extern "C" fn copy_nix_str(start: *const c_char, n: c_uint, user_data: *mut c_void) {388 let s = unsafe { std::slice::from_raw_parts(start.cast::<u8>(), n as usize) };394 let s = unsafe { slice::from_raw_parts(start.cast::<u8>(), n as usize) };389 let s = std::str::from_utf8(s).expect("c string has invalid utf-8");395 let s = std::str::from_utf8(s).expect("c string has invalid utf-8");390 unsafe { *user_data.cast::<String>() = s.to_owned() };396 unsafe { *user_data.cast::<String>() = s.to_owned() };391}397}392398393struct Store(*mut nix_raw::Store);399struct Store(*mut c_store);394unsafe impl Send for Store {}400unsafe impl Send for Store {}395unsafe impl Sync for Store {}401unsafe impl Sync for Store {}396402397struct EvalState(*mut nix_raw::EvalState);403struct EvalState(*mut c_eval_state);398unsafe impl Send for EvalState {}404unsafe impl Send for EvalState {}399unsafe impl Sync for EvalState {}405unsafe impl Sync for EvalState {}400406406 }412 }407}413}408414409pub struct FlakeReference(*mut nix_raw::flake_reference);415pub struct FlakeReference(*mut flake_reference);410impl FlakeReference {416impl FlakeReference {411 #[instrument(name = "new-flake-reference", skip(flake, parse, fetch))]417 #[instrument(name = "new-flake-reference", skip(flake, parse, fetch))]412 pub fn new(418 pub fn new(419 let mut fragment = String::new();425 let mut fragment = String::new();420 // let fetch_settings = fetcher_settings;426 // let fetch_settings = fetcher_settings;421 with_default_context(|c, _| unsafe {427 with_default_context(|c, _| unsafe {422 nix_raw::flake_reference_and_fragment_from_string(428 flake_reference_and_fragment_from_string(423 c,429 c,424 fetch.0,430 fetch.0,425 flake.0,431 flake.0,449unsafe impl Send for FlakeReference {}455unsafe impl Send for FlakeReference {}450unsafe impl Sync for FlakeReference {}456unsafe impl Sync for FlakeReference {}451457452pub struct LockedFlake(*mut nix_raw::locked_flake);458pub struct LockedFlake(*mut locked_flake);453impl LockedFlake {459impl LockedFlake {454 pub fn get_attrs(&self, settings: &mut FlakeSettings) -> Result<Value> {460 pub fn get_attrs(&self, settings: &mut FlakeSettings) -> Result<Value> {455 with_default_context(|c, es| unsafe {461 with_default_context(|c, es| unsafe {480 f486 f481}487}482488483pub struct RealisedString(*mut nix_raw::realised_string);489pub struct RealisedString(*mut realised_string);484impl fmt::Debug for RealisedString {490impl fmt::Debug for RealisedString {485 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {491 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {486 self.as_str().fmt(f)492 self.as_str().fmt(f)489495490impl RealisedString {496impl RealisedString {491 pub fn as_str(&self) -> &str {497 pub fn as_str(&self) -> &str {492 let len = unsafe { nix_raw::realised_string_get_buffer_size(self.0) };498 let len = unsafe { realised_string_get_buffer_size(self.0) };493 let data: *const u8 = unsafe { nix_raw::realised_string_get_buffer_start(self.0) }.cast();499 let data: *const u8 = unsafe { realised_string_get_buffer_start(self.0) }.cast();494 let data = unsafe { std::slice::from_raw_parts(data, len) };500 let data = unsafe { slice::from_raw_parts(data, len) };495 std::str::from_utf8(data).expect("non-utf8 strings not supported")501 std::str::from_utf8(data).expect("non-utf8 strings not supported")496 }502 }497 pub fn path_count(&self) -> usize {503 pub fn path_count(&self) -> usize {498 unsafe { nix_raw::realised_string_get_store_path_count(self.0) }504 unsafe { realised_string_get_store_path_count(self.0) }499 }505 }500 pub fn path(&self, i: usize) -> String {506 pub fn path(&self, i: usize) -> String {501 assert!(i < self.path_count());507 assert!(i < self.path_count());502 let path = unsafe { nix_raw::realised_string_get_store_path(self.0, i) };508 let path = unsafe { realised_string_get_store_path(self.0, i) };503 let mut err_out = String::new();509 let mut err_out = String::new();504 unsafe { nix_raw::store_path_name(path, Some(copy_nix_str), (&raw mut err_out).cast()) };510 unsafe { store_path_name(path, Some(copy_nix_str), (&raw mut err_out).cast()) };505 err_out511 err_out506 }512 }507}513}508514509unsafe impl Send for RealisedString {}515unsafe impl Send for RealisedString {}510impl Drop for RealisedString {516impl Drop for RealisedString {511 fn drop(&mut self) {517 fn drop(&mut self) {512 unsafe { nix_raw::realised_string_free(self.0) }518 unsafe { realised_string_free(self.0) }513 }519 }514}520}515521516pub struct Value(*mut nix_raw::value);522pub struct Value(*mut value);517523518unsafe impl Send for Value {}524unsafe impl Send for Value {}519unsafe impl Sync for Value {}525unsafe impl Sync for Value {}544 }550 }545}551}546552547struct AttrsBuilder(*mut nix_raw::BindingsBuilder);553struct AttrsBuilder(*mut c_bindings_builder);548impl AttrsBuilder {554impl AttrsBuilder {549 fn new(capacity: usize) -> Self {555 fn new(capacity: usize) -> Self {550 with_default_context(|c, es| unsafe { nix_raw::make_bindings_builder(c, es, capacity) })556 with_default_context(|c, es| unsafe { make_bindings_builder(c, es, capacity) })551 .map(Self)557 .map(Self)552 .expect("alloc should not fail")558 .expect("alloc should not fail")553 }559 }554 fn insert(&mut self, k: &impl AsFieldName, v: Value) {560 fn insert(&mut self, k: &impl AsFieldName, v: Value) {555 k.as_field_name(|name| {561 k.as_field_name(|name| {556 with_default_context(|c, _| unsafe {562 with_default_context(|c, _| unsafe {557 nix_raw::bindings_builder_insert(c, self.0, name.as_ptr().cast(), v.0)563 bindings_builder_insert(c, self.0, name.as_ptr().cast(), v.0);564 // bindings_builder_insert doesn't do incref558 })565 })559 })566 })560 .expect("builder insert shouldn't fail");567 .expect("builder insert shouldn't fail");561 }568 }562}569}563impl Drop for AttrsBuilder {570impl Drop for AttrsBuilder {564 fn drop(&mut self) {571 fn drop(&mut self) {565 unsafe { nix_raw::bindings_builder_free(self.0) };572 unsafe { bindings_builder_free(self.0) };566 }573 }567}574}568575573 for (k, v) in v {580 for (k, v) in v {574 b.insert(&k, v);581 b.insert(&k, v);575 }582 }576 with_default_context(|c, _| unsafe { nix_raw::make_attrs(c, out.0, b.0) })583 with_default_context(|c, _| unsafe { make_attrs(c, out.0, b.0) })577 .expect("attrs initialization should not fail");584 .expect("attrs initialization should not fail");585578 out586 out611 // Ok(())619 // Ok(())612 // }620 // }613 pub fn type_of(&self) -> NixType {621 pub fn type_of(&self) -> NixType {614 let ty = with_default_context(|c, _| unsafe { nix_raw::get_type(c, self.0) })622 let ty = with_default_context(|c, _| unsafe { get_type(c, self.0) })615 .expect("get_type should not fail");623 .expect("get_type should not fail");616 NixType::from_int(ty)624 NixType::from_int(ty)617 }625 }628 Ok(str_out)636 Ok(str_out)629 }637 }630 pub fn to_realised_string(&self) -> Result<RealisedString> {638 pub fn to_realised_string(&self) -> Result<RealisedString> {631 with_default_context(|c, es| unsafe { nix_raw::string_realise(c, es, self.0, false) })639 with_default_context(|c, es| unsafe { string_realise(c, es, self.0, false) })632 .map(RealisedString)640 .map(RealisedString)633641634 // let store_paths = unsafe { nix_raw::realised_string_get_store_path_count(str) };642 // let store_paths = unsafe { nix_raw::realised_string_get_store_path_count(str) };643 pub fn has_field(&self, field: &str) -> Result<bool> {651 pub fn has_field(&self, field: &str) -> Result<bool> {644 let f = init_field_name(field);652 let f = init_field_name(field);645 with_default_context(|c, es| unsafe {653 with_default_context(|c, es| unsafe { has_attr_byname(c, self.0, es, f.as_ptr().cast()) })646 nix_raw::has_attr_byname(c, self.0, es, f.as_ptr().cast())647 })648 }654 }649 // pub fn derivation_path(&self) {655 // pub fn derivation_path(&self) {654 bail!("invalid type: expected attrs");660 bail!("invalid type: expected attrs");655 }661 }656662657 let len = with_default_context(|c, _| unsafe { nix_raw::get_attrs_size(c, self.0) })?;663 let len = with_default_context(|c, _| unsafe { get_attrs_size(c, self.0) })?;658 let mut out = Vec::with_capacity(len as usize);664 let mut out = Vec::with_capacity(len as usize);659665660 for i in 0..len {666 for i in 0..len {661 let name = with_default_context(|c, es| unsafe {667 let name =662 nix_raw::get_attr_name_byidx(c, self.0, es, i)668 with_default_context(|c, es| unsafe { get_attr_name_byidx(c, self.0, es, i) })?;663 })?;664 let c = unsafe { CStr::from_ptr(name) };669 let c = unsafe { CStr::from_ptr(name) };665 out.push(c.to_str().expect("nix field names are utf-8").to_owned());670 out.push(c.to_str().expect("nix field names are utf-8").to_owned());671 bail!("invalid type: expected list");676 bail!("invalid type: expected list");672 }677 }673 let len =678 let len = with_default_context(|c, _| unsafe { get_list_size(c, self.0) })? as usize;674 with_default_context(|c, _| unsafe { nix_raw::get_list_size(c, self.0) })? as usize;675 if v >= len {679 if v >= len {676 bail!("oob list get: {v} >= {len}");680 bail!("oob list get: {v} >= {len}");677 }681 }678682679 with_default_context(|c, es| unsafe { nix_raw::get_list_byidx(c, self.0, es, v as u32) })683 with_default_context(|c, es| unsafe { get_list_byidx(c, self.0, es, v as u32) }).map(Self)680 .map(Self)681 }684 }682 pub fn attrs_update(self, other: Value) -> Result<Self> {685 pub fn attrs_update(self, other: Value) -> Result<Self> {710713711 name.as_field_name(|name| {714 name.as_field_name(|name| {712 with_default_context(|c, es| unsafe {715 with_default_context(|c, es| unsafe {713 nix_raw::get_attr_byname(c, self.0, es, name.as_ptr().cast())716 get_attr_byname(c, self.0, es, name.as_ptr().cast())714 })717 })715 .map(Self)718 .map(Self)716 })719 })736739737 let out = Value::new_uninit();740 let out = Value::new_uninit();738 with_default_context(|c, es| unsafe {741 with_default_context(|c, es| unsafe { value_call(c, es, function.0, v.0, out.0) })?;739 nix_raw::value_call(c, es, function.0, v.0, out.0)740 })?;741742742 Ok(out)743 Ok(out)745 let s = CString::new(v).expect("expression shouldn't have internal NULs");746 let s = CString::new(v).expect("expression shouldn't have internal NULs");746 let out = Self::new_uninit();747 let out = Self::new_uninit();747 with_default_context(|c, es| unsafe {748 with_default_context(|c, es| unsafe {748 expr_eval_from_string(c, es, s.as_ptr(), c"/homeless-shelter".as_ptr(), out.0)749 expr_eval_from_string(c, es, s.as_ptr(), c"/root".as_ptr(), out.0)749 })?;750 })?;750 Ok(out)751 Ok(out)751 }752 }764 self.clone()765 self.clone()765 };766 };766 // to_string here blocks until the path is built767 // to_string here blocks until the path is built767 let drv_path =768 tokio::task::spawn_blocking(move || v.builtin_to_string()?.to_realised_string())768 let s = v.builtin_to_string()?;769 let rs = s.to_realised_string()?;769 .await770 let drv_path = rs.as_str().to_owned();770 .expect("spawn should not fail")?;771 Ok(PathBuf::from(drv_path.as_str()))771 Ok(PathBuf::from(drv_path))772 }772 }773 pub fn as_json<T: DeserializeOwned>(&self) -> Result<T> {773 pub fn as_json<T: DeserializeOwned>(&self) -> Result<T> {774 let to_json = Self::eval("builtins.toJSON")?;774 let to_json = Self::eval("builtins.toJSON")?;848}848}849849850pub fn init_libraries() {850pub fn init_libraries() {851 unsafe { nix_raw::GC_allow_register_threads() };851 unsafe { GC_allow_register_threads() };852 unsafe {853 nix_raw::GC_init();854 };855852856 let mut ctx = NixContext::new();853 let mut ctx = NixContext::new();857 ctx.run_in_context(|c| unsafe { nix_raw::libutil_init(c) })854 ctx.run_in_context(|c| unsafe { libutil_init(c) })858 .expect("util init should not fail");855 .expect("util init should not fail");859 ctx.run_in_context(|c| unsafe { nix_raw::libstore_init(c) })856 ctx.run_in_context(|c| unsafe { libstore_init(c) })860 .expect("store init should not fail");857 .expect("store init should not fail");861 ctx.run_in_context(|c| unsafe { nix_raw::libexpr_init(c) })858 ctx.run_in_context(|c| unsafe { libexpr_init(c) })862 .expect("expr init should not fail");859 .expect("expr init should not fail");863860864 nix_logging_cxx::apply_tracing_logger();861 nix_logging_cxx::apply_tracing_logger();872 fetch_settings.set(c"warn-dirty", c"false");869 fetch_settings.set(c"warn-dirty", c"false");873870874 let manifest = format!("{}/../../", env!("CARGO_MANIFEST_DIR"));871 let manifest = format!("{}/../../", env!("CARGO_MANIFEST_DIR"));872 let flake = FlakeSettings::new()?;873 let parse = FlakeReferenceParseFlags::new(&flake)?;875 let (mut r, _) = FlakeReference::new(&manifest, &fetch_settings)?;874 let (mut r, _) = FlakeReference::new(&manifest, &flake, &parse, &fetch_settings)?;875 let lock = FlakeLockFlags::new(&flake)?;876 let locked = r.lock(&fetch_settings)?;876 let locked = r.lock(&fetch_settings, &flake, &lock)?;877 let attrs = locked.get_attrs(&mut FlakeSettings::new()?)?;877 let attrs = locked.get_attrs(&mut FlakeSettings::new()?)?;878878879 let builtins = Value::eval("builtins")?;879 let builtins = Value::eval("builtins")?;888 Ok(())888 Ok(())889}889}890891// pub struct GcAlloc;892// unsafe impl GlobalAlloc for GcAlloc {893// unsafe fn alloc(&self, l: Layout) -> *mut u8 {894// let ptr = unsafe { GC_malloc(l.size()) };895// ptr.cast()896// }897// unsafe fn dealloc(&self, ptr: *mut u8, _: Layout) {898// // unsafe { GC_free(ptr.cast()) };899// }900//901// unsafe fn realloc(&self, ptr: *mut u8, _: Layout, new_size: usize) -> *mut u8 {902// let ptr = unsafe { GC_realloc(ptr.cast(), new_size) };903// ptr.cast()904// }905// }906//907// #[global_allocator]908// static GC: GcAlloc = GcAlloc;890909crates/nix-eval/src/logging.rsdiffbeforeafterboth504 // Only plain colors are enabled, everything other might corrupt the output504 // Only plain colors are enabled, everything other might corrupt the output505 return;505 return;506 }506 }507 self.output.push_str("IDK\x1b[");507 self.output.push_str("\x1b[");508 for (i, par) in params.iter().enumerate() {508 for (i, par) in params.iter().enumerate() {509 if i != 0 {509 if i != 0 {510 let _ = write!(self.output, ";");510 let _ = write!(self.output, ";");crates/nixlike/Cargo.tomldiffbeforeafterboth7[dependencies]7[dependencies]8thiserror.workspace = true8thiserror.workspace = true9910alejandra = { git = "https://github.com/kamadorueda/alejandra" }11linked-hash-map = "0.5.6"10linked-hash-map = "0.5.6"12peg = "0.8.5"11peg = "0.8.5"13ron = "0.11.0"12ron = "0.11.0"crates/nixlike/src/lib.rsdiffbeforeafterboth5//! expressions and expect it to work, only basic primitives are supported, and there is no5//! expressions and expect it to work, only basic primitives are supported, and there is no6//! variables/recursive records, interpolation, e.t.c.6//! variables/recursive records, interpolation, e.t.c.778use alejandra::config::Indentation;9use linked_hash_map::LinkedHashMap;8use linked_hash_map::LinkedHashMap;10use peg::str::LineCol;9use peg::str::LineCol;11use se_impl::MySerialize;10use se_impl::MySerialize;197 assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"\n");196 assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"\n");198}197}199pub fn format_nix(value: &String) -> String {198pub fn format_nix(value: &String) -> String {200 let (_, out) = alejandra::format::in_memory(199 // TODO201 "".to_owned(),202 value.to_owned(),200 value.to_owned()203 alejandra::config::Config {204 indentation: Indentation::TwoSpaces,205 },206 );207 out208}201}209202210#[test]203#[test]crates/nixlike/src/to_string.rsdiffbeforeafterboth1use alejandra::config::Indentation;23use crate::Value;1use crate::Value;42100pub fn write_nix(value: &Value) -> String {98pub fn write_nix(value: &Value) -> String {101 let mut out = String::new();99 let mut out = String::new();102 write_nix_buf(value, &mut out);100 write_nix_buf(value, &mut out);103 let (_, out) = alejandra::format::in_memory(104 "".to_owned(),105 out,106 alejandra::config::Config {107 indentation: Indentation::TwoSpaces,108 },109 );110 out101 out111}102}112103flake.nixdiffbeforeafterboth114 {114 {115 _module.args.pkgs = import inputs.nixpkgs {115 _module.args.pkgs = import inputs.nixpkgs {116 inherit system;116 inherit system;117 overlays = [ (inputs.rust-overlay.overlays.default) ];117 overlays = [ (inputs.rust-overlay.overlays.default) (final: prev: {118 boehmgc = prev.boehmgc.overrideAttrs (prevAttrs: {119 configureFlags = prevAttrs.configureFlags ++ [120 "--enable-gc-assertions"121 ];122 });123 }) ];118 };124 };119 # Reference fleet package should be built with nightly rust, specified in rust-toolchain.toml.125 # Reference fleet package should be built with nightly rust, specified in rust-toolchain.toml.120 packages = lib.mkIf deployerSystem (126 packages = lib.mkIf deployerSystem (157 factory = craneLib.devShell;163 factory = craneLib.devShell;158 packages = with pkgs; [164 packages = with pkgs; [159 rust165 rust160 alejandra161 cargo-edit166 cargo-edit162 cargo-udeps167 cargo-udeps163 cargo-fuzz168 cargo-fuzz