From 521a65806d80d66ba15e2c4a29c1a209c1052d1b Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Mon, 01 Sep 2025 01:46:11 +0000 Subject: [PATCH] refactor: use nix bindings instead of REPL --- --- a/Cargo.lock +++ b/Cargo.lock @@ -22,9 +22,9 @@ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aead" @@ -63,9 +63,9 @@ [[package]] name = "age" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2020562e68d7a02c2743707b262c62484b340a296924a5e4146d5a0a96ca8103" +checksum = "57fc171f4874fa10887e47088f81a55fcf030cd421aa31ec2b370cafebcc608a" dependencies = [ "aes", "aes-gcm", @@ -127,12 +127,13 @@ [[package]] name = "alejandra" -version = "3.1.0" -source = "git+https://github.com/kamadorueda/alejandra#264e23546663a5676a77174cab31340a81aa2cc0" +version = "4.0.0" +source = "git+https://github.com/kamadorueda/alejandra#c68bef57c1db3add865493d9cb741a14618bdc28" dependencies = [ "mimalloc", "rnix", "rowan", + "serde", ] [[package]] @@ -152,9 +153,9 @@ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -167,43 +168,44 @@ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arc-swap" @@ -241,9 +243,9 @@ [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", @@ -258,9 +260,9 @@ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" @@ -283,8 +285,8 @@ "pin-project-lite", "rustversion", "serde", - "sync_wrapper 1.0.1", - "tower 0.5.1", + "sync_wrapper", + "tower 0.5.2", "tower-layer", "tower-service", ] @@ -304,16 +306,16 @@ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper", "tower-layer", "tower-service", ] [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -321,7 +323,7 @@ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -338,15 +340,15 @@ [[package]] name = "base64ct" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "basic-toml" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" dependencies = [ "serde", ] @@ -380,10 +382,30 @@ ] [[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn", +] + +[[package]] name = "bitflags" -version = "2.9.1" +version = "2.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" dependencies = [ "serde", ] @@ -418,15 +440,15 @@ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytecount" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e" [[package]] name = "byteorder" @@ -436,9 +458,9 @@ [[package]] name = "bytes" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cbc" @@ -450,28 +472,28 @@ ] [[package]] -name = "cbitset" -version = "0.2.0" +name = "cc" +version = "1.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b" +checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" dependencies = [ - "num-traits", + "shlex", ] [[package]] -name = "cc" -version = "1.2.1" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "shlex", + "nom 7.1.3", ] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "cfg_aliases" @@ -530,10 +552,21 @@ ] [[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] name = "clap" -version = "4.5.21" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" dependencies = [ "clap_builder", "clap_derive", @@ -541,9 +574,9 @@ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" dependencies = [ "anstream", "anstyle", @@ -551,23 +584,23 @@ "strsim", "terminal_size", "unicase", - "unicode-width 0.2.0", + "unicode-width 0.2.1", ] [[package]] name = "clap_complete" -version = "4.5.38" +version = "4.5.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" +checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck", "proc-macro2", @@ -577,27 +610,38 @@ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" +dependencies = [ + "serde", + "termcolor", + "unicode-width 0.2.1", +] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "console" -version = "0.15.8" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width 0.1.11", - "windows-sys 0.52.0", + "once_cell", + "unicode-width 0.2.1", + "windows-sys 0.60.2", ] [[package]] @@ -632,26 +676,20 @@ [[package]] name = "countme" -version = "2.0.4" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328b822bdcba4d4e402be8d9adb6eebf269f969f8eadef977a553ff3c4fbcb58" +checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] name = "crossterm" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -664,7 +702,7 @@ "filedescriptor", "mio", "parking_lot", - "rustix 1.0.7", + "rustix 1.0.8", "signal-hook", "signal-hook-mio", "winapi", @@ -691,6 +729,22 @@ ] [[package]] +name = "ctor" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67773048316103656a637612c4a62477603b777d91d9c62ff2290f9cde178fdb" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2931af7e13dc045d8e9d26afccc6fa115d64e115c9c84b1166288b46f6782c2" + +[[package]] name = "ctr" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -727,24 +781,72 @@ ] [[package]] -name = "dashmap" -version = "6.1.0" +name = "cxx" +version = "1.0.173" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c64ed3da1c337cbaae7223cdcff8b4dddf698d188cd3eaddd1116f6b0295950" +dependencies = [ + "cc", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "ae0a26a75a05551f5ae3d75b3557543d06682284eaa7419113162d602cb45766" dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", + "cc", + "codespan-reporting", + "indexmap 2.11.0", + "proc-macro2", + "quote", + "scratch", + "syn", ] [[package]] +name = "cxxbridge-cmd" +version = "1.0.173" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "952d408b6002b7db4b36da07c682a9cbb34f2db0efa03e976ae50a388414e16c" +dependencies = [ + "clap", + "codespan-reporting", + "indexmap 2.11.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.173" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccbd201b471c75c6abb6321cace706d1982d270e308b891c11a3262d320f5265" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.173" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bea8b915bbc4cb4288f242aa7ca18b23ecc6965e4d6e7c1b07905e3fe2e0c41" +dependencies = [ + "indexmap 2.11.0", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "zeroize", @@ -752,9 +854,9 @@ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "75d7cc94194b4dd0fa12845ef8c911101b7f37633cda14997a6e82099aa0b693" dependencies = [ "powerfmt", "serde", @@ -814,6 +916,21 @@ ] [[package]] +name = "dtor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e58a0764cddb55ab28955347b45be00ade43d4d6f3ba4bf3dc354e4ec9432934" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + +[[package]] name = "ed25519" version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -825,9 +942,9 @@ [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", @@ -839,37 +956,58 @@ [[package]] name = "either" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "env_filter" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "log", +] [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fiat-crypto" @@ -879,9 +1017,9 @@ [[package]] name = "filedescriptor" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7199d965852c3bac31f779ef99cbb4537f80e952e2d6aa0ffeb30cce00f4f46e" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" dependencies = [ "libc", "thiserror 1.0.69", @@ -899,9 +1037,9 @@ [[package]] name = "fixedbitset" -version = "0.4.2" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "fleet" @@ -963,7 +1101,7 @@ "nixlike", "nom 8.0.0", "openssh", - "rand 0.9.1", + "rand 0.9.2", "serde", "serde_json", "tabled", @@ -985,7 +1123,7 @@ "ed25519-dalek", "fleet-shared", "hex", - "rand 0.9.1", + "rand 0.9.2", "x25519-dalek", ] @@ -1035,7 +1173,7 @@ "fluent-syntax", "intl-memoizer", "intl_pluralrules", - "rustc-hash", + "rustc-hash 1.1.0", "self_cell 0.10.3", "smallvec", "unic-langid", @@ -1066,6 +1204,12 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] name = "futures" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1166,13 +1310,13 @@ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", ] [[package]] @@ -1184,7 +1328,7 @@ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasi 0.14.3+wasi-0.2.4", ] [[package]] @@ -1204,10 +1348,16 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] name = "h2" -version = "0.4.6" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -1215,7 +1365,7 @@ "futures-core", "futures-sink", "http", - "indexmap 2.6.0", + "indexmap 2.11.0", "slab", "tokio", "tokio-util", @@ -1224,12 +1374,6 @@ [[package]] name = "hashbrown" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" - -[[package]] -name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" @@ -1242,9 +1386,9 @@ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" [[package]] name = "heck" @@ -1254,15 +1398,9 @@ [[package]] name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hermit-abi" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -1310,9 +1448,9 @@ [[package]] name = "http" -version = "1.1.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" dependencies = [ "bytes", "fnv", @@ -1331,12 +1469,12 @@ [[package]] name = "http-body-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "pin-project-lite", @@ -1344,9 +1482,9 @@ [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "httpdate" @@ -1362,13 +1500,14 @@ [[package]] name = "hyper" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" dependencies = [ + "atomic-waker", "bytes", "futures-channel", - "futures-util", + "futures-core", "h2", "http", "http-body", @@ -1376,6 +1515,7 @@ "httpdate", "itoa", "pin-project-lite", + "pin-utils", "smallvec", "tokio", "want", @@ -1396,18 +1536,20 @@ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ "bytes", "futures-channel", + "futures-core", "futures-util", "http", "http-body", "hyper", + "libc", "pin-project-lite", - "socket2", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -1415,9 +1557,9 @@ [[package]] name = "i18n-config" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e88074831c0be5b89181b05e6748c4915f77769ecc9a4c372f88b169a8509c9" +checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef" dependencies = [ "basic-toml", "log", @@ -1429,9 +1571,9 @@ [[package]] name = "i18n-embed" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7839d8c7bb8da7bd58c1112d3a1aeb7f178ff3df4ae87783e758ca3bfb750b7" +checksum = "669ffc2c93f97e6ddf06ddbe999fcd6782e3342978bb85f7d3c087c7978404c4" dependencies = [ "arc-swap", "fluent", @@ -1439,7 +1581,6 @@ "fluent-syntax", "i18n-embed-impl", "intl-memoizer", - "lazy_static", "log", "parking_lot", "rust-embed", @@ -1450,17 +1591,15 @@ [[package]] name = "i18n-embed-fl" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e9571c3cba9eba538eaa5ee40031b26debe76f0c7e17bafc97ea57a76cd82e" +checksum = "04b2969d0b3fc6143776c535184c19722032b43e6a642d710fa3f88faec53c2d" dependencies = [ - "dashmap", "find-crate", "fluent", "fluent-syntax", "i18n-config", "i18n-embed", - "lazy_static", "proc-macro-error2", "proc-macro2", "quote", @@ -1484,14 +1623,15 @@ [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", "windows-core", ] @@ -1517,24 +1657,24 @@ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.5", ] [[package]] name = "indicatif" -version = "0.17.9" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" dependencies = [ "console", - "number_prefix", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width 0.2.1", + "unit-prefix", "vt100", "web-time", ] @@ -1547,9 +1687,9 @@ [[package]] name = "inout" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ "block-padding", "generic-array", @@ -1557,9 +1697,9 @@ [[package]] name = "intl-memoizer" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" +checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" dependencies = [ "type-map", "unic-langid", @@ -1575,6 +1715,17 @@ ] [[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] name = "io_tee" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1582,13 +1733,13 @@ [[package]] name = "is-terminal" -version = "0.4.13" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1623,16 +1774,17 @@ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1647,27 +1799,46 @@ [[package]] name = "libc" -version = "0.2.174" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.3", +] + +[[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libmimalloc-sys" -version = "0.1.39" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +checksum = "667f4fec20f29dfc6bc7357c582d91796c169ad7e2fce709468aefeb2c099870" dependencies = [ "cc", "libc", ] [[package]] +name = "link-cplusplus" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6f6da007f968f9def0d65a05b187e2960183de70c160204ecfccf0ee330212" +dependencies = [ + "cc", +] + +[[package]] name = "linked-hash-map" version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1675,9 +1846,9 @@ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" @@ -1687,15 +1858,15 @@ [[package]] name = "litrs" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" +checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -1703,17 +1874,17 @@ [[package]] name = "log" -version = "0.4.22" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -1724,24 +1895,24 @@ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] [[package]] name = "mimalloc" -version = "0.1.43" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +checksum = "e1ee66a4b64c74f4ef288bcbb9192ad9c3feaad75193129ac8509af543894fd8" dependencies = [ "libmimalloc-sys", ] @@ -1760,31 +1931,30 @@ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ - "hermit-abi 0.3.9", "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] name = "multimap" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "nix" @@ -1804,17 +1974,24 @@ dependencies = [ "anyhow", "better-command", + "bindgen", + "ctor", + "cxx", + "cxx-build", "futures", "itertools 0.14.0", "nixlike", + "pkg-config", "r2d2", "regex", "serde", "serde_json", - "thiserror 2.0.12", + "test-log", + "thiserror 2.0.16", "tokio", "tokio-util", "tracing", + "tracing-indicatif", "unindent", ] @@ -1829,7 +2006,7 @@ "serde", "serde-transcode", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.16", ] [[package]] @@ -1853,12 +2030,11 @@ [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -1915,25 +2091,25 @@ ] [[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "opaque-debug" @@ -1951,24 +2127,18 @@ "once_cell", "shell-escape", "tempfile", - "thiserror 2.0.12", + "thiserror 2.0.16", "tokio", ] [[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] name = "owo-colors" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" dependencies = [ "supports-color 2.1.0", - "supports-color 3.0.1", + "supports-color 3.0.2", ] [[package]] @@ -1979,14 +2149,14 @@ dependencies = [ "bytecount", "fnv", - "unicode-width 0.2.0", + "unicode-width 0.2.1", ] [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1994,15 +2164,15 @@ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2050,9 +2220,9 @@ [[package]] name = "pem" -version = "3.0.4" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" dependencies = [ "base64 0.22.1", "serde", @@ -2060,34 +2230,34 @@ [[package]] name = "percent-encoding" -version = "2.3.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "petgraph" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset", - "indexmap 2.6.0", + "indexmap 2.11.0", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", @@ -2096,9 +2266,9 @@ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2128,6 +2298,12 @@ ] [[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] name = "poly1305" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2152,9 +2328,9 @@ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "powerfmt" @@ -2164,18 +2340,18 @@ [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", @@ -2205,18 +2381,18 @@ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" dependencies = [ "bytes", "prost-derive", @@ -2224,13 +2400,12 @@ [[package]] name = "prost-build" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "bytes", "heck", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -2245,12 +2420,12 @@ [[package]] name = "prost-derive" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn", @@ -2258,18 +2433,18 @@ [[package]] name = "prost-types" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" dependencies = [ "prost", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" dependencies = [ "proc-macro2", ] @@ -2304,9 +2479,9 @@ [[package]] name = "rand" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", @@ -2338,7 +2513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -2352,9 +2527,9 @@ [[package]] name = "rcgen" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" +checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" dependencies = [ "pem", "ring", @@ -2365,68 +2540,52 @@ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" [[package]] name = "ring" -version = "0.17.8" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -2455,20 +2614,18 @@ [[package]] name = "rnix" -version = "0.10.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8024a523e8836f1a5d051203dc00d833357fee94e351b51348dfaeca5364daa9" +checksum = "6f15e00b0ab43abd70d50b6f8cd021290028f9b7fdd7cdfa6c35997173bc1ba9" dependencies = [ - "cbitset", "rowan", - "smol_str", ] [[package]] name = "ron" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beceb6f7bf81c73e73aeef6dd1356d9a1b2b4909e1f0fc3e59b034f9572d7b7f" +checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468" dependencies = [ "base64 0.22.1", "bitflags", @@ -2479,22 +2636,22 @@ [[package]] name = "rowan" -version = "0.12.6" +version = "0.15.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b36e449f3702f3b0c821411db1cbdf30fb451726a9456dce5dabcd44420043" +checksum = "d4f1e4a001f863f41ea8d0e6a0c34b356d5b733db50dadab3efef640bafb779b" dependencies = [ "countme", - "hashbrown 0.9.1", + "hashbrown 0.14.5", "memoffset", - "rustc-hash", + "rustc-hash 1.1.0", "text-size", ] [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" dependencies = [ "const-oid", "digest", @@ -2512,9 +2669,9 @@ [[package]] name = "rust-embed" -version = "8.5.0" +version = "8.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" +checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -2523,9 +2680,9 @@ [[package]] name = "rust-embed-impl" -version = "8.5.0" +version = "8.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" +checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c" dependencies = [ "proc-macro2", "quote", @@ -2536,9 +2693,9 @@ [[package]] name = "rust-embed-utils" -version = "8.5.0" +version = "8.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" +checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594" dependencies = [ "sha2", "walkdir", @@ -2546,9 +2703,9 @@ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -2557,6 +2714,12 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2567,35 +2730,35 @@ [[package]] name = "rustix" -version = "0.38.40" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys 0.4.14", - "windows-sys 0.52.0", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", ] [[package]] name = "rustix" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "rustls" -version = "0.23.17" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "log", "once_cell", @@ -2617,15 +2780,18 @@ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] [[package]] name = "rustls-webpki" -version = "0.102.8" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "ring", "rustls-pki-types", @@ -2634,15 +2800,15 @@ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "salsa20" @@ -2678,6 +2844,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "scratch" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" + +[[package]] name = "scrypt" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2703,20 +2875,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" dependencies = [ - "self_cell 1.0.4", + "self_cell 1.2.0", ] [[package]] name = "self_cell" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" @@ -2738,9 +2910,9 @@ [[package]] name = "serde_bytes" -version = "0.11.15" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" dependencies = [ "serde", ] @@ -2758,9 +2930,9 @@ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" dependencies = [ "itoa", "memchr", @@ -2770,9 +2942,9 @@ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -2802,9 +2974,9 @@ [[package]] name = "signal-hook" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ "libc", "signal-hook-registry", @@ -2823,9 +2995,9 @@ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -2842,36 +3014,34 @@ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.13.2" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "smol_str" -version = "0.1.24" +name = "socket2" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ - "serde", + "libc", + "windows-sys 0.52.0", ] [[package]] name = "socket2" -version = "0.5.7" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2914,18 +3084,18 @@ [[package]] name = "supports-color" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77" +checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" dependencies = [ "is_ci", ] [[package]] name = "syn" -version = "2.0.87" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -2934,15 +3104,9 @@ [[package]] name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - -[[package]] -name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" [[package]] name = "tabled" @@ -2970,25 +3134,34 @@ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.7", - "windows-sys 0.59.0", + "rustix 1.0.8", + "windows-sys 0.60.2", ] [[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] name = "terminal_size" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" +checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 0.38.40", - "windows-sys 0.59.0", + "rustix 1.0.8", + "windows-sys 0.60.2", ] [[package]] @@ -3003,12 +3176,34 @@ ] [[package]] +name = "test-log" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b" +dependencies = [ + "env_logger", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "testing_table" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f8daae29995a24f65619e19d8d31dea5b389f3d853d8bf297bbf607cd0014cc" dependencies = [ - "unicode-width 0.2.0", + "unicode-width 0.2.1", ] [[package]] @@ -3056,11 +3251,11 @@ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.16", ] [[package]] @@ -3076,9 +3271,9 @@ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" dependencies = [ "proc-macro2", "quote", @@ -3087,19 +3282,18 @@ [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ "cfg-if", - "once_cell", ] [[package]] name = "time" -version = "0.3.41" +version = "0.3.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "8ca967379f9d8eb8058d86ed467d81d03e81acd45757e4ca341c24affbe8e8e3" dependencies = [ "deranged", "num-conv", @@ -3111,15 +3305,15 @@ [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "a9108bb380861b07264b950ded55a44a14a4adc68b9f5efd85aafc3aa4d40a68" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "7182799245a7264ce590b349d90338f1c1affad93d2639aed5f8f69c090b334c" dependencies = [ "num-conv", "time-core", @@ -3127,28 +3321,31 @@ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", + "zerovec", ] [[package]] name = "tokio" -version = "1.45.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3164,20 +3361,19 @@ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite", @@ -3187,9 +3383,9 @@ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -3229,7 +3425,7 @@ "pin-project", "prost", "rustls-pemfile", - "socket2", + "socket2 0.5.10", "tokio", "tokio-rustls", "tokio-stream", @@ -3275,14 +3471,14 @@ [[package]] name = "tower" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 0.1.2", + "sync_wrapper", "tower-layer", "tower-service", ] @@ -3318,9 +3514,9 @@ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -3329,9 +3525,9 @@ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", @@ -3340,9 +3536,9 @@ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -3350,9 +3546,9 @@ [[package]] name = "tracing-indicatif" -version = "0.3.6" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069580424efe11d97c3fef4197fa98c004fa26672cc71ad8770d224e23b1951d" +checksum = "04d4e11e0e27acef25a47f27e9435355fecdc488867fa2bc90e75b0700d2823d" dependencies = [ "indicatif", "tracing", @@ -3373,9 +3569,9 @@ [[package]] name = "tracing-serde" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ "serde", "tracing-core", @@ -3383,14 +3579,14 @@ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "serde", "serde_json", "sharded-slab", @@ -3410,33 +3606,33 @@ [[package]] name = "type-map" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" dependencies = [ - "rustc-hash", + "rustc-hash 2.1.1", ] [[package]] name = "typenum" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" [[package]] name = "unic-langid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" dependencies = [ "unic-langid-impl", ] [[package]] name = "unic-langid-impl" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" dependencies = [ "serde", "tinystr", @@ -3444,15 +3640,15 @@ [[package]] name = "unicase" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" [[package]] name = "unicode-segmentation" @@ -3462,15 +3658,15 @@ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unicode_categories" @@ -3485,6 +3681,12 @@ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] +name = "unit-prefix" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" + +[[package]] name = "universal-hash" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3508,9 +3710,9 @@ [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "version_check" @@ -3526,7 +3728,7 @@ dependencies = [ "itoa", "log", - "unicode-width 0.1.11", + "unicode-width 0.1.14", "vte", ] @@ -3572,39 +3774,39 @@ [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.2+wasi-0.2.4" +version = "0.14.3+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -3613,9 +3815,9 @@ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3623,9 +3825,9 @@ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -3636,9 +3838,12 @@ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-time" @@ -3659,7 +3864,7 @@ "either", "home", "once_cell", - "rustix 0.38.40", + "rustix 0.38.44", ] [[package]] @@ -3680,11 +3885,11 @@ [[package]] name = "winapi-util" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -3695,11 +3900,37 @@ [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -3709,12 +3940,30 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -3723,23 +3972,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", +] + +[[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -3749,55 +4024,100 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "windows_x86_64_msvc" +version = "0.53.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "wit-bindgen" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" [[package]] name = "wsl" @@ -3834,19 +4154,18 @@ [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", @@ -3854,6 +4173,12 @@ ] [[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" + +[[package]] name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3872,3 +4197,12 @@ "quote", "syn", ] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "zerofrom", +] --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ nix-eval = { path = "./crates/nix-eval" } nixlike = { path = "./crates/nixlike" } -age = { version = "0.11", features = ["ssh", "plugin"] } +age = { version = "0.11", features = ["plugin", "ssh"] } anyhow = "1.0" clap = { version = "4.5", features = ["derive", "env", "unicode", "wrap_help"] } clap_complete = "4.5" --- a/cmds/fleet/Cargo.toml +++ b/cmds/fleet/Cargo.toml @@ -43,7 +43,7 @@ fleet-base = { version = "0.1.0", path = "../../crates/fleet-base" } human-repr = { version = "1.1", optional = true } -indicatif = { version = "0.17", optional = true } +indicatif = { version = "0.18", optional = true } nom = "8.0.0" tracing-indicatif = { version = "0.3", optional = true } --- a/cmds/fleet/src/cmds/build_systems.rs +++ b/cmds/fleet/src/cmds/build_systems.rs @@ -1,13 +1,13 @@ use std::{env::current_dir, os::unix::fs::symlink, path::PathBuf}; -use anyhow::{Result, anyhow}; +use anyhow::Result; use clap::Parser; use fleet_base::{ deploy::{DeployAction, deploy_task, upload_task}, host::{Config, DeployKind, GenerationStorage}, opts::FleetOpts, }; -use nix_eval::{NixBuildBatch, nix_go}; +use nix_eval::nix_go; use tokio::task::LocalSet; use tracing::{Instrument, error, field, info, info_span, warn}; @@ -32,17 +32,15 @@ config: Config, hostname: String, build_attr: &str, - batch: Option, + // batch: Option, ) -> Result { info!("building"); let host = config.host(&hostname).await?; // let action = Action::from(self.subcommand.clone()); let nixos = host.nixos_config().await?; let drv = nix_go!(nixos.system.build[{ build_attr }]); - let outputs = drv.build_maybe_batch(batch).await?; - let out_output = outputs - .get("out") - .ok_or_else(|| anyhow!("system build should produce \"out\" output"))?; + // let outputs = drv.build_maybe_batch(batch).await?; + let out_output = drv.build("out").await?; // We already have system profiles for backups. if !host.local { @@ -56,11 +54,11 @@ config.data().gc_root_prefix ), ) - .arg(out_output); + .arg(&out_output); cmd.sudo().run_nix().await?; } - Ok(out_output.clone()) + Ok(out_output) } impl BuildSystems { @@ -68,21 +66,20 @@ let hosts = opts.filter_skipped(config.list_hosts().await?).await?; let set = LocalSet::new(); let build_attr = self.build_attr.clone(); - let batch = (hosts.len() > 1).then(|| { - config - .nix_session - .new_build_batch("build-hosts".to_string()) - }); + // let batch = (hosts.len() > 1).then(|| { + // config + // .nix_session + // .new_build_batch("build-hosts".to_string()) + // }); for host in hosts { let config = config.clone(); let span = info_span!("build", host = field::display(&host.name)); let hostname = host.name; let build_attr = build_attr.clone(); - let batch = batch.clone(); + // let batch = batch.clone(); set.spawn_local( (async move { - let built = match build_task(config, hostname.clone(), &build_attr, batch).await - { + let built = match build_task(config, hostname.clone(), &build_attr).await { Ok(path) => path, Err(e) => { error!("failed to deploy host: {}", e); @@ -91,7 +88,7 @@ }; // TODO: Handle error let mut out = current_dir().expect("cwd exists"); - out.push(format!("built-{}", hostname)); + out.push(format!("built-{hostname}")); info!("linking iso image to {:?}", out); if let Err(e) = symlink(built, out) { @@ -101,7 +98,6 @@ .instrument(span), ); } - drop(batch); set.await; Ok(()) } @@ -111,17 +107,16 @@ pub async fn run(self, config: &Config, opts: &FleetOpts) -> Result<()> { let hosts = opts.filter_skipped(config.list_hosts().await?).await?; let set = LocalSet::new(); - let batch = (hosts.len() > 1).then(|| { - config - .nix_session - .new_build_batch("deploy-hosts".to_string()) - }); + // let batch = (hosts.len() > 1).then(|| { + // config + // .nix_session + // .new_build_batch("deploy-hosts".to_string()) + // }); for host in hosts.into_iter() { let config = config.clone(); let span = info_span!("deploy", host = field::display(&host.name)); let hostname = host.name.clone(); let opts = opts.clone(); - let batch = batch.clone(); if let Some(deploy_kind) = opts.action_attr::(&host, "deploy_kind").await? { host.set_deploy_kind(deploy_kind); }; @@ -131,15 +126,14 @@ set.spawn_local( (async move { - let built = - match build_task(config.clone(), hostname.clone(), "toplevel", batch).await - { - Ok(path) => path, - Err(e) => { - error!("failed to build host system closure: {}", e); - return; - } - }; + let built = match build_task(config.clone(), hostname.clone(), "toplevel").await + { + Ok(path) => path, + Err(e) => { + error!("failed to build host system closure: {:#}", e); + return; + } + }; let deploy_kind = match host.deploy_kind().await { Ok(v) => v, @@ -187,7 +181,6 @@ .instrument(span), ); } - drop(batch); set.await; Ok(()) } --- a/cmds/fleet/src/cmds/info.rs +++ b/cmds/fleet/src/cmds/info.rs @@ -38,7 +38,8 @@ 'host: for host in config.list_hosts().await? { if !tagged.is_empty() { let config = &config.config_field; - let tags: Vec = nix_go_json!(config.hosts[{ host.name }].tags); + let host_name = &host.name; + let tags: Vec = nix_go_json!(config.hosts[host_name].tags); for tag in tagged { if !tags.contains(tag) { continue 'host; --- a/cmds/fleet/src/cmds/secrets/mod.rs +++ b/cmds/fleet/src/cmds/secrets/mod.rs @@ -2,6 +2,7 @@ collections::{BTreeMap, BTreeSet, HashSet}, io::{self, Read, Write, stdin, stdout}, path::PathBuf, + slice, }; use age::Recipient; @@ -14,7 +15,7 @@ opts::FleetOpts, }; use fleet_shared::SecretData; -use nix_eval::{NixBuildBatch, Value, nix_go, nix_go_json}; +use nix_eval::{NixType, Value, nix_go, nix_go_json}; use owo_colors::OwoColorize; use serde::Deserialize; use tabled::{Table, Tabled}; @@ -159,7 +160,7 @@ } #[allow(clippy::too_many_arguments)] -#[tracing::instrument(skip(config, secret, field, prefer_identities, batch))] +#[tracing::instrument(skip(config, secret, field, prefer_identities))] async fn maybe_regenerate_shared_secret( secret_name: &str, config: &Config, @@ -168,7 +169,7 @@ expected_owners: &[String], expected_generation_data: serde_json::Value, prefer_identities: &[String], - batch: Option, + // batch: Option, ) -> Result { let original_set = secret.owners.clone(); @@ -206,12 +207,12 @@ field, expected_owners.to_vec(), expected_generation_data, - batch, + // batch, ) .await?; Ok(generated) } else { - drop(batch); + // drop(batch); let identity_holder = if !prefer_identities.is_empty() { prefer_identities .iter() @@ -263,7 +264,7 @@ default_generator: Value, expected_owners: &[String], expected_generation_data: serde_json::Value, - batch: Option, + // batch: Option, ) -> Result { let generator = nix_go!(secret.generator); let on: Option = nix_go_json!(default_generator.impureOn); @@ -284,17 +285,16 @@ recipients.push(key); } let generators = nix_go!(mk_secret_generators(Obj { recipients })); - let pkgs_and_generators = nix_go!(on_pkgs + generators); + // FIXME: Apparently, // operator is slow in nix + let pkgs_and_generators = on_pkgs.attrs_update(generators)?; let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators)); let generator = nix_go!(call_package(generator)(Obj {})); - let generator = generator.build_maybe_batch(batch).await?; - let generator = generator - .get("out") - .ok_or_else(|| anyhow!("missing generateImpure out"))?; - let generator = host.remote_derivation(generator).await?; + // let generator = generator.build_maybe_batch(batch).await?; + let generator = generator.build("out").await?; + let generator = host.remote_derivation(&generator).await?; let out_parent = host.mktemp_dir().await?; let out = format!("{out_parent}/out"); @@ -347,21 +347,21 @@ secret: Value, expected_owners: &[String], expected_generation_data: serde_json::Value, - batch: Option, + // batch: Option, ) -> Result { let generator = nix_go!(secret.generator); // Can't properly check on nix module system level { - let gen_ty = generator.type_of().await?; - if gen_ty == "null" { + let gen_ty = generator.type_of()?; + if matches!(gen_ty, NixType::Null) { bail!("secret has no generator defined, can't automatically generate it."); } - if gen_ty == "set" { - if !generator.has_field("__functor").await? { - bail!("generator should be functor, got {gen_ty}"); + if matches!(gen_ty, NixType::Attrs) { + if !generator.has_field("__functor")? { + bail!("generator should be functor, got {gen_ty:?}"); } - } else if gen_ty != "lambda" { - bail!("generator should be functor, got {gen_ty}"); + } else if matches!(gen_ty, NixType::Function) { + bail!("generator should be functor, got {gen_ty:?}"); } } let nixpkgs = &config.nixpkgs; @@ -378,7 +378,7 @@ let generators = nix_go!(default_mk_secret_generators(Obj { recipients: >::new(), })); - let pkgs_and_generators = nix_go!(default_pkgs + generators); + let pkgs_and_generators = default_pkgs.clone().attrs_update(generators)?; let call_package = nix_go!(nixpkgs.lib.callPackageWith(pkgs_and_generators)); let default_generator = nix_go!(call_package(generator)(Obj {})); @@ -394,7 +394,7 @@ default_generator, expected_owners, expected_generation_data, - batch, + // batch, ) .await } @@ -416,7 +416,7 @@ secret: Value, expected_owners: Vec, expected_generation_data: serde_json::Value, - batch: Option, + // batch: Option, ) -> Result { // let owners: Vec = nix_go_json!(secret.expectedOwners); Ok(FleetSharedSecret { @@ -426,7 +426,7 @@ secret, &expected_owners, expected_generation_data, - batch, + // batch, ) .await?, owners: expected_owners, @@ -722,7 +722,8 @@ } let config_field = &config.config_field; - let field = nix_go!(config_field.sharedSecrets[{ name }]); + let name_clone = name.clone(); + let field = nix_go!(config_field.sharedSecrets[name_clone]); let expected_generation_data = nix_go_json!(field.expectedGenerationData); let updated = maybe_regenerate_shared_secret( @@ -733,7 +734,7 @@ &target_machines, expected_generation_data, &prefer_identities, - None, + // None, ) .await?; config.replace_shared(name, updated); @@ -746,7 +747,7 @@ let stored_shared_set = config.list_shared().into_iter().collect::>(); { // Generate missing shared - let shared_batch = None; + // let shared_batch = None; let _span = info_span!("shared").entered(); let expected_shared_set = config .list_configured_shared() @@ -771,7 +772,7 @@ secret, expected_owners, expected_generation_data, - shared_batch.clone(), + // shared_batch.clone(), ) .in_current_span() .await?; @@ -779,7 +780,7 @@ } } if !skip_hosts { - let hosts_batch = None; + // let hosts_batch = None; for host in config.list_hosts().await? { if opts.should_skip(&host).await? { continue; @@ -805,9 +806,9 @@ config, missing, secret, - &[host.name.clone()], + slice::from_ref(&host.name), expected_generation_data, - hosts_batch.clone(), + // hosts_batch.clone(), ) .in_current_span() .await @@ -831,9 +832,9 @@ config, &name, secret, - &[host.name.clone()], + slice::from_ref(&host.name), expected_generation_data, - hosts_batch.clone(), + // hosts_batch.clone(), ) .in_current_span() .await @@ -874,7 +875,7 @@ &expected_owners, expected_generation_data, &prefer_identities, - None, + // None, ) .await?, ); --- a/cmds/fleet/src/cmds/tf.rs +++ b/cmds/fleet/src/cmds/tf.rs @@ -42,8 +42,7 @@ debug!("generating terraform configs"); let system = &config.local_system; let config = &config.config_field; - let data: HashMap = nix_go!(config.tf({ system })).build().await?; - let data = &data["out"]; + let data: PathBuf = nix_go!(config.tf({ system })).build("out").await?; let data = fs::read(&data).await?; create_dir_all(&dir).await?; --- a/cmds/fleet/src/main.rs +++ b/cmds/fleet/src/main.rs @@ -23,6 +23,7 @@ use human_repr::HumanCount; #[cfg(feature = "indicatif")] use indicatif::{ProgressState, ProgressStyle}; +use nix_eval::{gc_register_my_thread, gc_unregister_my_thread, init_libraries}; use tracing::{Instrument, error, info, info_span}; #[cfg(feature = "indicatif")] use tracing_indicatif::IndicatifLayer; @@ -183,21 +184,31 @@ } setup_logging(); - async_main(opts) -} -#[tokio::main] -async fn async_main(opts: RootOpts) -> ExitCode { - if let Err(e) = main_real(opts).await { - error!("{e:#}"); - return ExitCode::FAILURE; - } - ExitCode::SUCCESS + init_libraries(); + + tokio::runtime::Builder::new_multi_thread() + .enable_all() + .on_thread_start(|| { + gc_register_my_thread(); + }) + .on_thread_stop(|| { + gc_unregister_my_thread(); + }) + .build() + .expect("failed to build runtime") + .block_on(async { + if let Err(e) = main_real(opts).await { + error!("{e:#}"); + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } + }) + // async_main(opts) } async fn main_real(opts: RootOpts) -> Result<()> { - nix_eval::init_tokio(); - let nix_args = std::env::var_os("NIX_ARGS") .map(|a| extra_args::parse_os(&a)) .transpose()? --- a/crates/fleet-base/src/host.rs +++ b/crates/fleet-base/src/host.rs @@ -12,7 +12,7 @@ use anyhow::{Context, Result, anyhow, bail, ensure}; use fleet_shared::SecretData; -use nix_eval::{NixSession, Value, nix_go, nix_go_json, util::assert_warn}; +use nix_eval::{Value, nix_go, nix_go_json, util::assert_warn}; use openssh::SessionBuilder; use serde::de::DeserializeOwned; use tabled::Tabled; @@ -41,8 +41,6 @@ pub default_pkgs: Value, /// inputs.nixpkgs pub nixpkgs: Value, - - pub nix_session: NixSession, } // TODO: Make field not pub @@ -232,14 +230,17 @@ } }; if !is_fleet_managed { - bail!(indoc::indoc! {" + bail!( + "{}", + indoc::indoc! {" host is not marked as managed by fleet if you're not trying to lustrate/install system from scratch, you should either 1. manually create /etc/FLEET_HOST file on the target host, 2. use ?deploy_kind=fleet host argument if you're upgrading from older version of fleet 3. use ?deploy_kind=upgrade_to_fleet if you're upgrading from plain nixos to fleet-managed nixos - "}); + "} + ); } // TOCTOU is possible let _ = self.deploy_kind.set(DeployKind::Fleet); @@ -503,8 +504,8 @@ let nixos = self.nixos_unchecked_config().await?; let secrets = nix_go!(nixos.secrets); let mut out = Vec::new(); - for name in secrets.list_fields().await? { - let secret = nix_go!(secrets[{ name }]); + for name in secrets.list_fields()? { + let secret = secrets.get_field(&name)?; let is_shared: bool = nix_go_json!(secret.shared); if is_shared { continue; @@ -592,7 +593,7 @@ } pub async fn list_hosts(&self) -> Result> { let config = &self.config_field; - let names = nix_go!(config.hosts).list_fields().await?; + let names = nix_go!(config.hosts).list_fields()?; let mut out = vec![]; for name in names { out.push(self.host(&name).await?); @@ -608,7 +609,7 @@ /// Shared secrets configured in fleet.nix or in flake pub async fn list_configured_shared(&self) -> Result> { let config_field = &self.config_field; - Ok(nix_go!(config_field.sharedSecrets).list_fields().await?) + nix_go!(config_field.sharedSecrets).list_fields() } /// Shared secrets configured in fleet.nix pub fn list_shared(&self) -> Vec { @@ -680,10 +681,10 @@ // maybe it can be a .nix file for persistence, but accessible only // thru some shared state controller? Might it be stored in terraform // state provider? - pub fn data(&self) -> MutexGuard { + pub fn data(&'_ self) -> MutexGuard<'_, FleetData> { self.data.lock().unwrap() } - pub fn data_mut(&self) -> MutexGuard { + pub fn data_mut(&'_ self) -> MutexGuard<'_, FleetData> { self.data.lock().unwrap() } pub fn save(&self) -> Result<()> { @@ -691,8 +692,7 @@ let data = nixlike::serialize(&self.data() as &FleetData)?; tempfile.write_all( format!( - "# This file contains fleet state and shouldn't be edited by hand\n\n{}\n\n# vim: ts=2 et nowrap\n", - data + "# This file contains fleet state and shouldn't be edited by hand\n\n{data}\n\n# vim: ts=2 et nowrap\n" ) .as_bytes(), )?; --- a/crates/fleet-base/src/opts.rs +++ b/crates/fleet-base/src/opts.rs @@ -7,7 +7,7 @@ }; use anyhow::{Context, Result, bail}; -use nix_eval::{NixSessionPool, Value, nix_go, util::assert_warn}; +use nix_eval::{FetchSettings, FlakeReference, FlakeSettings, Value, nix_go, util::assert_warn}; use nom::{ Parser, bytes::complete::take_while1, @@ -210,30 +210,39 @@ std::fs::read_to_string(&fleet_data_path).context("reading fleet state (fleet.nix)")?; let data: Mutex = nixlike::parse_str(&bytes)?; - let pool = NixSessionPool::new( - directory.as_os_str().to_owned(), - nix_args.clone(), - self.local_system.clone(), - self.fail_fast, - ) - .await?; - let nix_session = pool.get().await?; + let mut fetch_settings = FetchSettings::new(); + fetch_settings.set(c"warn-dirty", c"false"); + + // TODO: use correct directory, not cwd + let (mut flake, _) = FlakeReference::new( + directory + .to_str() + .ok_or_else(|| anyhow::anyhow!("fleet dir should have utf-8 path"))?, + &fetch_settings, + )?; + let flake = flake.lock(&fetch_settings)?; + + let mut flake_settings = FlakeSettings::new()?; + let flake = flake.get_attrs(&mut flake_settings)?; - let builtins_field = Value::binding(nix_session.clone(), "builtins").await?; + let builtins_field = Value::eval("builtins")?; - let fleet_root = Value::binding(nix_session.clone(), "fleetConfigurations").await?; - let fleet_field = nix_go!(fleet_root.default({ data })); + let fleet_root = flake.get_field("fleetConfigurations")?; + let data_val = Value::serialized(&data)?; + let fleet_field = nix_go!(fleet_root.default(data_val)); let config_field = nix_go!(fleet_field.config); if assert { - assert_warn("fleet config evaluation", &config_field).await?; + assert_warn("fleet config evaluation", &config_field) + .await + .context("failed to verify assertions")?; } let import = nix_go!(builtins_field.import); let overlays = nix_go!(config_field.nixpkgs.overlays); let nixpkgs = nix_go!(config_field.nixpkgs.buildUsing); - let nixpkgs_imported = nix_go!(nixpkgs | import); + let nixpkgs_imported = nix_go!(import(nixpkgs)); let default_pkgs = nix_go!(nixpkgs_imported(Obj { overlays, @@ -241,7 +250,6 @@ })); Ok(Config(Arc::new(FleetConfigInternals { - nix_session, directory, data, local_system: self.local_system.clone(), --- a/crates/nix-eval/Cargo.toml +++ b/crates/nix-eval/Cargo.toml @@ -16,12 +16,17 @@ tokio-util.workspace = true tracing.workspace = true +cxx = "1.0.168" futures = "0.3.31" itertools = "0.14.0" r2d2 = "0.8.10" regex = "1.11.1" +test-log = { version = "0.2.18", features = ["trace"] } unindent = "0.2.4" +tracing-indicatif = "0.3.13" +ctor = "0.5.0" -# [build-dependencies] -# bindgen = "0.69.4" -# pkg-config = "0.3.30" +[build-dependencies] +bindgen = "0.72.0" +cxx-build = "1.0.168" +pkg-config = "0.3.30" --- a/crates/nix-eval/build.rs +++ b/crates/nix-eval/build.rs @@ -1,30 +1,101 @@ -// use bindgen::callbacks::ParseCallbacks; -// use std::path::PathBuf; -// -// #[derive(Debug)] -// struct StripPrefix; -// impl ParseCallbacks for StripPrefix { -// fn item_name(&self, name: &str) -> Option { -// name.strip_prefix("nix_").map(ToOwned::to_owned) -// } -// } +use bindgen::{ + RustEdition, + callbacks::{ItemInfo, ParseCallbacks}, +}; +use std::path::PathBuf; +#[derive(Debug)] +struct StripPrefix; +impl ParseCallbacks for StripPrefix { + fn item_name(&self, name: ItemInfo<'_>) -> Option { + name.name.strip_prefix("nix_").map(ToOwned::to_owned) + } +} + fn main() { - // - // let mut libnix = bindgen::builder().header_contents("nix.h", " - // #define GC_THREADS - // #include - // #include - // #include - // #include - // #include - // ").parse_callbacks(Box::new(StripPrefix)); - // - // for header in pkg_config::probe_library("nix-expr-c").expect("nix-expr-c").include_paths.into_iter().chain(pkg_config::probe_library("bdw-gc").expect("bdw-gc").include_paths.into_iter()) { - // libnix = libnix.clang_arg(format!("-I{}", header.to_str().expect("path is utf-8"))); - // } + // Link nix C++ libraries for cxx + for lib in &[ + "nix-util", + "nix-store", + "nix-expr", + "nix-flake", + "nix-fetchers", + "bdw-gc", + ] { + if let Ok(library) = pkg_config::probe_library(lib) { + for lib_path in library.libs { + println!("cargo:rustc-link-lib={lib_path}"); + } + for search_path in library.link_paths { + println!("cargo:rustc-link-search=native={}", search_path.display()); + } + } + } + + cxx_build::bridge("src/logging.rs") + .file("src/logging.cc") + .std("c++20") + .shared_flag(true) + .compile("nix-eval-logging"); + cxx_build::bridge("src/lib.rs") + .file("src/lib.cc") + .std("c++20") + .shared_flag(true) + .compile("nix-eval"); + + println!("cargo:rerun-if-changed=src/lib.cc"); + println!("cargo:rerun-if-changed=src/lib.hh"); + println!("cargo:rerun-if-changed=src/logging.cc"); + println!("cargo:rerun-if-changed=src/logging.hh"); + // - // let mut out = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is set by cargo")); - // out.push("bindings.rs"); - // libnix.generate().expect("generate bindings").write_to_file(out).expect("write bindings"); + let mut libnix = bindgen::builder() + .rust_edition(RustEdition::Edition2024) + .header_contents( + "nix.h", + " + #define GC_THREADS + #include + #include + #include + #include + #include + #include + #include + ", + ) + .parse_callbacks(Box::new(StripPrefix)); + + for header in pkg_config::probe_library("nix-expr-c") + .expect("nix-expr-c") + .include_paths + .into_iter() + .chain( + pkg_config::probe_library("nix-flake-c") + .expect("nix-flake-c") + .include_paths + .into_iter(), + ) + .chain( + pkg_config::probe_library("nix-fetchers-c") + .expect("nix-fetchers-c") + .include_paths + .into_iter(), + ) + .chain( + pkg_config::probe_library("bdw-gc") + .expect("bdw-gc") + .include_paths + .into_iter(), + ) { + libnix = libnix.clang_arg(format!("-I{}", header.to_str().expect("path is utf-8"))); + } + + let mut out = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is set by cargo")); + out.push("bindings.rs"); + libnix + .generate() + .expect("generate bindings") + .write_to_file(out) + .expect("write bindings"); } --- /dev/null +++ b/crates/nix-eval/src/lib.cc @@ -0,0 +1,17 @@ +#include "nix-eval/src/lib.rs" +#include "lib.hh" +#include +#include +#include + +struct nix_fetchers_settings { + nix::ref settings; +}; + +extern "C" { +void set_fetcher_setting(nix_fetchers_settings *settings_struct, + const char *setting, const char *value) { + auto &settings_ref = settings_struct->settings; + bool result = settings_ref->set(setting, value); +} +} --- /dev/null +++ b/crates/nix-eval/src/lib.hh @@ -0,0 +1,7 @@ +#pragma once +#include + +extern "C" { +void set_fetcher_setting(nix_fetchers_settings *settings, const char *setting, + const char *value); +} --- a/crates/nix-eval/src/lib.rs +++ b/crates/nix-eval/src/lib.rs @@ -3,120 +3,892 @@ //! //! Current api is awful, little effort was put into this implementation. -use std::{collections::HashMap, path::PathBuf, sync::Arc}; +use std::borrow::Cow; +use std::cell::RefCell; +use std::ffi::{CStr, CString, c_char, c_int, c_uint, c_void}; +use std::fmt; +use std::ptr::null_mut; +use std::sync::LazyLock; +use std::{collections::HashMap, path::PathBuf}; -pub use pool::NixSessionPool; -use pool::NixSessionPoolInner; -use r2d2::PooledConnection; -pub use session::{Error, Result}; -use tokio::sync::{mpsc, oneshot}; -use tracing::instrument; -pub use value::{Index, Value}; +use anyhow::{Context, bail}; +use serde::Serialize; +use serde::de::DeserializeOwned; + +pub use anyhow::Result; + +use self::logging::nix_logging_cxx; +use self::nix_cxx::set_fetcher_setting; +use self::nix_raw::{ + alloc_value, c_context, c_context_create, err_code, err_info_msg, eval_state_build, + eval_state_builder_new, expr_eval_from_string, fetchers_settings, fetchers_settings_free, + fetchers_settings_new, flake_lock, flake_lock_flags, flake_lock_flags_free, + flake_lock_flags_new, flake_reference_parse_flags, flake_reference_parse_flags_free, + flake_reference_parse_flags_new, flake_reference_parse_flags_set_base_directory, + flake_settings, flake_settings_free, flake_settings_new, init_bool, init_int, init_string, + locked_flake_free, locked_flake_get_output_attrs, set_err_msg, setting_set, state_free, + value_decref, value_force, value_incref, +}; -mod pool; -mod session; mod value; // Contains macros helpers +pub mod logging; #[doc(hidden)] pub mod macros; pub mod util; -// #[allow(non_upper_case_globals, non_camel_case_types, non_snake_case)] -// mod nix_raw { -// include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -// } -// fn init() { -// nix_raw::libutil_init(); -// } +#[allow(non_upper_case_globals, non_camel_case_types, non_snake_case)] +mod nix_raw { + include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +} +#[cxx::bridge] +pub mod nix_cxx { + unsafe extern "C++" { + type nix_fetchers_settings; + include!("nix-eval/src/lib.hh"); + + unsafe fn set_fetcher_setting( + settings: *mut nix_fetchers_settings, + setting: *const c_char, + value: *const c_char, + ); + } +} + +#[derive(Debug, PartialEq, Eq)] +pub enum NixType { + Thunk, + Int, + Float, + Bool, + String, + Path, + Null, + Attrs, + List, + Function, + External, +} +impl NixType { + fn from_int(c: c_uint) -> Self { + match c { + 0 => Self::Thunk, + 1 => Self::Int, + 2 => Self::Float, + 3 => Self::Bool, + 4 => Self::String, + 5 => Self::Path, + 6 => Self::Null, + 7 => Self::Attrs, + 8 => Self::List, + 9 => Self::Function, + 10 => Self::External, + _ => unreachable!("unknown nix type: {c}"), + } + } +} + +#[derive(Debug)] +#[repr(i32)] +enum NixErrorKind { + Unknown = 1, + Overflow = 2, + Key = 3, + Generic = 4, +} +impl NixErrorKind { + fn from_int(v: c_int) -> Option { + Some(match v { + 0 => return None, + -1 => Self::Unknown, + -2 => Self::Overflow, + -3 => Self::Key, + -4 => Self::Generic, + _ => { + debug_assert!(false, "unexpected nix error kind: {v}"); + Self::Unknown + } + }) + } +} + +pub fn gc_register_my_thread() { + assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 0); + + let mut sb = nix_raw::GC_stack_base { + mem_base: null_mut(), + }; + let r = unsafe { nix_raw::GC_get_stack_base(&mut sb) }; + if r as u32 != nix_raw::GC_SUCCESS { + panic!("failed to get thread stack base"); + } + unsafe { nix_raw::GC_register_my_thread(&sb) }; +} +pub fn gc_unregister_my_thread() { + assert_eq!(unsafe { nix_raw::GC_thread_is_registered() }, 1); + + unsafe { nix_raw::GC_unregister_my_thread() }; +} + +struct ThreadRegisterGuard {} +impl ThreadRegisterGuard { + fn new() -> Self { + gc_register_my_thread(); + Self {} + } +} +impl Drop for ThreadRegisterGuard { + fn drop(&mut self) { + gc_unregister_my_thread(); + } +} + +struct NixContext(*mut c_context); +impl NixContext { + fn set_err(&mut self, err: NixErrorKind, msg: &CStr) { + unsafe { set_err_msg(self.0, err as c_int, msg.as_ptr()) }; + } + fn new() -> Self { + let ctx = unsafe { c_context_create() }; + Self(ctx) + } + fn error_kind(&self) -> Option { + let code = unsafe { err_code(self.0) }; + NixErrorKind::from_int(code) + } + fn error<'t>(&self) -> Option> { + if let NixErrorKind::Generic = self.error_kind()? { + let mut err_out = String::new(); + unsafe { + err_info_msg( + null_mut(), + self.0, + Some(copy_nix_str), + (&raw mut err_out).cast(), + ) + }; + return Some(Cow::Owned(err_out)); + }; + + // TODO: Can throw error (resulting in panic) if unable to retrieve error. Should be able to resolve by passing context as a first argument, + // but it looks ugly + let str = unsafe { nix_raw::err_msg(null_mut(), self.0, null_mut()) }; + Some(unsafe { CStr::from_ptr(str) }.to_string_lossy()) + + // TODO: There is also nix_err_info_msg, but I don't understand when it should be used + // Some(match self.error_kind()? { + // NixErrorKind::Generic => { + // } + // }) + } + fn clean_err(&mut self) { + unsafe { + nix_raw::clear_err(self.0); + } + } + + fn bail_if_error(&self) -> Result<()> { + if let Some(err) = self.error() { + bail!("{err}"); + }; + Ok(()) + } + + fn run_in_context(&mut self, f: impl FnOnce(*mut c_context) -> T) -> Result { + self.clean_err(); + let o = f(self.0); + self.bail_if_error()?; + self.clean_err(); + Ok(o) + } +} +impl Drop for NixContext { + fn drop(&mut self) { + unsafe { + nix_raw::c_context_free(self.0); + } + } +} +struct GlobalState { + store: Store, + state: EvalState, +} +impl GlobalState { + fn new() -> Result { + let mut ctx = NixContext::new(); + let store = ctx + .run_in_context(|c| unsafe { nix_raw::store_open(c, c"daemon".as_ptr(), null_mut()) }) + .map(Store)?; + + let builder = ctx.run_in_context(|c| unsafe { eval_state_builder_new(c, store.0) })?; + ctx.run_in_context(|c| { + unsafe { + nix_raw::eval_state_builder_set_eval_setting( + c, + builder, + c"lazy-trees".as_ptr(), + c"true".as_ptr(), + ) + } + // eval_s + })?; + let state = ctx + .run_in_context(|c| unsafe { eval_state_build(c, builder) }) + .map(EvalState)?; + + Ok(Self { store, state }) + } +} + +struct ThreadState { + ctx: NixContext, +} +impl ThreadState { + fn new() -> Result { + let ctx = NixContext::new(); + + Ok(Self { ctx }) + } +} + +static GLOBAL_STATE: LazyLock = + LazyLock::new(|| GlobalState::new().expect("global state init shouldn't fail")); + +thread_local! { + static THREAD_STATE: RefCell = RefCell::new(ThreadState::new().expect("thread state init shouldn't fail")); +} +fn with_default_context( + f: impl FnOnce(*mut c_context, *mut nix_raw::EvalState) -> T, +) -> Result { + let global = &GLOBAL_STATE.state; + let (ctx, state) = THREAD_STATE.with_borrow_mut(|w| (w.ctx.0, global.0)); + let mut ctx = NixContext(ctx); + let v = ctx.run_in_context(|c| f(c, state)); + // It is reused for thread + std::mem::forget(ctx); + v +} + +fn set_setting(s: &CStr, v: &CStr) -> Result<()> { + with_default_context(|c, _| unsafe { setting_set(c, s.as_ptr(), v.as_ptr()) }).map(|_| ()) +} + +pub struct FetchSettings(*mut fetchers_settings); +impl FetchSettings { + pub fn new() -> Self { + Self::try_new().expect("allocation should not fail") + } + fn try_new() -> Result { + with_default_context(|c, _| unsafe { fetchers_settings_new(c) }).map(Self) + } + pub fn set(&mut self, setting: &CStr, value: &CStr) { + unsafe { + set_fetcher_setting(self.0.cast(), setting.as_ptr(), value.as_ptr()); + }; + } +} +unsafe impl Send for FetchSettings {} +unsafe impl Sync for FetchSettings {} +impl Drop for FetchSettings { + fn drop(&mut self) { + unsafe { fetchers_settings_free(self.0) }; + } +} +pub struct FlakeSettings(*mut flake_settings); +impl FlakeSettings { + pub fn new() -> Result { + with_default_context(|c, _| unsafe { flake_settings_new(c) }).map(Self) + } +} +unsafe impl Send for FlakeSettings {} +unsafe impl Sync for FlakeSettings {} +impl Drop for FlakeSettings { + fn drop(&mut self) { + unsafe { + flake_settings_free(self.0); + } + } +} + +struct FlakeReferenceParseFlags(*mut flake_reference_parse_flags); +impl FlakeReferenceParseFlags { + fn new(settings: &mut FlakeSettings) -> Result { + with_default_context(|c, _| unsafe { flake_reference_parse_flags_new(c, settings.0) }) + .map(Self) + } + fn set_base_dir(&mut self, dir: &str) -> Result<()> { + with_default_context(|c, _| { + unsafe { + flake_reference_parse_flags_set_base_directory( + c, + self.0, + dir.as_ptr().cast(), + dir.len(), + ) + }; + }) + } +} +impl Drop for FlakeReferenceParseFlags { + fn drop(&mut self) { + unsafe { + flake_reference_parse_flags_free(self.0); + } + } +} +struct FlakeLockFlags(*mut flake_lock_flags); +impl FlakeLockFlags { + fn new(settings: &mut FlakeSettings) -> Result { + with_default_context(|c, _| unsafe { flake_lock_flags_new(c, settings.0) }).map(Self) + } +} +impl Drop for FlakeLockFlags { + fn drop(&mut self) { + unsafe { + flake_lock_flags_free(self.0); + } + } +} + +unsafe extern "C" fn copy_nix_str(start: *const c_char, n: c_uint, user_data: *mut c_void) { + let s = unsafe { std::slice::from_raw_parts(start.cast::(), n as usize) }; + let s = std::str::from_utf8(s).expect("c string has invalid utf-8"); + unsafe { *user_data.cast::() = s.to_owned() }; +} + +struct Store(*mut nix_raw::Store); +unsafe impl Send for Store {} +unsafe impl Sync for Store {} + +struct EvalState(*mut nix_raw::EvalState); +impl EvalState { + // TODO: store ownership + fn new_raw(store: *mut nix_raw::Store) -> Result { + let builder = + with_default_context(|c, _| unsafe { nix_raw::eval_state_builder_new(c, store) })?; + + with_default_context(|c, _| unsafe { eval_state_build(c, builder) }).map(Self) + + // with_default_context(|c| state_create(c)) + } +} +unsafe impl Send for EvalState {} +unsafe impl Sync for EvalState {} +impl Drop for EvalState { + fn drop(&mut self) { + unsafe { + state_free(self.0); + } + } +} + +pub struct FlakeReference(*mut nix_raw::flake_reference); +impl FlakeReference { + pub fn new(s: &str, fetch: &FetchSettings) -> Result<(Self, String)> { + let mut flake_settings = FlakeSettings::new()?; + let mut parse_flags = FlakeReferenceParseFlags::new(&mut flake_settings)?; + + // parse_flags.set_base_dir("/home/lach/build/fleet")?; + + let mut out = null_mut(); + let mut fragment = String::new(); + // let fetch_settings = fetcher_settings; + with_default_context(|c, _| unsafe { + nix_raw::flake_reference_and_fragment_from_string( + c, + fetch.0, + flake_settings.0, + parse_flags.0, + s.as_ptr().cast(), + s.len(), + &mut out, + Some(copy_nix_str), + (&raw mut fragment).cast(), + ) + })?; + assert!(!out.is_null()); + + Ok((Self(out), fragment)) + } + pub fn lock(&mut self, fetch: &FetchSettings) -> Result { + let mut settings = FlakeSettings::new()?; + let lock_flags = FlakeLockFlags::new(&mut settings)?; + with_default_context(|c, es| unsafe { + flake_lock(c, fetch.0, settings.0, es, lock_flags.0, self.0) + }) + .map(LockedFlake) + } +} +unsafe impl Send for FlakeReference {} +unsafe impl Sync for FlakeReference {} + +pub struct LockedFlake(*mut nix_raw::locked_flake); +impl LockedFlake { + pub fn get_attrs(&self, settings: &mut FlakeSettings) -> Result { + with_default_context(|c, es| unsafe { + locked_flake_get_output_attrs(c, settings.0, es, self.0) + }) + .map(Value) + } +} +unsafe impl Send for LockedFlake {} +unsafe impl Sync for LockedFlake {} +impl Drop for LockedFlake { + fn drop(&mut self) { + unsafe { + locked_flake_free(self.0); + }; + } +} + +type FieldName = [u8; 32]; +fn init_field_name(v: &str) -> FieldName { + let mut f = [0; 32]; + assert!(v.len() < 32, "max field name is 31 char"); + assert!( + v.bytes().all(|v| v != 0), + "nul bytes are unsupported in field name" + ); + f[0..v.len()].copy_from_slice(v.as_bytes()); + f +} + +pub struct RealisedString(*mut nix_raw::realised_string); +impl fmt::Debug for RealisedString { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_str().fmt(f) + } +} + +impl RealisedString { + fn as_str(&self) -> &str { + let len = unsafe { nix_raw::realised_string_get_buffer_size(self.0) }; + let data: *const u8 = unsafe { nix_raw::realised_string_get_buffer_start(self.0) }.cast(); + let data = unsafe { std::slice::from_raw_parts(data, len) }; + std::str::from_utf8(data).expect("non-utf8 strings not supported") + } + fn path_count(&self) -> usize { + unsafe { nix_raw::realised_string_get_store_path_count(self.0) } + } + fn path(&self, i: usize) -> String { + assert!(i < self.path_count()); + let path = unsafe { nix_raw::realised_string_get_store_path(self.0, i) }; + let mut err_out = String::new(); + unsafe { nix_raw::store_path_name(path, Some(copy_nix_str), (&raw mut err_out).cast()) }; + err_out + } +} + +unsafe impl Send for RealisedString {} +impl Drop for RealisedString { + fn drop(&mut self) { + with_default_context(|c, _| unsafe { nix_raw::realised_string_free(self.0) }) + .expect("string free should not fail") + } +} -#[derive(Clone)] -pub struct NixSession(pub(crate) Arc>>); +pub struct Value(*mut nix_raw::value); -struct NixBuildTask(Value, oneshot::Sender>>); +unsafe impl Send for Value {} +unsafe impl Sync for Value {} -#[derive(Clone)] -pub struct NixBuildBatch { - tx: mpsc::UnboundedSender, +pub trait AsFieldName { + fn as_field_name(&self, v: impl FnOnce(FieldName) -> Result) -> Result; + fn to_field_name(&self) -> Result; +} +impl AsFieldName for Value { + fn as_field_name(&self, v: impl FnOnce(FieldName) -> Result) -> Result { + let f = self.to_string()?; + v(init_field_name(&f)) + } + fn to_field_name(&self) -> Result { + self.to_string() + } +} +impl AsFieldName for E +where + E: AsRef, +{ + fn as_field_name(&self, v: impl FnOnce(FieldName) -> Result) -> Result { + let f = self.as_ref(); + v(init_field_name(f)) + } + fn to_field_name(&self) -> Result { + Ok(self.as_ref().to_owned()) + } } -#[instrument(skip(session, values))] -async fn build_multiple(name: String, session: NixSession, values: Vec) -> Result<()> { - let system = session.0.lock().await.nix_system.clone(); - let builtins = Value::binding(session, "builtins").await?; - let drv = nix_go!(builtins.derivation(Obj { - system, - name, - builder: "/bin/sh", - // we want nothing from this derivation, it is only used to perform multiple builds at once. - args: vec!["-c", "echo > $out"], - preferLocalBuild: true, - allowSubstitutes: false, - buildInputs: values, - })); - drv.build().await?; - Ok(()) +struct AttrsBuilder(*mut nix_raw::BindingsBuilder); +impl AttrsBuilder { + fn new(capacity: usize) -> Self { + with_default_context(|c, es| unsafe { nix_raw::make_bindings_builder(c, es, capacity) }) + .map(Self) + .expect("alloc should not fail") + } + fn insert(&mut self, k: &impl AsFieldName, v: Value) { + k.as_field_name(|name| { + with_default_context(|c, _| unsafe { + nix_raw::bindings_builder_insert(c, self.0, name.as_ptr().cast(), v.0) + }) + }) + .expect("builder insert shouldn't fail"); + } } +impl Drop for AttrsBuilder { + fn drop(&mut self) { + unsafe { nix_raw::bindings_builder_free(self.0) }; + } +} + +impl Value { + pub fn new_attrs(v: HashMap<&str, Value>) -> Result { + let out = Self::new_uninit()?; + let mut b = AttrsBuilder::new(v.len()); + for (k, v) in v { + b.insert(&k, v); + } + with_default_context(|c, _| unsafe { nix_raw::make_attrs(c, out.0, b.0) })?; + Ok(out) + } + fn new_list>(v: Vec) -> Result { + todo!() + } + fn new_uninit() -> Result { + let out = with_default_context(|c, es| unsafe { alloc_value(c, es) })?; + Ok(Self(out)) + } + fn new_str(v: &str) -> Result { + let s = CString::new(v).expect("string should not contain NULs"); + let uninit = Self::new_uninit()?; + // String is copied, `s` is free to be dropped + with_default_context(|c, _| unsafe { init_string(c, uninit.0, s.as_ptr()) })?; + Ok(uninit) + } + fn new_int(i: i64) -> Result { + let uninit = Self::new_uninit()?; + with_default_context(|c, _| unsafe { init_int(c, uninit.0, i) })?; + Ok(uninit) + } + fn new_bool(v: bool) -> Result { + let uninit = Self::new_uninit()?; + with_default_context(|c, _| unsafe { init_bool(c, uninit.0, v) })?; + Ok(uninit) + } + fn force(&mut self, st: &mut EvalState) -> Result<()> { + with_default_context(|c, _| unsafe { value_force(c, st.0, self.0) })?; + Ok(()) + } + pub fn type_of(&self) -> Result { + let ty = with_default_context(|c, _| unsafe { nix_raw::get_type(c, self.0) })?; + Ok(NixType::from_int(ty)) + } + pub fn to_string(&self) -> Result { + Ok(self.to_realised_string()?.as_str().to_owned()) + } + pub fn to_realised_string(&self) -> Result { + with_default_context(|c, es| unsafe { nix_raw::string_realise(c, es, self.0, false) }) + .map(RealisedString) + + // let store_paths = unsafe { nix_raw::realised_string_get_store_path_count(str) }; + // for i in 0..store_paths { + // let store_path = unsafe { nix_raw::realised_string_get_store_path(str, i) }; + // nix_raw::store_path_name(store_path, callback, user_data); + // } + // dbg!(store_paths); + // todo!(); + } + + pub fn has_field(&self, field: &str) -> Result { + let f = init_field_name(field); + with_default_context(|c, es| unsafe { + nix_raw::has_attr_byname(c, self.0, es, f.as_ptr().cast()) + }) + } + // pub fn derivation_path(&self) { + // nix_raw::real + // } + pub fn list_fields(&self) -> Result> { + if !matches!(self.type_of()?, NixType::Attrs) { + bail!("invalid type: expected attrs"); + } -impl NixBuildBatch { - fn new(name: String, session: NixSession) -> Self { - let (tx, mut rx) = mpsc::unbounded_channel::(); + let len = with_default_context(|c, _| unsafe { nix_raw::get_attrs_size(c, self.0) })?; + let mut out = Vec::with_capacity(len as usize); - tokio::task::spawn(async move { - let mut deps = vec![]; - let mut build_data = vec![]; - while let Some(task) = rx.recv().await { - build_data.push(task.0.clone()); - deps.push(task); + for i in 0..len { + let name = with_default_context(|c, es| unsafe { + nix_raw::get_attr_name_byidx(c, self.0, es, i) + })?; + let c = unsafe { CStr::from_ptr(name) }; + out.push(c.to_str().expect("nix field names are utf-8").to_owned()); + } + Ok(out) + } + pub fn get_elem(&self, v: usize) -> Result { + if !matches!(self.type_of()?, NixType::List) { + bail!("invalid type: expected list"); + } + let len = + with_default_context(|c, _| unsafe { nix_raw::get_list_size(c, self.0) })? as usize; + if v >= len { + bail!("oob list get: {v} >= {len}"); + } + + with_default_context(|c, es| unsafe { nix_raw::get_list_byidx(c, self.0, es, v as u32) }) + .map(Self) + } + pub fn attrs_update(self, other: Value) -> Result { + let a_fields = self.list_fields()?; + let b_fields = other.list_fields()?; + match (a_fields.len(), b_fields.len()) { + (_, 0) => return Ok(self), + (0, _) => return Ok(other), + _ => {} + } + let mut out = HashMap::new(); + for f in a_fields.iter() { + if b_fields.contains(f) { + break; } - if deps.is_empty() { - return; + out.insert(f.as_str(), self.get_field(f)?); + } + if out.is_empty() { + // All fields from lhs are overriden by rhs + return Ok(other); + } + for f in b_fields.iter() { + out.insert(f.as_str(), other.get_field(f)?); + } + Self::new_attrs(out) + } + pub fn get_field(&self, name: impl AsFieldName) -> Result { + if !matches!(self.type_of()?, NixType::Attrs) { + bail!("invalid type: expected attrs"); + } + + name.as_field_name(|name| { + with_default_context(|c, es| unsafe { + nix_raw::get_attr_byname(c, self.0, es, name.as_ptr().cast()) + }) + .map(Self) + }) + .with_context(|| format!("getting field {:?}", name.to_field_name())) + } + pub fn call(&self, v: Value) -> Result { + if !matches!(self.type_of()?, NixType::Function) { + // TODO: Functors + bail!("invalid type: expected function"); + } + + let out = Value::new_uninit()?; + with_default_context(|c, es| unsafe { nix_raw::value_call(c, es, self.0, v.0, out.0) })?; + + Ok(out) + } + pub fn eval(v: &str) -> Result { + let s = CString::new(v).expect("expression shouldn't have internal NULs"); + let out = Self::new_uninit()?; + with_default_context(|c, es| unsafe { + expr_eval_from_string(c, es, s.as_ptr(), c"/homeless-shelter".as_ptr(), out.0) + })?; + Ok(out) + } + pub async fn build(&self, output: &str) -> Result { + if !self.is_derivation() { + bail!("expected derivation to build") + } + let output_name = self.get_field("outputName")?.to_string()?; + let v = if output_name != output { + let out = self.get_field(output)?; + if !out.is_derivation() { + bail!("unknown output: {output}"); } - match build_multiple(name, session, build_data).await { - Ok(_) => { - for NixBuildTask(v, o) in deps { - let _ = o.send(v.build().await); - } - } - Err(e) => { - for NixBuildTask(v, o) in deps { - let s = v.to_string_weak().await; - let s = match s { - Ok(s) => s, - Err(e) => { - let _ = o.send(Err(e)); - continue; - } - }; - if PathBuf::from(s).exists() { - let _ = o.send(v.build().await); - } else { - let _ = o.send(Err(e.clone())); - } - } - } - }; - }); - Self { tx } + out + } else { + self.clone() + }; + // to_string here blocks until the path is built + let drv_path = tokio::task::spawn_blocking(move || v.get_field("outPath")?.to_string()) + .await + .expect("should not fail")?; + Ok(PathBuf::from(drv_path)) } - pub async fn submit(self, task: Value) -> Result> { - let Self { tx: task_tx } = self; - let (tx, rx) = oneshot::channel(); - let _ = task_tx.send(NixBuildTask(task, tx)); - drop(task_tx); - rx.await.expect("shoudn't be cancelled here") + pub fn as_json(&self) -> Result { + let to_json = Self::eval("builtins.toJSON")?; + let s = to_json.call(self.clone())?.to_string()?; + Ok(serde_json::from_str(&s)?) + } + pub fn serialized(v: &T) -> Result { + Self::eval(&nixlike::serialize(v)?) + } + + // Convert to string/evaluate derivations/etc + fn to_string_weak(&self) -> Result { + // TODO + self.to_string() + } + + fn is_derivation(&self) -> bool { + if !matches!(self.type_of(), Ok(NixType::Attrs)) { + return false; + } + let Some(ty) = self.get_field("type").ok() else { + return false; + }; + matches!(ty.to_string().as_deref(), Ok("derivation")) } } -impl NixSession { - fn ptr_eq(a: &Self, b: &Self) -> bool { - Arc::ptr_eq(&a.0, &b.0) +impl From for Value { + fn from(value: String) -> Self { + Value::new_str(&value).expect("todo: TryFrom") } +} +impl From for Value { + fn from(value: bool) -> Self { + Value::new_bool(value).expect("todo: TryFrom") + } +} +impl From<&str> for Value { + fn from(value: &str) -> Self { + Value::new_str(&value).expect("todo: TryFrom") + } +} +impl From> for Value +where + T: Into, +{ + fn from(value: Vec) -> Self { + Value::new_list(value).expect("todo: TryFrom") + } +} - pub fn new_build_batch(&self, name: String) -> NixBuildBatch { - NixBuildBatch::new(name, self.clone()) +impl Clone for Value { + fn clone(&self) -> Self { + with_default_context(|c, _| unsafe { value_incref(c, self.0) }) + .expect("value incref should not fail"); + Self(self.0) } } +impl Drop for Value { + fn drop(&mut self) { + with_default_context(|c, _| unsafe { value_decref(c, self.0) }) + .expect("value drop should not fail"); + } +} + +pub fn init_libraries() { + unsafe { nix_raw::GC_allow_register_threads() }; -pub fn init_tokio() { - let _ = pool::TOKIO_RUNTIME.set(tokio::runtime::Handle::current()); + let mut ctx = NixContext::new(); + ctx.run_in_context(|c| unsafe { nix_raw::libutil_init(c) }) + .expect("util init should not fail"); + ctx.run_in_context(|c| unsafe { nix_raw::libstore_init(c) }) + .expect("store init should not fail"); + ctx.run_in_context(|c| unsafe { nix_raw::libexpr_init(c) }) + .expect("expr init should not fail"); + + nix_logging_cxx::apply_tracing_logger(); } + +#[test_log::test] +fn test_native() -> Result<()> { + let mut fetch_settings = FetchSettings::new(); + fetch_settings.set(c"warn-dirty", c"false"); + // + + let (mut r, _) = FlakeReference::new("/home/lach/build/fleet", &fetch_settings)?; + let locked = r.lock(&fetch_settings)?; + let attrs = locked.get_attrs(&mut FlakeSettings::new()?)?; + + let builtins = Value::eval("builtins")?; + dbg!(builtins.type_of()?); + + dbg!(attrs.type_of()?); + dbg!(attrs.list_fields()?); + dbg!( + attrs + .get_field("packages")? + .get_field("x86_64-linux")? + .get_field("fleet")? + .get_field("outPath")? + .to_string() + ); + + Ok(()) +} + +// struct NixBuildTask(Value, oneshot::Sender>>); +// +// #[derive(Clone)] +// pub struct NixBuildBatch { +// tx: mpsc::UnboundedSender, +// } +// +// #[instrument(skip(values))] +// async fn build_multiple(name: String, values: Vec) -> Result<()> { +// let builtins = Value::eval("builtins")?; +// let drv = nix_go!(builtins.derivation(Obj { +// // FIXME: pass system from localSystem or fleet args +// // system, +// name, +// builder: "/bin/sh", +// // we want nothing from this derivation, it is only used to perform multiple builds at once. +// args: vec!["-c", "echo > $out"], +// preferLocalBuild: true, +// allowSubstitutes: false, +// buildInputs: values, +// })); +// drv.build()?; +// Ok(()) +// } +// +// impl NixBuildBatch { +// fn new(name: String) -> Self { +// let (tx, mut rx) = mpsc::unbounded_channel::(); +// +// tokio::task::spawn(async move { +// let mut deps = vec![]; +// let mut build_data = vec![]; +// while let Some(task) = rx.recv().await { +// build_data.push(task.0.clone()); +// deps.push(task); +// } +// if deps.is_empty() { +// return; +// } +// match build_multiple(name, build_data).await { +// Ok(_) => { +// for NixBuildTask(v, o) in deps { +// let _ = o.send(v.build()); +// } +// } +// Err(e) => { +// for NixBuildTask(v, o) in deps { +// let s = v.to_string_weak(); +// let s = match s { +// Ok(s) => s, +// Err(e) => { +// let _ = o.send(Err(e)); +// continue; +// } +// }; +// if PathBuf::from(s).exists() { +// let _ = o.send(v.build()); +// } else { +// let _ = o.send(Err(e.clone())); +// } +// } +// } +// }; +// }); +// Self { tx } +// } +// pub async fn submit(self, task: Value) -> Result> { +// let Self { tx: task_tx } = self; +// let (tx, rx) = oneshot::channel(); +// let _ = task_tx.send(NixBuildTask(task, tx)); +// drop(task_tx); +// rx.await.expect("shoudn't be cancelled here") +// } +// } --- /dev/null +++ b/crates/nix-eval/src/logging.cc @@ -0,0 +1,75 @@ +#include "nix-eval/src/logging.rs" +#include "logging.hh" +#include + +using namespace nix; + +struct TracingLogger : Logger { + TracingLogger() {} + + bool isVerbose() override { return true; } + // void addFields(nlohmann::json & json, const Fields & fields) + // { + // if (fields.empty()) + // return; + // auto & arr = json["fields"] = nlohmann::json::array(); + // for (auto & f : fields) + // if (f.type == Logger::Field::tInt) + // arr.push_back(f.i); + // else if (f.type == Logger::Field::tString) + // arr.push_back(f.s); + // else + // unreachable(); + // } + void log(Verbosity lvl, std::string_view s) override { + rust::Str str(s.data(), s.size()); + emit_log(lvl, str); + } + void logEI(const ErrorInfo &ei) override { emit_log(ei.level, ei.msg.str()); } + + void startActivity(ActivityId act, Verbosity lvl, ActivityType type, + const std::string &s, const Fields &fields, + ActivityId parent) override { + auto b = new_start_activity(act, lvl, type); + for (auto &f : fields) { + if (f.type == Logger::Field::tInt) { + b->add_int_field(f.i); + } else if (f.type == Logger::Field::tString) { + b->add_string_field(f.s); + } else { + unreachable(); + } + } + b->emit(parent, s); + }; + + void stopActivity(ActivityId act) override { emit_stop(act); }; + + void result(ActivityId act, ResultType type, const Fields &fields) override { + auto b = new_start_activity(act, 0, type); + for (auto &f : fields) { + if (f.type == Logger::Field::tInt) { + b->add_int_field(f.i); + } else if (f.type == Logger::Field::tString) { + b->add_string_field(f.s); + } else { + unreachable(); + } + } + b->emit_result(type); + }; + + void writeToStdout(std::string_view s) override { + printf("writeToStdout() called\n"); + } + void warn(const std::string &msg) override { emit_warn(msg); } + + virtual std::optional ask(std::string_view s) { + printf("ask() called\n"); + return {}; + } +}; + +extern "C" { +void apply_tracing_logger() { logger = std::make_unique(); } +} --- /dev/null +++ b/crates/nix-eval/src/logging.hh @@ -0,0 +1,5 @@ +#pragma once + +extern "C" { +void apply_tracing_logger(); +} --- /dev/null +++ b/crates/nix-eval/src/logging.rs @@ -0,0 +1,602 @@ +use std::collections::HashMap; +use std::fmt::Arguments; +use std::sync::{LazyLock, Mutex}; + +use tracing::{ + Level, Metadata, Span, debug, debug_span, error, error_span, event, info, info_span, trace, + trace_span, warn, warn_span, +}; +use tracing_indicatif::span_ext::IndicatifSpanExt as _; + +#[derive(Debug)] +enum ActivityType { + Unknown = 0, + CopyPath = 100, + FileTransfer = 101, + Realise = 102, + CopyPaths = 103, + Builds = 104, + Build = 105, + OptimiseStore = 106, + VerifyPaths = 107, + Substitute = 108, + QueryPathInfo = 109, + PostBuildHook = 110, + BuildWaiting = 111, + FetchTree = 112, +} + +fn strip_prefix_suffix<'s, 'p>(a: &'s str, pref: &'p str, suff: &'p str) -> Option<&'s str> { + a.strip_prefix(pref)?.strip_suffix(suff) +} + +fn parse_path(path: &str) -> &str { + let path = strip_prefix_suffix(path, "\x1b[35;1m", "\x1b[0m").unwrap_or(path); + path +} + +fn parse_drv(drv: &str) -> &str { + let drv = parse_path(drv); + if let Some(pkg) = drv.strip_prefix("/nix/store/") { + let mut it = pkg.splitn(2, '-'); + it.next(); + if let Some(pkg) = it.next() { + return pkg; + } + } + drv +} +fn parse_host(host: &str) -> &str { + if host.is_empty() || host == "local" { + return "local"; + } + // https/ssh is the default + host.strip_prefix("https://").unwrap_or(host) +} + +impl ActivityType { + fn name(&self) -> &'static str { + match self { + ActivityType::Unknown => "nix", + ActivityType::CopyPath => "nix::copy-path", + ActivityType::FileTransfer => "nix::file-transfer", + ActivityType::Realise => "nix::realise", + ActivityType::CopyPaths => "nix::copy-paths", + ActivityType::Builds => "nix::builds", + ActivityType::Build => "nix::build", + ActivityType::OptimiseStore => "nix::optimise-store", + ActivityType::VerifyPaths => "nix::verify-paths", + ActivityType::Substitute => "nix::substitute", + ActivityType::QueryPathInfo => "nix::query-path-info", + ActivityType::PostBuildHook => "nix::post-build-hook", + ActivityType::BuildWaiting => "nix::build-waiting", + ActivityType::FetchTree => "nix::fetch-tree", + } + } + fn format( + &self, + values: &[FieldValue], + s: &str, + into: impl FnOnce(Arguments<'_>) -> Span, + ) -> Span { + use FieldValue::*; + match (self, values) { + (ActivityType::QueryPathInfo, [Str(drv), Str(host)]) => { + let drv = parse_drv(drv); + let host = parse_host(host); + debug_span!(target: "nix::query-path-info", "querying", drv, host) + } + (ActivityType::Substitute, [Str(drv), Str(host)]) => { + let drv = parse_drv(drv); + let host = parse_host(host); + debug_span!(target: "nix::substitute", "substituting", drv, host) + } + (ActivityType::CopyPath, [Str(drv), Str(from), Str(to)]) => { + let drv = parse_drv(drv); + let from = parse_host(from); + let to = parse_host(to); + debug_span!(target: "nix::copy-path", "copying", drv, from, to) + } + (ActivityType::Build, [Str(drv), Str(host), Int(_), Int(_)]) => { + let drv = parse_drv(drv); + let host = parse_host(host); + info_span!(target: "nix::build", "building", drv, host) + } + (ActivityType::FileTransfer, [Str(file)]) => { + info_span!(target: "nix::file-transfer", "downloading", file) + } + (ActivityType::Realise, []) => { + debug_span!(target: "nix::realise", "realising") + } + (ActivityType::CopyPaths, []) => { + debug_span!(target: "nix::copy-paths", "copying paths") + } + (ActivityType::Unknown, []) + if s.starts_with("copying \"") && s.ends_with("\" to the store") => + { + let tree = s + .trim_start_matches("copying \"") + .trim_end_matches("\" to the store"); + debug_span!(target: "nix::trees", "copying", tree) + } + (ActivityType::Unknown, []) + if s.starts_with("copying '") && s.ends_with("' to the store") => + { + let tree = s + .trim_start_matches("copying '") + .trim_end_matches("' to the store"); + debug_span!(target: "nix::trees", "copying", tree) + } + (ActivityType::Unknown, []) if s.starts_with("hashing '") && s.ends_with("'") => { + let tree = s.trim_start_matches("hashing '").trim_end_matches("'"); + debug_span!(target: "nix::trees", "hashing", tree) + } + (ActivityType::Unknown, []) if s.starts_with("connecting to '") && s.ends_with("'") => { + let host = s + .trim_start_matches("connecting to '") + .trim_end_matches("'"); + debug_span!(target: "nix::remote", "connecting", host) + } + (ActivityType::Unknown, []) + if s.starts_with("copying outputs from '") && s.ends_with("'") => + { + let host = s + .trim_start_matches("copying outputs from '") + .trim_end_matches("'"); + debug_span!(target: "nix::remote", "copying outputs", host) + } + (ActivityType::Unknown, []) + if s.starts_with("copying dependencies to '") && s.ends_with("'") => + { + let host = s + .trim_start_matches("copying dependencies to '") + .trim_end_matches("'"); + debug_span!(target: "nix::remote", "copying dependencies", host) + } + (ActivityType::Unknown, []) + if s.starts_with("waiting for the upload lock to '") && s.ends_with("'") => + { + let host = s + .trim_start_matches("waiting for the upload lock to '") + .trim_end_matches("'"); + debug_span!(target: "nix::remote", "waiting for upload lock", host) + } + (ActivityType::BuildWaiting, []) + if s.starts_with("waiting for a machine to build '") && s.ends_with("'") => + { + let drv = parse_drv( + s.trim_start_matches("waiting for a machine to build '") + .trim_end_matches("'"), + ); + debug_span!(target: "nix::build-waiting", "waiting for available builder", drv) + } + (ActivityType::Unknown, []) if s == "querying info about missing paths" => { + debug_span!(target: "nix::remote", "querying") + } + _ => into(format_args!("{}({values:?})", self.name())), + } + } + fn from_int(v: u32) -> Self { + match v { + 0 => Self::Unknown, + 100 => Self::CopyPath, + 101 => Self::FileTransfer, + 102 => Self::Realise, + 103 => Self::CopyPaths, + 104 => Self::Builds, + 105 => Self::Build, + 106 => Self::OptimiseStore, + 107 => Self::VerifyPaths, + 108 => Self::Substitute, + 109 => Self::QueryPathInfo, + 110 => Self::PostBuildHook, + 111 => Self::BuildWaiting, + 112 => Self::FetchTree, + _ => { + warn!("unknown nix action: {v}"); + Self::Unknown + } + } + } +} + +#[derive(Debug)] +enum ResultType { + FileLinked = 100, + BuildLogLine = 101, + UntrustedPath = 102, + CorruptedPath = 103, + SetPhase = 104, + Progress = 105, + SetExpected = 106, + PostBuildLogLine = 107, + FetchStatus = 108, + + Unknown = 999, +} +impl ResultType { + fn from_int(v: u32) -> Self { + match v { + 100 => Self::FileLinked, + 101 => Self::BuildLogLine, + 102 => Self::UntrustedPath, + 103 => Self::CorruptedPath, + 104 => Self::SetPhase, + 105 => Self::Progress, + 106 => Self::SetExpected, + 107 => Self::PostBuildLogLine, + 108 => Self::FetchStatus, + + _ => { + warn!("unknown nix result: {v}"); + Self::Unknown + } + } + } +} +#[derive(Clone, Copy)] +enum Verbosity { + Error, + Warn, + Notice, + Info, + Talkative, + Chatty, + Debug, + Vomit, +} +impl Into for Verbosity { + fn into(self) -> tracing::Level { + match self { + Verbosity::Error => Level::ERROR, + Verbosity::Warn => Level::WARN, + Verbosity::Notice => Level::WARN, + Verbosity::Info => Level::INFO, + Verbosity::Talkative => Level::DEBUG, + Verbosity::Chatty => Level::DEBUG, + Verbosity::Debug => Level::DEBUG, + Verbosity::Vomit => Level::TRACE, + } + } +} +impl Verbosity { + fn from_int(u: u32) -> Self { + [ + Self::Error, + Self::Warn, + Self::Notice, + Self::Info, + Self::Talkative, + Self::Chatty, + Self::Debug, + Self::Vomit, + ] + .get(u as usize) + .cloned() + .unwrap_or_else(|| { + warn!("unknown log level: {u}"); + Verbosity::Vomit + }) + } +} + +#[derive(Hash, PartialEq, Eq, Clone, Copy)] +enum MetadataKind { + Span, + Event, +} +// impl MetadataKind { +// fn kind(&self) -> Kind { +// match self { +// MetadataKind::Span => Kind::SPAN, +// MetadataKind::Event => Kind::EVENT, +// } +// } +// } + +#[derive(Hash, PartialEq, Eq)] +struct ForeignMetadataInfo { + target: &'static str, + level: Level, + kind: MetadataKind, + name: &'static str, + module: Option<&'static str>, + file: Option<&'static str>, + line: Option, + names: &'static [&'static str], +} + +struct FakeCallsite; +impl tracing::callsite::Callsite for FakeCallsite { + fn set_interest(&self, interest: tracing::subscriber::Interest) { + unreachable!() + } + + fn metadata(&self) -> &Metadata<'_> { + unreachable!() + } +} +const FAKE_CALLSITE: FakeCallsite = FakeCallsite; + +#[cfg(false)] +#[derive(Default)] +struct ForeignSpanData { + interned: HashSet<&'static str>, + metadatas: HashMap>, +} +#[cfg(false)] +impl ForeignSpanData { + fn intern(&mut self, s: &str) -> &'static str { + if let Some(v) = self.interned.get(s) { + return *v; + } + let leaked: Box = s.into(); + let leaked = Box::leak(leaked); + self.interned.insert(leaked); + return leaked; + } + fn alloc_metadata<'t>( + &'t mut self, + target: &'static str, + level: Level, + kind: MetadataKind, + name: &'static str, + module: Option<&'static str>, + file: Option<&'static str>, + line: Option, + names: &'static [&'static str], + ) -> &'static Metadata<'static> { + let info = ForeignMetadataInfo { + target, + level, + kind, + name, + module, + file, + line, + names, + }; + if let Some(v) = self.metadatas.get(&info) { + return *v; + } + let fake = FakeCallsite; + let metadata = Box::leak::<'static>(Box::new(Metadata::new( + name, + target, + level, + file, + line, + module, + FieldSet::new(names, tracing::callsite::Identifier(&FAKE_CALLSITE)), + kind.kind(), + ))); + + let meta_raw = &raw const *metadata; + let fields_raw = &raw const *metadata.fields(); + + // SAFETY: FieldSet struct should be inside of metadata struct... Which we assume here, but do not test + // FIXME: Safety comment above might be invalidated at any time, this should actually be covered by unit test (or, better: runtime assertion... Somehow.) + let fields_offset = unsafe { fields_raw.cast::().offset_from(meta_raw.cast()) }; + let field_set = unsafe { + ((&raw mut *metadata).cast::<()>()) + .byte_offset(fields_offset) + .cast::
() + }; + // FIXME: metadata borrow here invalidates our &mut borrow of 'static Metadata, and 'static FieldSet so this construction should be replaced with raw pointers or idk. + // Something should be better done inside of tracing crate itself, someting like interior mutability. + let callsite = Box::leak(Box::new(tracing::callsite::DefaultCallsite::new(metadata))); + unsafe { *field_set = FieldSet::new(names, tracing::callsite::Identifier(callsite)) }; + + tracing::callsite::register(&*callsite); + + self.metadatas.insert(info, metadata); + return metadata; + } +} + +#[cfg(false)] +static FOREIGN_SPAN_DATA: LazyLock> = + LazyLock::new(|| Mutex::new(ForeignSpanData::default())); +static NIX_SPAN_MAPPING: LazyLock>> = + LazyLock::new(|| Mutex::new(HashMap::new())); + +#[derive(Debug)] +enum FieldValue { + Int(i32), + Str(String), +} + +struct StartActivityBuilder { + activity_id: u64, + verbosity: Verbosity, + typ: ActivityType, + fields: Vec, +} +impl StartActivityBuilder { + fn add_int_field(&mut self, i: i32) { + self.fields.push(FieldValue::Int(i)); + } + fn add_string_field(&mut self, v: &str) { + self.fields.push(FieldValue::Str(v.to_owned())); + } + fn emit(&mut self, parent: u64, s: &str) { + let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned"); + + let parent = mapping.get(&parent); + + // let meta = spans.alloc_metadata( + // self.typ.name(), + // self.verbosity.into(), + // MetadataKind::Span, + // "nix activity start", + // None, + // None, + // None, + // self.typ.fields(), + // ); + // + // let mut fields = meta.fields().iter(); + // let span = if let Some(parent) = parent { + // let s = Span::new( + // meta, + // &match meta.fields().len() { + // 1 => meta.fields().value_set( + // &<[_; 1]>::try_from([( + // &fields.next().expect("has field"), + // Some(&format_args!("Test") as &dyn tracing::Value), + // )]) + // .expect("valid size"), + // ), + // _ => unreachable!(), + // }, + // ); + // s.follows_from(parent); + // s + // } else { + // Span::new_root( + // meta, + // &match meta.fields().len() { + // 1 => meta.fields().value_set( + // &<[_; 1]>::try_from([( + // &fields.next().expect("has field"), + // Some(&format_args!("Test") as &dyn tracing::Value), + // )]) + // .expect("valid size"), + // ), + // _ => unreachable!(), + // }, + // ) + // }; + // + // let id = span.id().expect("id created"); + + let span = { + let _in_parent = parent.map(|p| p.enter()); + let level: Level = self.verbosity.into(); + if level == Level::ERROR { + self.typ + .format(&self.fields, s, |v| error_span!("action", v)) + } else if level == Level::WARN { + self.typ + .format(&self.fields, s, |v| warn_span!("action", v)) + } else if level == Level::INFO { + self.typ + .format(&self.fields, s, |v| info_span!("action", v)) + } else if level == Level::DEBUG { + self.typ + .format(&self.fields, s, |v| debug_span!("action", v)) + } else { + self.typ + .format(&self.fields, s, |v| trace_span!("action", v)) + } + }; + if !s.trim().is_empty() { + span.pb_set_message(s); + let _e = span.enter(); + let level: Level = self.verbosity.into(); + if level == Level::ERROR { + error!(target: "nix", "{}", s) + } else if level == Level::WARN { + warn!(target: "nix", "{}", s) + } else if level == Level::INFO { + info!(target: "nix", "{}", s) + } else if level == Level::DEBUG { + debug!(target: "nix", "{}", s) + } else { + trace!(target: "nix", "{}", s) + } + } else { + span.pb_start(); + } + mapping.insert(self.activity_id, span); + } + fn emit_result(&mut self, ty: u32) { + let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned"); + + let Some(parent) = mapping.get(&self.activity_id) else { + panic!("unexpected result for dead parent"); + }; + + let _in_parent = parent.enter(); + let res = ResultType::from_int(ty); + + use FieldValue::*; + match (&res, self.fields.as_slice()) { + // ResultType::FileLinked => todo!(), + (ResultType::BuildLogLine, [Str(s)]) => { + info!("{s:?}"); + } + // ResultType::UntrustedPath => todo!(), + // ResultType::CorruptedPath => todo!(), + // ResultType::SetPhase => todo!(), + (ResultType::SetExpected, [Int(act_ty), Int(_expected)]) => { + let _act_ty = ActivityType::from_int(*act_ty as u32); + } + (ResultType::SetPhase, [Str(phase)]) => { + // parent.pb_set_message(phase); + debug!(target: "nix::phase", phase) + } + (ResultType::Progress, [Int(done), Int(expected), Int(_), Int(_)]) => { + parent.pb_set_length(*expected as u64); + parent.pb_set_position(*done as u64); + } + _ => warn!("unknown progress report: {:?}({:?})", &res, &self.fields), + } + } +} +fn new_start_activity(activity_id: u64, lvl: u32, typ: u32) -> Box { + Box::new(StartActivityBuilder { + activity_id, + verbosity: Verbosity::from_int(lvl), + typ: ActivityType::from_int(typ), + fields: vec![], + }) +} + +fn emit_warn(v: &str) { + warn!(target: "nix::eval", "{v}") +} +fn emit_stop(v: u64) { + let mut mapping = NIX_SPAN_MAPPING.lock().expect("not poisoned"); + mapping.remove(&v); +} +fn emit_log(lvl: u32, v: &str) { + let verbosity = Verbosity::from_int(lvl); + let level: Level = verbosity.into(); + if level == Level::ERROR { + error!(target: "nix", "{v}") + } else if level == Level::WARN { + warn!(target: "nix", "{v}") + } else if level == Level::INFO { + info!(target: "nix", "{v}") + } else if level == Level::DEBUG { + debug!(target: "nix", "{v}") + } else { + trace!(target: "nix", "{v}") + } +} + +// fn start_activity(act: u64, lvl: u32, act_ty: u32, s: &str, parent: u32) { +// tracing::Span::new(meta, values) +// } + +#[cxx::bridge] +pub mod nix_logging_cxx { + extern "Rust" { + type StartActivityBuilder; + fn new_start_activity(activity_id: u64, lvl: u32, typ: u32) -> Box; + fn add_int_field(&mut self, i: i32); + fn add_string_field(&mut self, v: &str); + fn emit(&mut self, parent: u64, s: &str); + fn emit_result(&mut self, ty: u32); + + fn emit_warn(v: &str); + fn emit_stop(id: u64); + fn emit_log(lvl: u32, v: &str); + } + unsafe extern "C++" { + include!("nix-eval/src/logging.hh"); + + fn apply_tracing_logger(); + } +} --- a/crates/nix-eval/src/macros.rs +++ b/crates/nix-eval/src/macros.rs @@ -1,171 +1,26 @@ -use serde::Serialize; - -use crate::{NixSession, Value}; - -#[derive(Clone)] -pub struct NixExprBuilder { - pub(crate) out: String, - used_fields: Vec, -} -pub trait AttrSetValue { - fn to_builder(self) -> NixExprBuilder; -} -trait Primitive {} - -macro_rules! impl_primitive { - ($($t:ty),+) => { - $( - impl Primitive for $t {} - )+ - }; -} -impl_primitive!(String, bool, &'static str); - -impl AttrSetValue for T -where - // Limited by Primitive trait to avoid orphan rules violation with Vec - T: Serialize + Primitive, -{ - fn to_builder(self) -> NixExprBuilder { - let serialized = nixlike::serialize(self).expect("invalid value for apply"); - NixExprBuilder { - out: serialized.trim_end().to_owned(), - used_fields: Vec::new(), - } - } -} -impl AttrSetValue for Value { - fn to_builder(self) -> NixExprBuilder { - NixExprBuilder { - out: format!("sess_field_{}", self.session_field_id()), - used_fields: vec![self], - } - } -} -impl AttrSetValue for Vec -where - T: AttrSetValue, -{ - fn to_builder(self) -> NixExprBuilder { - let mut builder = NixExprBuilder::list(); - for v in self { - builder.list_value(NixExprBuilder::attrset_value(v)); - } - builder.list_end(); - builder - } -} - -impl NixExprBuilder { - pub fn object() -> Self { - NixExprBuilder { - out: "{ ".to_owned(), - used_fields: Vec::new(), - } - } - pub fn list() -> Self { - NixExprBuilder { - out: "[".to_owned(), - used_fields: Vec::new(), - } - } - pub fn string(s: &str) -> Self { - NixExprBuilder { - out: nixlike::serialize(s) - .expect("no problems with serializing_string") - .trim_end() - .to_owned(), - used_fields: Vec::new(), - } - } - pub fn attrset_value(v: impl AttrSetValue) -> Self { - v.to_builder() - } - pub fn serialized(v: impl Serialize) -> Self { - let serialized = nixlike::serialize(v).expect("invalid value for apply"); - Self { - out: serialized.trim_end().to_owned(), - used_fields: Vec::new(), - } - } - pub fn value(f: Value) -> Self { - Self { - out: format!("sess_field_{}", f.session_field_id()), - used_fields: vec![f], - } - } - pub fn end_obj(&mut self) { - self.out.push('}'); - } - pub fn obj_key(&mut self, name: Self, value: Self) { - self.out.push_str(r#""${"#); - self.extend(name); - self.out.push_str(r#"}" = "#); - self.extend(value); - self.out.push_str("; "); - } - pub fn list_value(&mut self, value: Self) { - self.extend(value); - self.out.push(' '); - } - pub fn list_end(&mut self) { - self.out.push(']'); - } - - pub fn extend(&mut self, e: Self) { - self.out.push_str(&e.out); - self.used_fields.extend(e.used_fields); - } - - #[allow(dead_code)] - pub fn session(&self) -> NixSession { - let mut session = None; - for ele in &self.used_fields { - if session.is_none() { - session = Some(ele.session()); - continue; - } - let session = session.as_ref().expect("checked"); - let ele_sess = ele.session(); - assert!( - NixSession::ptr_eq(session, &ele_sess), - "can't mix fields from different session" - ); - } - session.expect("expr without fields used") - } - #[allow(dead_code)] - pub fn index_attr(&mut self, s: &str) { - let escaped = nixlike::serialize(s).expect("string"); - self.out.push('.'); - self.out.push_str(escaped.trim_end()); - } -} - #[macro_export] macro_rules! nix_expr_inner { //(@munch_object FIXME: value should be arbitrary nix_expr_inner input... Time to write proc-macro? (@obj($o:ident) $field:ident$(, $($tt:tt)*)?) => {{ - $o.obj_key( - NixExprBuilder::string(stringify!($field)), - NixExprBuilder::attrset_value($field), + $o.insert( + stringify!($field), + $crate::Value::from($field), ); $(nix_expr_inner!(@obj($o) $($tt)*);)? }}; (@obj($o:ident) $field:ident: $v:expr$(, $($tt:tt)*)?) => {{ - $o.obj_key( - NixExprBuilder::string(stringify!($field)), - NixExprBuilder::attrset_value($v), + $o.insert( + stringify!($field), + $crate::Value::from($v), ); $(nix_expr_inner!(@obj($o) $($tt)*);)? }}; (@obj($o:ident)) => {{}}; (Obj { $($tt:tt)* }) => {{ - use $crate::{macros::NixExprBuilder, nix_expr_inner}; - let mut out = NixExprBuilder::object(); + use $crate::{nix_expr_inner}; + let mut out = std::collections::hash_map::HashMap::new(); nix_expr_inner!(@obj(out) $($tt)*); - out.end_obj(); - out + Value::new_attrs(out)? }}; (@field($o:ident) . $var:ident $($tt:tt)*) => {{ $o.index_attr(stringify!($var)); @@ -185,10 +40,10 @@ }; (@field($o:ident)) => {}; ($field:ident $($tt:tt)*) => {{ - use $crate::{macros::NixExprBuilder, nix_expr_inner}; + use $crate::{nix_expr_inner}; // might be used if indexed #[allow(unused_mut)] - let mut out = NixExprBuilder::value($field.clone()); + let mut out = $field.clone(); nix_expr_inner!(@field(out) $($tt)*); out }}; @@ -197,8 +52,7 @@ NixExprBuilder::string($v) }}; ({$v:expr}) => {{ - use $crate::macros::NixExprBuilder; - NixExprBuilder::serialized(&$v) + $crate::Value::serialized(&$v)? }} } #[macro_export] @@ -212,40 +66,25 @@ #[macro_export] macro_rules! nix_go { - (@o($o:ident) . $var:ident $($tt:tt)*) => {{ - $o.push(Index::attr(stringify!($var))); - nix_go!(@o($o) $($tt)*); - }}; - (@o($o:ident) [{ $v:expr }] $($tt:tt)*) => {{ - $o.push(Index::attr(&$v)); - nix_go!(@o($o) $($tt)*); + (@o($o:expr) . $var:ident $($tt:tt)*) => {{ + nix_go!(@o($o.get_field(stringify!($var))?) $($tt)*) }}; - (@o($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{ - $o.push(Index::Expr($crate::nix_expr_inner!($($var)+))); - nix_go!(@o($o) $($tt)*); + (@o($o:expr) [ $v:expr ] $($tt:tt)*) => {{ + nix_go!(@o($o.get_field($v)?) $($tt)*) }}; - (@o($o:ident) ($($var:tt)*) $($tt:tt)*) => { - $o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+))); - nix_go!(@o($o) $($tt)*); - }; - (@o($o:ident) | $($var:tt)*) => { - $o.push(Index::Pipe($crate::nix_expr_inner!($($var)+))); - }; - (@o($o:ident) + $($var:tt)*) => { - $o.push(Index::Merge($crate::nix_expr_inner!($($var)+))); + (@o($o:expr) ($($var:tt)*) $($tt:tt)*) => { + nix_go!(@o($o.call($crate::nix_expr_inner!($($var)+))?) $($tt)*) }; - (@o($o:ident)) => {}; + (@o($o:expr)) => {$o}; ($field:ident $($tt:tt)+) => {{ - use $crate::{nix_go, Index}; - let field = $field.clone(); - let mut out = vec![]; - nix_go!(@o(out) $($tt)*); - field.select(out).await? + use $crate::nix_go; + let out = $field.clone(); + nix_go!(@o(out) $($tt)*) }} } #[macro_export] macro_rules! nix_go_json { ($($tt:tt)*) => {{ - $crate::nix_go!($($tt)*).as_json().await? + $crate::nix_go!($($tt)*).as_json()? }}; } --- a/crates/nix-eval/src/pool.rs +++ /dev/null @@ -1,76 +0,0 @@ -use std::{ - ffi::OsString, - sync::{Arc, OnceLock}, -}; - -use r2d2::Pool; - -use crate::{Error, NixSession, Result, session::NixSessionInner}; - -pub struct NixSessionPool(Pool); -impl NixSessionPool { - pub async fn new( - flake: OsString, - nix_args: Vec, - nix_system: String, - fail_fast: bool, - ) -> Result { - let inner = tokio::task::block_in_place(|| { - r2d2::Builder::::new() - .min_idle(Some(0)) - .build(NixSessionPoolInner { - flake, - nix_args, - nix_system, - fail_fast, - }) - })?; - Ok(Self(inner)) - } - pub async fn get(&self) -> Result { - let v = tokio::task::block_in_place(|| self.0.get())?; - Ok(NixSession(Arc::new(tokio::sync::Mutex::new(v)))) - } -} - -pub(crate) struct NixSessionPoolInner { - flake: OsString, - nix_args: Vec, - fail_fast: bool, - pub(crate) nix_system: String, -} - -impl r2d2::ManageConnection for NixSessionPoolInner { - type Connection = NixSessionInner; - type Error = Error; - fn connect(&self) -> std::result::Result { - let _v = TOKIO_RUNTIME - .get() - .expect("missed tokio runtime init!") - .enter(); - futures::executor::block_on(NixSessionInner::new( - self.flake.as_os_str(), - self.nix_args.iter().map(OsString::as_os_str), - self.nix_system.clone(), - self.fail_fast, - )) - } - - fn is_valid(&self, conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> { - let _v = TOKIO_RUNTIME - .get() - .expect("missed tokio runtime init!") - .enter(); - let res = futures::executor::block_on(conn.execute_expression_number("2 + 2"))?; - if res != 4 { - // just in case, should fail much earlier - return Err(Error::SessionInit("misbehaving session")); - }; - Ok(()) - } - - fn has_broken(&self, _conn: &mut Self::Connection) -> bool { - false - } -} -pub static TOKIO_RUNTIME: OnceLock = OnceLock::new(); --- a/crates/nix-eval/src/session.rs +++ /dev/null @@ -1,450 +0,0 @@ -use std::{ffi::OsStr, num::ParseIntError, process::Stdio, sync::Arc}; - -use better_command::{ClonableHandler, Handler, NixHandler, NoopHandler}; -use futures::StreamExt; -use itertools::Itertools as _; -use serde::{Deserialize, de::DeserializeOwned}; -use thiserror::Error; -use tokio::{ - io::AsyncWriteExt, - process::{ChildStderr, ChildStdin, ChildStdout, Command}, - select, - sync::{Mutex, mpsc, oneshot}, -}; -use tokio_util::codec::{FramedRead, LinesCodec}; -use tracing::{Level, debug, error, warn}; - -#[derive(Error, Debug, Clone)] -pub enum Error { - #[error("failed to create nix repl session: {0}")] - SessionInit(&'static str), - #[error("unexpected end of output, nix crashed?")] - MissingDelimiter, - - #[error("expression did'nt produce any output")] - ExpectedOutput, - #[error("expression produced output, which is unexpected")] - UnexpectedOutput, - - #[error("unexpected expression output type")] - InvalidType, - - #[error("failed to build attr {attribute}:\n{error}")] - BuildFailed { attribute: String, error: String }, - - #[error("output: {0}")] - Json(Arc), - // int outputs are too specific, and should not be used, - // thus error is ok to be not informative. - #[error("int output: {0}")] - Int(ParseIntError), - #[error("pool: {0}")] - Pool(Arc), - #[error("io: {0}")] - Io(Arc), - - // TODO: Should be done by wrapper/in different type. - #[error("at {0}: {1}")] - InContext(String, Box), - - #[error("error: {0}")] - NixError(String), -} -impl From for Error { - fn from(value: r2d2::Error) -> Self { - Self::Pool(Arc::new(value)) - } -} -impl From for Error { - fn from(value: std::io::Error) -> Self { - Self::Io(Arc::new(value)) - } -} -impl From for Error { - fn from(value: serde_json::Error) -> Self { - Self::Json(Arc::new(value)) - } -} -impl Error { - pub(crate) fn context(self, context: String) -> Self { - Self::InContext(context, Box::new(self)) - } -} -pub type Result = std::result::Result; - -enum OutputLine { - Out(String), - Err(String), -} -struct OutputHandler { - rx: mpsc::Receiver, - _cancel_handle: oneshot::Receiver<()>, -} -impl OutputHandler { - fn new(out: ChildStdout, err: ChildStderr) -> Self { - let mut out = FramedRead::new(out, LinesCodec::new()); - let mut err = FramedRead::new(err, LinesCodec::new()); - let (tx, rx) = mpsc::channel(20); - let (mut cancelled, _cancel_handle) = oneshot::channel(); - tokio::spawn(async move { - loop { - select! { - // We should receive errors earlier than synchronization - biased; - e = err.next() => { - let Some(Ok(e)) = e else { - if e.is_some() { - error!("bad repl stderr: {e:?}"); - } - continue; - }; - let _ = tx.send(OutputLine::Err(e)).await; - } - o = out.next() => { - let Some(Ok(o)) = o else { - if o.is_some() { - error!("bad repl stdout: {o:?}"); - } - continue; - }; - let _ = tx.send(OutputLine::Out(o)).await; - } - // Reader doesn't care about stdout, as this is cancelled. - // Error still might be useful, to process leftover span closures? - _ = cancelled.closed() => { - break; - } - } - } - }); - Self { rx, _cancel_handle } - } - async fn next(&mut self) -> Option { - self.rx.recv().await - } -} - -#[must_use] -struct ErrorCollector<'i, H> { - collected: Vec, - inner: &'i mut H, -} -impl<'i, H> ErrorCollector<'i, H> { - fn new(inner: &'i mut H) -> Self { - Self { - collected: vec![], - inner, - } - } -} -impl ErrorCollector<'_, H> { - fn handle_line_inner(&mut self, msg: &str) -> bool { - let Some(msg) = msg.strip_prefix("@nix ") else { - return false; - }; - #[derive(Deserialize)] - struct ErrorAction { - action: String, - level: u32, - msg: String, - } - let Ok(act) = serde_json::from_str::(msg) else { - return false; - }; - if act.action != "msg" || act.level != 0 { - return false; - } - self.collected.push(act.msg); - true - } - fn finish(self) -> Result<()> { - // fn dedent(s: String) -> String { - // s.split('\n').filter(|s| !s.trim().is_empty()).map(|v| v.) - // } - if !self.collected.is_empty() { - return Err(Error::NixError( - self.collected - .iter() - .map(|v| { - if let Some(f) = v.strip_prefix("\u{1b}[31;1merror:\u{1b}[0m ") { - let v = unindent::unindent(f.trim_start()); - v.trim().to_owned() - } else { - v.to_owned() - } - }) - .join("\n") - .to_string(), - )); - } - Ok(()) - } - fn flush(self) { - for line in self.collected { - warn!("{line}"); - } - } -} -impl Handler for ErrorCollector<'_, H> { - fn handle_line(&mut self, e: &str) { - if self.handle_line_inner(e) { - return; - } - self.inner.handle_line(e) - } -} - -pub struct NixSessionInner { - full_delimiter: String, - nix_handler: ClonableHandler, - out: OutputHandler, - stdin: ChildStdin, - string_wrapping: (String, String), - number_wrapping: (String, String), - - executing_command: Arc>, - - next_id: u32, - pub(crate) free_list: Vec, - - pub nix_system: String, -} - -/// Discover inter-message repl delimiter -const REPL_DELIMITER: &str = "\"FLEET_MAGIC_REPL_DELIMITER\""; -/// Discover formatting around strings -const TRAIN_STRING: &str = "\"TRAIN_STRING\""; -/// Discover formatting around numbers -const TRAIN_NUMBER: &str = "13141516"; -// Other types of formatting are not discovered, because they are not used, JSON serialization is used instead -// Techically, number training is also not required, because numbers can be converted to string too... -// Eh, I'll remove it later. - -impl NixSessionInner { - pub(crate) async fn new( - flake: &OsStr, - extra_args: impl IntoIterator, - nix_system: String, - fail_fast: bool, - ) -> Result { - let mut cmd = Command::new("nix"); - cmd.arg("repl") - .args(["--option", "pure-eval", "true"]) - .arg(flake) - .arg("--log-format") - .arg("internal-json"); - if !fail_fast { - cmd.arg("--keep-going"); - } - for arg in extra_args { - cmd.arg(arg); - } - cmd.stdin(Stdio::piped()); - cmd.stdout(Stdio::piped()); - cmd.stderr(Stdio::piped()); - let cmd = cmd.spawn()?; - let stdout = cmd.stdout.unwrap(); - let stderr = cmd.stderr.unwrap(); - let mut out = OutputHandler::new(stdout, stderr); - let mut stdin = cmd.stdin.unwrap(); - // Standard repl hello doesn't work with internal-json logger - stdin.write_all(REPL_DELIMITER.as_bytes()).await?; - stdin.write_all(b"\n").await?; - stdin.flush().await?; - let nix_handler = NixHandler::default(); - let mut full_delimiter = None; - let mut errors = vec![]; - while let Some(line) = out.next().await { - let line = match line { - OutputLine::Out(o) => o, - OutputLine::Err(_e) => { - // Handle startup errors, but skip repl hello? - errors.push(_e); - continue; - } - }; - if line.contains(REPL_DELIMITER) { - debug!("discovered repl delimiter with added colors: {line}"); - full_delimiter = Some(line.to_owned()); - break; - } - } - let Some(full_delimiter) = full_delimiter else { - for e in errors { - error!("{e}"); - } - return Err(Error::SessionInit("failed to discover delimiter")); - }; - let mut res = Self { - full_delimiter, - nix_handler: ClonableHandler::new(nix_handler), - out, - stdin, - string_wrapping: Default::default(), - number_wrapping: Default::default(), - - executing_command: Arc::new(Mutex::new(())), - - next_id: 0, - free_list: vec![], - - nix_system, - }; - res.train().await?; - Ok(res) - } - async fn train(&mut self) -> Result<()> { - { - let full_string = self - .execute_expression_raw(TRAIN_STRING, &mut NoopHandler) - .await?; - let string_offset = full_string.find(TRAIN_STRING).expect("contained"); - let string_prefix = &full_string[..string_offset]; - let string_suffix = &full_string[string_offset + TRAIN_STRING.len()..]; - self.string_wrapping = (string_prefix.to_owned(), string_suffix.to_owned()); - } - { - let full_number = self - .execute_expression_raw(TRAIN_NUMBER, &mut NoopHandler) - .await?; - let number_offset = full_number.find(TRAIN_NUMBER).expect("contained"); - let number_prefix = &full_number[..number_offset]; - let number_suffix = &full_number[number_offset + TRAIN_NUMBER.len()..]; - self.number_wrapping = (number_prefix.to_owned(), number_suffix.to_owned()); - } - Ok(()) - } - async fn send_command(&mut self, cmd: impl AsRef<[u8]>) -> Result<()> { - if tracing::enabled!(Level::DEBUG) && cmd.as_ref() != REPL_DELIMITER.as_bytes() { - let cmd_str = String::from_utf8_lossy(cmd.as_ref()); - tracing::debug!("{cmd_str}"); - }; - self.stdin.write_all(cmd.as_ref()).await?; - self.stdin.write_all(b"\n").await?; - Ok(()) - } - async fn read_until_delimiter(&mut self, err_handler: &mut dyn Handler) -> Result { - let mut out = String::new(); - while let Some(line) = self.out.next().await { - let line = match line { - OutputLine::Out(out) => out, - OutputLine::Err(err) => { - err_handler.handle_line(&err); - continue; - } - }; - if line == self.full_delimiter { - return Ok(out); - } - if !out.is_empty() { - out.push('\n'); - } - out.push_str(&line); - } - Err(Error::MissingDelimiter) - } - pub(crate) async fn execute_expression_number( - &mut self, - expr: impl AsRef<[u8]>, - ) -> Result { - let num = self.number_wrapping.clone(); - let n = self.execute_expression_wrapping(expr, &num).await?; - n.parse::().map_err(Error::Int) - } - async fn execute_expression_string(&mut self, expr: impl AsRef<[u8]>) -> Result { - // builtins.toJSON escapes some thing in incorrect way, e.g escaped "$" in "\${" is being outputed as "\$", - // while this escape should be removed as it is intended for nix itself, not for json output. - // - // This regex only allows \$ in the beginning of the string, it is easier to implement correctly. - // TODO: Add peg parser for nix-produced JSON?.. - let regex = regex::Regex::new(r#"(?[: {,\[]\\")\\\$"#).expect("fixup json"); - - let num = self.string_wrapping.clone(); - let n = self.execute_expression_wrapping(expr, &num).await?; - let n = regex.replace_all(&n, "$prefix$$"); - let str: String = serde_json::from_str(&n)?; - Ok(str) - } - pub(crate) async fn execute_expression_to_json( - &mut self, - expr: impl AsRef<[u8]>, - ) -> Result { - let mut fexpr = b"builtins.toJSON (".to_vec(); - fexpr.extend_from_slice(expr.as_ref()); - fexpr.push(b')'); - - Ok(serde_json::from_str( - &self.execute_expression_string(fexpr).await?, - )?) - } - async fn execute_expression_wrapping( - &mut self, - expr: impl AsRef<[u8]>, - wrapping: &(String, String), - ) -> Result { - let mut nix_handler = self.nix_handler.clone(); - let mut collected = ErrorCollector::new(&mut nix_handler); - let res = self.execute_expression_raw(expr, &mut collected).await?; - if res.is_empty() { - collected.finish()?; - return Err(Error::ExpectedOutput); - } else { - collected.flush() - }; - let Some(res) = res.strip_prefix(&wrapping.0) else { - return Err(Error::InvalidType); - }; - let Some(res) = res.strip_suffix(&wrapping.1) else { - return Err(Error::InvalidType); - }; - Ok(res.to_owned()) - } - async fn execute_expression_empty(&mut self, expr: impl AsRef<[u8]>) -> Result<()> { - let mut nix_handler = self.nix_handler.clone(); - let mut collected = ErrorCollector::new(&mut nix_handler); - let v = self.execute_expression_raw(expr, &mut collected).await?; - collected.finish()?; - if !v.is_empty() { - return Err(Error::UnexpectedOutput); - } - Ok(()) - } - pub(crate) async fn execute_expression_raw( - &mut self, - expr: impl AsRef<[u8]>, - err_handler: &mut dyn Handler, - ) -> Result { - // Prevent two commands from being executed in parallel, messing with each other. - let _lock = self.executing_command.clone(); - let _guard = _lock.lock().await; - - self.send_command(expr).await?; - // It will be echoed - self.send_command(REPL_DELIMITER).await?; - self.read_until_delimiter(err_handler).await - } - pub(crate) async fn execute_assign(&mut self, expr: impl AsRef) -> Result { - let id = self.allocate_id(); - self.execute_expression_empty(format!("sess_field_{id} = {}", expr.as_ref())) - .await?; - Ok(id) - } - - /// Id should be immediately used - fn allocate_id(&mut self) -> u32 { - if let Some(free) = self.free_list.pop() { - free - } else { - let v = self.next_id; - self.next_id += 1; - v - } - } - // Nix has no way to deallocate variable, yet GC will correct everything not reachable. - // async fn free_id(&mut self, id: u32) -> Result<()> { - // self.execute_expression_empty(format!("sess_field_{id} = null")) - // .await?; - // self.free_list.push(id); - // Ok(()) - // } -} --- a/crates/nix-eval/src/value.rs +++ b/crates/nix-eval/src/value.rs @@ -3,302 +3,4 @@ use better_command::NixHandler; use serde::{Serialize, de::DeserializeOwned}; -use crate::{Error, NixBuildBatch, NixSession, Result, macros::NixExprBuilder, nix_go}; - -#[derive(Clone)] -pub enum Index { - Var(String), - String(String), - #[allow(dead_code)] - Apply(String), - #[allow(dead_code)] - Expr(NixExprBuilder), - ExprApply(NixExprBuilder), - Pipe(NixExprBuilder), - Merge(NixExprBuilder), -} -impl Index { - pub fn var(v: impl AsRef) -> Self { - let v = v.as_ref(); - assert!( - !(v.contains('.') | v.contains(' ')), - "bad variable name: {v}" - ); - Self::Var(v.to_owned()) - } - pub fn attr(v: impl AsRef) -> Self { - Self::String(v.as_ref().to_owned()) - } - #[allow(dead_code)] - pub fn apply(v: impl Serialize) -> Self { - let serialized = nixlike::serialize(v).expect("invalid value for apply"); - Self::Apply(serialized.trim_end().to_owned()) - } -} -impl fmt::Display for Index { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Index::Var(v) => { - write!(f, "{v}") - } - Index::String(k) => { - let v = nixlike::format_identifier(k.as_str()); - write!(f, ".{v}") - } - Index::Apply(_) => { - write!(f, "(...)") - } - Index::Expr(e) => { - write!(f, "[{}]", e.out) - } - Index::ExprApply(_) => { - write!(f, "(...)") - } - Index::Pipe(e) => { - write!(f, "({})", e.out) - } - Index::Merge(e) => { - write!(f, "//({})", e.out) - } - } - } -} -impl fmt::Debug for Index { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{self}") - } -} -struct PathDisplay<'i>(&'i [Index]); -impl fmt::Display for PathDisplay<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if !matches!(self.0.first(), Some(Index::Var(_))) { - write!(f, "")?; - } - for i in self.0 { - write!(f, "{i}")?; - } - Ok(()) - } -} -struct ValueInner { - full_path: Vec, - session: NixSession, - value: u32, -} -#[derive(Clone)] -pub struct Value(Arc); -impl Value { - async fn new(session: NixSession, query: &str) -> Result { - let vid = session.0.lock().await.execute_assign(query).await?; - Ok(Self(Arc::new(ValueInner { - full_path: vec![], - session, - value: vid, - }))) - } - /// Get a top-level binding. - /// - /// In flake repl session, every output is exposed as top-level binding. - pub async fn binding(session: NixSession, query: &str) -> Result { - // TODO: Verify that query is a valid variable name - let vid = session.0.lock().await.execute_assign(query).await?; - Ok(Self(Arc::new(ValueInner { - full_path: vec![Index::Var(query.to_owned())], - session, - value: vid, - }))) - } - pub async fn select(&self, name: impl IntoIterator) -> Result { - let mut used_fields = Vec::new(); - let name = name.into_iter(); - - let mut full_path = self.0.full_path.clone(); - let mut query = self.sess_field_name(); - for v in name { - full_path.push(v.clone()); - match v { - Index::Var(_) => panic!("var item may only be first"), - Index::String(s) => { - let escaped = - nixlike::serialize(s).expect("strings are always serialized successfully"); - query.push('.'); - query.push_str(escaped.trim()); - } - Index::Apply(a) => { - // In cases like `a {}.b` first `{}.b` will be evaluated, so `a {}` should be encased in `()` - query = format!("({query} {a})"); - } - Index::Expr(e) => { - let index = Value::new(self.0.session.clone(), &e.out).await?; - used_fields.push(index.clone()); - query.push('.'); - let index = format!("${{sess_field_{}}}", index.0.value); - query.push_str(&index); - } - Index::ExprApply(e) => { - let index = Value::new(self.0.session.clone(), &e.out).await?; - used_fields.push(index.clone()); - query.push(' '); - let index = format!("sess_field_{}", index.0.value); - query.push_str(&index); - query = format!("({query})"); - } - Index::Pipe(v) => { - let index = Value::new(self.0.session.clone(), &v.out).await?; - used_fields.push(index.clone()); - let index = format!("sess_field_{}", index.0.value); - query = format!("({index} {query})"); - } - Index::Merge(v) => { - let index = Value::new(self.0.session.clone(), &v.out).await?; - used_fields.push(index.clone()); - let index = format!("sess_field_{}", index.0.value); - query = format!("({query} // {index})"); - } - } - } - - let vid = self - .0 - .session - .0 - .lock() - .await - .execute_assign(&query) - .await - .map_err(|e| e.context(self.attribute()))?; - Ok(Self(Arc::new(ValueInner { - full_path, - session: self.0.session.clone(), - value: vid, - }))) - } - pub async fn as_json(&self) -> Result { - let query = self.sess_field_name(); - self.0 - .session - .0 - .lock() - .await - .execute_expression_to_json(&query) - .await - .map_err(|e| e.context(self.attribute())) - } - #[allow(dead_code)] - pub async fn has_field(&self, name: &str) -> Result { - let key = nixlike::escape_string(name); - let query = format!("{} ? {key}", self.sess_field_name()); - self.0 - .session - .0 - .lock() - .await - .execute_expression_to_json(&query) - .await - .map_err(|e| e.context(self.attribute())) - } - pub async fn list_fields(&self) -> Result> { - let query = format!("builtins.attrNames {}", self.sess_field_name()); - self.0 - .session - .0 - .lock() - .await - .execute_expression_to_json(&query) - .await - .map_err(|e| e.context(self.attribute())) - } - pub async fn type_of(&self) -> Result { - let query = format!("builtins.typeOf {}", self.sess_field_name()); - self.0 - .session - .0 - .lock() - .await - .execute_expression_to_json(&query) - .await - .map_err(|e| e.context(self.attribute())) - } - #[allow(dead_code)] - pub async fn import(&self) -> Result { - let import = Self::new(self.0.session.clone(), "import").await?; - Ok(nix_go!(self | import)) - } - fn sess_field_name(&self) -> String { - format!("sess_field_{}", self.0.value) - } - pub async fn build_maybe_batch( - &self, - batch: Option, - ) -> Result> { - if let Some(batch) = batch { - batch.submit(self.clone()).await - } else { - self.build().await - } - } - pub async fn build(&self) -> Result> { - let query = format!(":b {}", self.sess_field_name()); - let vid = self - .0 - .session - .0 - .lock() - .await - .execute_expression_raw(&query, &mut NixHandler::default()) - .await?; - if vid.is_empty() { - return Err(Error::BuildFailed { - attribute: self.attribute(), - error: "build produced no output".to_owned(), - }); - } - let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n") - else { - return Err(Error::BuildFailed { - attribute: self.attribute(), - error: format!("failed to parse output: {vid}"), - }); - }; - let outputs = vid - .split('\n') - .filter(|v| !v.is_empty()) - .map(|v| v.split_once(" -> ").expect("unexpected build output")) - .map(|(a, b)| (a.trim_start().to_owned(), PathBuf::from(b))) - .collect(); - Ok(outputs) - } - /// Weakly convert string-like types (derivation/path/string) to string - pub async fn to_string_weak(&self) -> Result { - let query = format!("\"${{{}}}\"", self.sess_field_name()); - let vid: String = self - .0 - .session - .0 - .lock() - .await - .execute_expression_to_json(&query) - .await?; - Ok(vid) - } - - fn attribute(&self) -> String { - PathDisplay(&self.0.full_path).to_string() - } - - pub(crate) fn session(&self) -> NixSession { - self.0.session.clone() - } - - pub(crate) fn session_field_id(&self) -> u32 { - self.0.value - } -} -impl Drop for ValueInner { - fn drop(&mut self) { - if let Ok(mut lock) = self.session.0.try_lock() { - lock.free_list.push(self.value) - } - // Leaked - } -} +use crate::{Result, Value, nix_go}; --- a/crates/nixlike/Cargo.toml +++ b/crates/nixlike/Cargo.toml @@ -10,7 +10,7 @@ alejandra = { git = "https://github.com/kamadorueda/alejandra" } linked-hash-map = "0.5.6" peg = "0.8.5" -ron = "0.10.1" +ron = "0.11.0" serde = "1.0.219" serde-transcode = "1.1.1" serde_json = "1.0.140" --- a/crates/nixlike/src/lib.rs +++ b/crates/nixlike/src/lib.rs @@ -5,6 +5,7 @@ //! expressions and expect it to work, only basic primitives are supported, and there is no //! variables/recursive records, interpolation, e.t.c. +use alejandra::config::Indentation; use linked_hash_map::LinkedHashMap; use peg::str::LineCol; use se_impl::MySerialize; @@ -196,7 +197,13 @@ assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"\n"); } pub fn format_nix(value: &String) -> String { - let (_, out) = alejandra::format::in_memory("".to_owned(), value.to_owned()); + let (_, out) = alejandra::format::in_memory( + "".to_owned(), + value.to_owned(), + alejandra::config::Config { + indentation: Indentation::TwoSpaces, + }, + ); out } --- a/crates/nixlike/src/to_string.rs +++ b/crates/nixlike/src/to_string.rs @@ -1,3 +1,5 @@ +use alejandra::config::Indentation; + use crate::Value; pub fn write_identifier(k: &str, out: &mut String) { @@ -98,6 +100,12 @@ pub fn write_nix(value: &Value) -> String { let mut out = String::new(); write_nix_buf(value, &mut out); - let (_, out) = alejandra::format::in_memory("".to_owned(), out); + let (_, out) = alejandra::format::in_memory( + "".to_owned(), + out, + alejandra::config::Config { + indentation: Indentation::TwoSpaces, + }, + ); out } --- a/flake.lock +++ b/flake.lock @@ -15,6 +15,22 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -35,8 +51,117 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1748821116, + "narHash": "sha256-F82+gS044J1APL0n4hH50GYdPRv/5JWm34oCJYmVKdE=", + "rev": "49f0870db23e8c1ca0b5259734a02cd9e1e371a1", + "revCount": 377, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/hercules-ci/flake-parts/0.1.377%2Brev-49f0870db23e8c1ca0b5259734a02cd9e1e371a1/01972f28-554a-73f8-91f4-d488cc502f08/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/hercules-ci/flake-parts/0.1" + } + }, + "git-hooks-nix": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": [ + "nix" + ], + "nixpkgs": [ + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747372754, + "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=", + "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", + "revCount": 1026, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/cachix/git-hooks.nix/0.1.1026%2Brev-80479b6ec16fefd9c1db3ea13aeb038c60530f46/0196d79a-1b35-7b8e-a021-c894fb62163d/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/cachix/git-hooks.nix/0.1.941" + } + }, + "nix": { + "inputs": { + "flake-parts": "flake-parts_2", + "git-hooks-nix": "git-hooks-nix", + "nixpkgs": "nixpkgs", + "nixpkgs-23-11": "nixpkgs-23-11", + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1756860322, + "narHash": "sha256-mT01CpWVdqSm79L270dSkjdYbdc37r+Hq9vk4GTp7Ao=", + "path": "/home/lach/build/nix-src", + "type": "path" + }, + "original": { + "path": "/home/lach/build/nix-src", + "type": "path" + } + }, "nixpkgs": { "locked": { + "lastModified": 1755922037, + "narHash": "sha256-wY1+2JPH0ZZC4BQefoZw/k+3+DowFyfOxv17CN/idKs=", + "rev": "b1b3291469652d5a2edb0becc4ef0246fff97a7c", + "revCount": 808723, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2505.808723%2Brev-b1b3291469652d5a2edb0becc4ef0246fff97a7c/0198daf7-011a-7703-95d7-57146e794342/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2505" + } + }, + "nixpkgs-23-11": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { "lastModified": 1753320130, "narHash": "sha256-KCuv6iYQ0XTVAEJvDLIsk99CJm7fuqIE0/KknyeYPtM=", "owner": "nixos", @@ -55,7 +180,8 @@ "inputs": { "crane": "crane", "flake-parts": "flake-parts", - "nixpkgs": "nixpkgs", + "nix": "nix", + "nixpkgs": "nixpkgs_2", "rust-overlay": "rust-overlay", "shelly": "shelly", "treefmt-nix": "treefmt-nix" --- a/flake.nix +++ b/flake.nix @@ -17,6 +17,9 @@ url = "github:numtide/treefmt-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + # DeterminateSystem's nix fork is controversial, but I don't mind it, + # and it has lazy-trees support which is useful for fleet. + nix.url = "/home/lach/build/nix-src"; }; outputs = inputs: @@ -41,6 +44,11 @@ fleetModules.tf = ./modules/extras/tf.nix; + testObj = { + v = "Hello"; + }; + testString = "hello"; + # To be used with https://github.com/NixOS/nix/pull/8892 schemas = let @@ -80,6 +88,7 @@ system, pkgs, self, + inputs', ... }: let @@ -108,7 +117,7 @@ packages = lib.mkIf deployerSystem ( let packages = pkgs.callPackages ./pkgs { - inherit craneLib; + inherit craneLib inputs'; }; in packages // { default = packages.fleet; } @@ -120,6 +129,7 @@ nixpkgsCraneLib = inputs.crane.mkLib pkgs; packages = pkgs.callPackages ./pkgs { craneLib = nixpkgsCraneLib; + inherit inputs; }; prefixAttrs = prefix: attrs: @@ -150,13 +160,16 @@ cargo-fuzz cargo-watch cargo-outdated + gdb pkg-config openssl bacon nil rustPlatform.bindgenHook - # nixVersions.nix_2_22 + inputs'.nix.packages.nix-expr-c + inputs'.nix.packages.nix-flake-c + inputs'.nix.packages.nix-fetchers-c ]; environment.PROTOC = "${pkgs.protobuf}/bin/protoc"; }; --- a/lib/flakePart.nix +++ b/lib/flakePart.nix @@ -65,7 +65,7 @@ normalEval = bootstrapNixpkgs.lib.evalModules { modules = (import ../modules/module-list.nix) ++ [ module - { + ({inputs', ...}: { config = { data = if isPath data then import data else data; nixpkgs.buildUsing = mkOptionDefault bootstrapNixpkgs; @@ -74,6 +74,7 @@ inherit (import ../pkgs { inherit (prev) callPackage; + inherit inputs'; craneLib = crane.mkLib prev; }) fleet-install-secrets @@ -82,7 +83,7 @@ }) ]; }; - } + }) ]; specialArgs = { inherit inputs self; --- a/modules/nixos/online.nix +++ b/modules/nixos/online.nix @@ -80,7 +80,8 @@ ''; supportsDryActivation = true; }; - } // config.system.onlineActivationScripts; + } + // config.system.onlineActivationScripts; config.systemd.services = mkIf config.networking.networkmanager.enable { # If machine is managed by fleet, we should not restart NetworkManager during activation, --- a/modules/secrets-data.nix +++ b/modules/secrets-data.nix @@ -105,7 +105,7 @@ description = "Age-compatible key"; }; }; - config = {}; + config = { }; }; in { --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,9 +1,10 @@ { callPackage, craneLib, + inputs', }: { - fleet = callPackage ./fleet.nix { inherit craneLib; }; + fleet = callPackage ./fleet.nix { inherit craneLib inputs'; }; fleet-install-secrets = callPackage ./fleet-install-secrets.nix { inherit craneLib; }; fleet-generator-helper = callPackage ./fleet-generator-helper.nix { inherit craneLib; }; } --- a/pkgs/fleet.nix +++ b/pkgs/fleet.nix @@ -1,16 +1,35 @@ { + lib, craneLib, installShellFiles, + inputs', + pkg-config, + rustPlatform, }: craneLib.buildPackage rec { pname = "fleet"; - - src = craneLib.cleanCargoSource (craneLib.path ../.); + src = lib.cleanSourceWith { + src = ../.; + filter = + path: type: + (lib.hasSuffix "\.cc" path) + || (lib.hasSuffix "\.hh" path) + || (craneLib.filterCargoSources path type); + }; strictDeps = true; cargoExtraArgs = "--locked -p ${pname}"; - nativeBuildInputs = [ installShellFiles ]; + buildInputs = [ + inputs'.nix.packages.nix-expr-c + inputs'.nix.packages.nix-flake-c + inputs'.nix.packages.nix-fetchers-c + ]; + nativeBuildInputs = [ + installShellFiles + pkg-config + rustPlatform.bindgenHook + ]; postInstall = '' for shell in bash fish zsh; do --- a/treefmt.nix +++ b/treefmt.nix @@ -9,4 +9,5 @@ programs.shfmt.enable = true; programs.rustfmt.enable = true; programs.taplo.enable = true; + programs.clang-format.enable = true; } -- gitstuff