git.delta.rocks / jrsonnet / refs/commits / 966e7f167d68

difftreelog

refactor c bindings

Yaroslav Bolyukin2024-05-25parent: #3f5aab0.patch.diff
in: trunk

26 files changed

modifiedCargo.lockdiffbeforeafterboth
198198
199[[package]]199[[package]]
200name = "anyhow"200name = "anyhow"
201version = "1.0.83"201version = "1.0.86"
202source = "registry+https://github.com/rust-lang/crates.io-index"202source = "registry+https://github.com/rust-lang/crates.io-index"
203checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"203checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
204204
205[[package]]205[[package]]
206name = "arc-swap"206name = "arc-swap"
222dependencies = [222dependencies = [
223 "proc-macro2",223 "proc-macro2",
224 "quote",224 "quote",
225 "syn 2.0.63",225 "syn 2.0.66",
226]226]
227227
228[[package]]228[[package]]
374374
375[[package]]375[[package]]
376name = "cc"376name = "cc"
377version = "1.0.97"377version = "1.0.98"
378source = "registry+https://github.com/rust-lang/crates.io-index"378source = "registry+https://github.com/rust-lang/crates.io-index"
379checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"379checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
380380
381[[package]]381[[package]]
382name = "cfg-if"382name = "cfg-if"
468 "heck",468 "heck",
469 "proc-macro2",469 "proc-macro2",
470 "quote",470 "quote",
471 "syn 2.0.63",471 "syn 2.0.66",
472]472]
473473
474[[package]]474[[package]]
587 "cfg-if",587 "cfg-if",
588 "cpufeatures",588 "cpufeatures",
589 "curve25519-dalek-derive",589 "curve25519-dalek-derive",
590 "digest",
590 "fiat-crypto",591 "fiat-crypto",
591 "platforms",592 "platforms",
592 "rustc_version",593 "rustc_version",
602dependencies = [603dependencies = [
603 "proc-macro2",604 "proc-macro2",
604 "quote",605 "quote",
605 "syn 2.0.63",606 "syn 2.0.66",
606]607]
607608
608[[package]]609[[package]]
658dependencies = [659dependencies = [
659 "proc-macro2",660 "proc-macro2",
660 "quote",661 "quote",
661 "syn 2.0.63",662 "syn 2.0.66",
662]663]
664
665[[package]]
666name = "ed25519"
667version = "2.2.3"
668source = "registry+https://github.com/rust-lang/crates.io-index"
669checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
670dependencies = [
671 "pkcs8",
672 "signature",
673]
674
675[[package]]
676name = "ed25519-dalek"
677version = "2.1.1"
678source = "registry+https://github.com/rust-lang/crates.io-index"
679checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
680dependencies = [
681 "curve25519-dalek",
682 "ed25519",
683 "rand_core",
684 "serde",
685 "sha2",
686 "subtle",
687 "zeroize",
688]
663689
664[[package]]690[[package]]
665name = "either"691name = "either"
666version = "1.11.0"692version = "1.12.0"
667source = "registry+https://github.com/rust-lang/crates.io-index"693source = "registry+https://github.com/rust-lang/crates.io-index"
668checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"694checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
669695
670[[package]]696[[package]]
671name = "encode_unicode"697name = "encode_unicode"
894dependencies = [920dependencies = [
895 "proc-macro2",921 "proc-macro2",
896 "quote",922 "quote",
897 "syn 2.0.63",923 "syn 2.0.66",
898]924]
899925
900[[package]]926[[package]]
927 "slab",953 "slab",
928]954]
955
956[[package]]
957name = "generator-helper"
958version = "0.1.0"
959dependencies = [
960 "age",
961 "anyhow",
962 "clap",
963 "ed25519-dalek",
964 "fleet-shared",
965 "rand",
966]
929967
930[[package]]968[[package]]
931name = "generic-array"969name = "generic-array"
1033 "serde",1071 "serde",
1034 "serde_derive",1072 "serde_derive",
1035 "thiserror",1073 "thiserror",
1036 "toml 0.8.12",1074 "toml 0.8.13",
1037 "unic-langid",1075 "unic-langid",
1038]1076]
10391077
1075 "proc-macro2",1113 "proc-macro2",
1076 "quote",1114 "quote",
1077 "strsim",1115 "strsim",
1078 "syn 2.0.63",1116 "syn 2.0.66",
1079 "unic-langid",1117 "unic-langid",
1080]1118]
10811119
1089 "i18n-config",1127 "i18n-config",
1090 "proc-macro2",1128 "proc-macro2",
1091 "quote",1129 "quote",
1092 "syn 2.0.63",1130 "syn 2.0.66",
1093]1131]
10941132
1095[[package]]1133[[package]]
11511189
1152[[package]]1190[[package]]
1153name = "instant"1191name = "instant"
1154version = "0.1.12"1192version = "0.1.13"
1155source = "registry+https://github.com/rust-lang/crates.io-index"1193source = "registry+https://github.com/rust-lang/crates.io-index"
1156checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"1194checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
1157dependencies = [1195dependencies = [
1158 "cfg-if",1196 "cfg-if",
1159]1197]
12411279
1242[[package]]1280[[package]]
1243name = "libc"1281name = "libc"
1244version = "0.2.154"1282version = "0.2.155"
1245source = "registry+https://github.com/rust-lang/crates.io-index"1283source = "registry+https://github.com/rust-lang/crates.io-index"
1246checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"1284checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
12471285
1248[[package]]1286[[package]]
1249name = "libm"1287name = "libm"
12531291
1254[[package]]1292[[package]]
1255name = "libmimalloc-sys"1293name = "libmimalloc-sys"
1256version = "0.1.37"1294version = "0.1.38"
1257source = "registry+https://github.com/rust-lang/crates.io-index"1295source = "registry+https://github.com/rust-lang/crates.io-index"
1258checksum = "81eb4061c0582dedea1cbc7aff2240300dd6982e0239d1c99e65c1dbf4a30ba7"1296checksum = "0e7bb23d733dfcc8af652a78b7bf232f0e967710d044732185e561e47c0336b6"
1259dependencies = [1297dependencies = [
1260 "cc",1298 "cc",
1261 "libc",1299 "libc",
12691307
1270[[package]]1308[[package]]
1271name = "linux-raw-sys"1309name = "linux-raw-sys"
1272version = "0.4.13"1310version = "0.4.14"
1273source = "registry+https://github.com/rust-lang/crates.io-index"1311source = "registry+https://github.com/rust-lang/crates.io-index"
1274checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"1312checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
12751313
1276[[package]]1314[[package]]
1277name = "lock_api"1315name = "lock_api"
13211359
1322[[package]]1360[[package]]
1323name = "mimalloc"1361name = "mimalloc"
1324version = "0.1.41"1362version = "0.1.42"
1325source = "registry+https://github.com/rust-lang/crates.io-index"1363source = "registry+https://github.com/rust-lang/crates.io-index"
1326checksum = "9f41a2280ded0da56c8cf898babb86e8f10651a34adcfff190ae9a1159c6908d"1364checksum = "e9186d86b79b52f4a77af65604b51225e8db1d6ee7e3f41aec1e40829c71a176"
1327dependencies = [1365dependencies = [
1328 "libmimalloc-sys",1366 "libmimalloc-sys",
1329]1367]
13361374
1337[[package]]1375[[package]]
1338name = "miniz_oxide"1376name = "miniz_oxide"
1339version = "0.7.2"1377version = "0.7.3"
1340source = "registry+https://github.com/rust-lang/crates.io-index"1378source = "registry+https://github.com/rust-lang/crates.io-index"
1341checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"1379checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
1342dependencies = [1380dependencies = [
1343 "adler",1381 "adler",
1344]1382]
15331571
1534[[package]]1572[[package]]
1535name = "parking_lot"1573name = "parking_lot"
1536version = "0.12.2"1574version = "0.12.3"
1537source = "registry+https://github.com/rust-lang/crates.io-index"1575source = "registry+https://github.com/rust-lang/crates.io-index"
1538checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"1576checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
1539dependencies = [1577dependencies = [
1540 "lock_api",1578 "lock_api",
1541 "parking_lot_core",1579 "parking_lot_core",
1608dependencies = [1646dependencies = [
1609 "proc-macro2",1647 "proc-macro2",
1610 "quote",1648 "quote",
1611 "syn 2.0.63",1649 "syn 2.0.66",
1612]1650]
16131651
1614[[package]]1652[[package]]
17171755
1718[[package]]1756[[package]]
1719name = "proc-macro2"1757name = "proc-macro2"
1720version = "1.0.82"1758version = "1.0.84"
1721source = "registry+https://github.com/rust-lang/crates.io-index"1759source = "registry+https://github.com/rust-lang/crates.io-index"
1722checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"1760checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
1723dependencies = [1761dependencies = [
1724 "unicode-ident",1762 "unicode-ident",
1725]1763]
1911 "proc-macro2",1949 "proc-macro2",
1912 "quote",1950 "quote",
1913 "rust-embed-utils",1951 "rust-embed-utils",
1914 "syn 2.0.63",1952 "syn 2.0.66",
1915 "walkdir",1953 "walkdir",
1916]1954]
19171955
20412079
2042[[package]]2080[[package]]
2043name = "serde"2081name = "serde"
2044version = "1.0.202"2082version = "1.0.203"
2045source = "registry+https://github.com/rust-lang/crates.io-index"2083source = "registry+https://github.com/rust-lang/crates.io-index"
2046checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"2084checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
2047dependencies = [2085dependencies = [
2048 "serde_derive",2086 "serde_derive",
2049]2087]
20592097
2060[[package]]2098[[package]]
2061name = "serde_derive"2099name = "serde_derive"
2062version = "1.0.202"2100version = "1.0.203"
2063source = "registry+https://github.com/rust-lang/crates.io-index"2101source = "registry+https://github.com/rust-lang/crates.io-index"
2064checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"2102checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
2065dependencies = [2103dependencies = [
2066 "proc-macro2",2104 "proc-macro2",
2067 "quote",2105 "quote",
2068 "syn 2.0.63",2106 "syn 2.0.66",
2069]2107]
20702108
2071[[package]]2109[[package]]
20812119
2082[[package]]2120[[package]]
2083name = "serde_spanned"2121name = "serde_spanned"
2084version = "0.6.5"2122version = "0.6.6"
2085source = "registry+https://github.com/rust-lang/crates.io-index"2123source = "registry+https://github.com/rust-lang/crates.io-index"
2086checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"2124checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
2087dependencies = [2125dependencies = [
2088 "serde",2126 "serde",
2089]2127]
22452283
2246[[package]]2284[[package]]
2247name = "syn"2285name = "syn"
2248version = "2.0.63"2286version = "2.0.66"
2249source = "registry+https://github.com/rust-lang/crates.io-index"2287source = "registry+https://github.com/rust-lang/crates.io-index"
2250checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"2288checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
2251dependencies = [2289dependencies = [
2252 "proc-macro2",2290 "proc-macro2",
2253 "quote",2291 "quote",
23082346
2309[[package]]2347[[package]]
2310name = "thiserror"2348name = "thiserror"
2311version = "1.0.60"2349version = "1.0.61"
2312source = "registry+https://github.com/rust-lang/crates.io-index"2350source = "registry+https://github.com/rust-lang/crates.io-index"
2313checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"2351checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
2314dependencies = [2352dependencies = [
2315 "thiserror-impl",2353 "thiserror-impl",
2316]2354]
23172355
2318[[package]]2356[[package]]
2319name = "thiserror-impl"2357name = "thiserror-impl"
2320version = "1.0.60"2358version = "1.0.61"
2321source = "registry+https://github.com/rust-lang/crates.io-index"2359source = "registry+https://github.com/rust-lang/crates.io-index"
2322checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"2360checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
2323dependencies = [2361dependencies = [
2324 "proc-macro2",2362 "proc-macro2",
2325 "quote",2363 "quote",
2326 "syn 2.0.63",2364 "syn 2.0.66",
2327]2365]
23282366
2329[[package]]2367[[package]]
2401dependencies = [2439dependencies = [
2402 "proc-macro2",2440 "proc-macro2",
2403 "quote",2441 "quote",
2404 "syn 2.0.63",2442 "syn 2.0.66",
2405]2443]
24062444
2407[[package]]2445[[package]]
24382476
2439[[package]]2477[[package]]
2440name = "toml"2478name = "toml"
2441version = "0.8.12"2479version = "0.8.13"
2442source = "registry+https://github.com/rust-lang/crates.io-index"2480source = "registry+https://github.com/rust-lang/crates.io-index"
2443checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"2481checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba"
2444dependencies = [2482dependencies = [
2445 "serde",2483 "serde",
2446 "serde_spanned",2484 "serde_spanned",
24502488
2451[[package]]2489[[package]]
2452name = "toml_datetime"2490name = "toml_datetime"
2453version = "0.6.5"2491version = "0.6.6"
2454source = "registry+https://github.com/rust-lang/crates.io-index"2492source = "registry+https://github.com/rust-lang/crates.io-index"
2455checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"2493checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
2456dependencies = [2494dependencies = [
2457 "serde",2495 "serde",
2458]2496]
24592497
2460[[package]]2498[[package]]
2461name = "toml_edit"2499name = "toml_edit"
2462version = "0.22.12"2500version = "0.22.13"
2463source = "registry+https://github.com/rust-lang/crates.io-index"2501source = "registry+https://github.com/rust-lang/crates.io-index"
2464checksum = "d3328d4f68a705b2a4498da1d580585d39a6510f98318a2cec3018a7ec61ddef"2502checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
2465dependencies = [2503dependencies = [
2466 "indexmap",2504 "indexmap",
2467 "serde",2505 "serde",
2489dependencies = [2527dependencies = [
2490 "proc-macro2",2528 "proc-macro2",
2491 "quote",2529 "quote",
2492 "syn 2.0.63",2530 "syn 2.0.66",
2493]2531]
24942532
2495[[package]]2533[[package]]
2708 "once_cell",2746 "once_cell",
2709 "proc-macro2",2747 "proc-macro2",
2710 "quote",2748 "quote",
2711 "syn 2.0.63",2749 "syn 2.0.66",
2712 "wasm-bindgen-shared",2750 "wasm-bindgen-shared",
2713]2751]
27142752
2730dependencies = [2768dependencies = [
2731 "proc-macro2",2769 "proc-macro2",
2732 "quote",2770 "quote",
2733 "syn 2.0.63",2771 "syn 2.0.66",
2734 "wasm-bindgen-backend",2772 "wasm-bindgen-backend",
2735 "wasm-bindgen-shared",2773 "wasm-bindgen-shared",
2736]2774]
2964dependencies = [3002dependencies = [
2965 "proc-macro2",3003 "proc-macro2",
2966 "quote",3004 "quote",
2967 "syn 2.0.63",3005 "syn 2.0.66",
2968]3006]
29693007
modifiedCargo.tomldiffbeforeafterboth
6[workspace.dependencies]6[workspace.dependencies]
7nixlike = { path = "./crates/nixlike" }7nixlike = { path = "./crates/nixlike" }
8better-command = { path = "./crates/better-command" }8better-command = { path = "./crates/better-command" }
9bifrostlink = "0.1.0"
10uuid = { version = "1.7.0", features = ["v4"] }9fleet-shared = { path = "./crates/fleet-shared" }
11tokio = { version = "1.36.0", features = ["fs", "rt", "macros", "sync", "time", "rt-multi-thread"] }10tokio = { version = "1.36.0", features = [
11 "fs",
12 "rt",
13 "macros",
14 "sync",
15 "time",
16 "rt-multi-thread",
17] }
18# Using fixed version for rust on stable nixos branches.
19clap = { version = ">=4.4, <4.5", features = [
20 "derive",
21 "env",
22 "wrap_help",
23 "unicode",
24] }
25age = { version = "0.10", features = ["ssh"] }
26anyhow = "1.0"
27tracing = "0.1"
28tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
29serde = { version = "1.0", features = ["derive"] }
30serde_json = "1.0"
31tempfile = "3.10"
12fleet-shared = { path = "./crates/fleet-shared" }32nix = {version = "0.27.1", features = ["user", "fs"]}
1333
modifiedcmds/fleet/Cargo.tomldiffbeforeafterboth
9nixlike.workspace = true9nixlike.workspace = true
10better-command.workspace = true10better-command.workspace = true
11tokio.workspace = true11tokio.workspace = true
12anyhow = "1.0"12clap.workspace = true
13serde = { version = "1.0", features = ["derive"] }13age = { workspace = true, features = ["armor"] }
14anyhow.workspace = true
15tracing.workspace = true
16tracing-subscriber.workspace = true
17serde.workspace = true
14serde_json = "1.0"18serde_json.workspace = true
19tempfile.workspace = true
15time = { version = "0.3", features = ["serde"] }20time = { version = "0.3", features = ["serde"] }
16tempfile = "3.10"
17once_cell = "1.19"21once_cell = "1.19"
18hostname = "0.3"22hostname = "0.3"
19age-core = "0.10"23age-core = "0.10"
20peg = "0.8"24peg = "0.8"
21age = { version = "0.10", features = ["ssh", "armor"] }
22base64 = "0.22.1"25base64 = "0.22.1"
23chrono = { version = "0.4", features = ["serde"] }26chrono = { version = "0.4", features = ["serde"] }
24# Using fixed version for rust on stable nixos branches.
25clap = { version = ">=4.4, <4.5", features = [
26 "derive",
27 "env",
28 "wrap_help",
29 "unicode",
30] }
31tracing = "0.1"
32tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
33tokio-util = { version = "0.7", features = ["codec"] }27tokio-util = { version = "0.7", features = ["codec"] }
34async-trait = "0.1"28async-trait = "0.1"
35futures = "0.3"29futures = "0.3"
40 "supports-color",34 "supports-color",
41 "supports-colors",35 "supports-colors",
42] }36] }
43r2d2 = "0.8.10"
44abort-on-drop = "0.2"37abort-on-drop = "0.2"
45unindent = "0.2"
46regex = "1.10"38regex = "1.10"
47openssh = "0.10"39openssh = "0.10"
48crossterm = { version = "0.27.0", features = ["use-dev-tty"] }40crossterm = { version = "0.27.0", features = ["use-dev-tty"] }
51tracing-indicatif = { version = "0.3", optional = true }43tracing-indicatif = { version = "0.3", optional = true }
52human-repr = { version = "1.1", optional = true }44human-repr = { version = "1.1", optional = true }
53indicatif = { version = "0.17", optional = true }45indicatif = { version = "0.17", optional = true }
46nix-eval = { version = "0.1.0", path = "../../crates/nix-eval" }
5447
55[features]48[features]
56# Not quite stable49# Not quite stable
57indicatif = [50indicatif = [
58 "tracing-indicatif",51 "dep:tracing-indicatif",
59 "dep:indicatif",52 "dep:indicatif",
60 "human-repr",53 "dep:human-repr",
61 "better-command/indicatif",54 "better-command/indicatif",
62]55]
6356
modifiedcmds/fleet/src/better_nix_eval.rsdiffbeforeafterboth
12use better_command::{ClonableHandler, Handler, NixHandler, NoopHandler};12use better_command::{ClonableHandler, Handler, NixHandler, NoopHandler};
13use futures::StreamExt;13use futures::StreamExt;
14use itertools::Itertools;14use itertools::Itertools;
15use r2d2::{Pool, PooledConnection};
16use serde::de::DeserializeOwned;15use serde::de::DeserializeOwned;
17use serde::{Deserialize, Serialize};16use serde::{Deserialize, Serialize};
18use tokio::io::AsyncWriteExt;17use tokio::io::AsyncWriteExt;
19use tokio::process::{ChildStderr, ChildStdin, ChildStdout, Command};18use tokio::process::{ChildStderr, ChildStdin, ChildStdout, Command};
20use tokio::select;19use tokio::select;
21use tokio::sync::{mpsc, oneshot, Mutex};20use tokio::sync::{mpsc, oneshot, Mutex};
22use tokio_util::codec::{FramedRead, LinesCodec};
23use tracing::{debug, error, warn, Level};21use tracing::{debug, error, warn, Level};
24
25const REPL_DELIMITER: &str = "\"FLEET_MAGIC_REPL_DELIMITER\"";
26
27pub struct NixSessionInner {
28 full_delimiter: String,
29 nix_handler: ClonableHandler<NixHandler>,
30 out: OutputHandler,
31 stdin: ChildStdin,
32 string_wrapping: (String, String),
33 number_wrapping: (String, String),
34
35 executing_command: Arc<Mutex<()>>,
36
37 next_id: u32,
38 free_list: Vec<u32>,
39}
40const TRAIN_STRING: &str = "\"TRAIN_STRING\"";
41const TRAIN_NUMBER: &str = "13141516";
42
43#[must_use]
44struct ErrorCollector<'i, H> {
45 collected: Vec<String>,
46 inner: &'i mut H,
47}
48impl<'i, H> ErrorCollector<'i, H> {
49 fn new(inner: &'i mut H) -> Self {
50 Self {
51 collected: vec![],
52 inner,
53 }
54 }
55}
56impl<H> ErrorCollector<'_, H> {
57 fn handle_line_inner(&mut self, msg: &str) -> bool {
58 let Some(msg) = msg.strip_prefix("@nix ") else {
59 return false;
60 };
61 #[derive(Deserialize)]
62 struct ErrorAction {
63 action: String,
64 level: u32,
65 msg: String,
66 }
67 let Ok(act) = serde_json::from_str::<ErrorAction>(msg) else {
68 return false;
69 };
70 if act.action != "msg" || act.level != 0 {
71 return false;
72 }
73 self.collected.push(act.msg);
74 true
75 }
76 fn finish(self) -> Result<()> {
77 // fn dedent(s: String) -> String {
78 // s.split('\n').filter(|s| !s.trim().is_empty()).map(|v| v.)
79 // }
80 if !self.collected.is_empty() {
81 bail!(
82 "{}",
83 self.collected
84 .iter()
85 .map(|v| {
86 if let Some(f) = v.strip_prefix("\u{1b}[31;1merror:\u{1b}[0m ") {
87 let v = unindent::unindent(f.trim_start());
88 v.trim().to_owned()
89 } else {
90 v.to_owned()
91 }
92 })
93 .join("\n")
94 );
95 }
96 Ok(())
97 }
98 fn flush(self) {
99 for line in self.collected {
100 warn!("{line}");
101 }
102 }
103}
104impl<H: Handler> Handler for ErrorCollector<'_, H> {
105 fn handle_line(&mut self, e: &str) {
106 if self.handle_line_inner(e) {
107 return;
108 }
109 self.inner.handle_line(e)
110 }
111}
112
113enum OutputLine {
114 Out(String),
115 Err(String),
116}
117struct OutputHandler {
118 rx: mpsc::Receiver<OutputLine>,
119 _cancel_handle: oneshot::Receiver<()>,
120}
121impl OutputHandler {
122 fn new(out: ChildStdout, err: ChildStderr) -> Self {
123 let mut out = FramedRead::new(out, LinesCodec::new());
124 let mut err = FramedRead::new(err, LinesCodec::new());
125 let (tx, rx) = mpsc::channel(20);
126 let (mut cancelled, _cancel_handle) = oneshot::channel();
127 tokio::spawn(async move {
128 loop {
129 select! {
130 // We should receive errors earlier than synchronization
131 biased;
132 e = err.next() => {
133 let Some(Ok(e)) = e else {
134 if e.is_some() {
135 error!("bad repl stderr: {e:?}");
136 }
137 continue;
138 };
139 let _ = tx.send(OutputLine::Err(e)).await;
140 }
141 o = out.next() => {
142 let Some(Ok(o)) = o else {
143 if o.is_some() {
144 error!("bad repl stdout: {o:?}");
145 }
146 continue;
147 };
148 let _ = tx.send(OutputLine::Out(o)).await;
149 }
150 // Reader doesn't care about stdout, as this is cancelled.
151 // Error still might be useful, to process leftover span closures?
152 _ = cancelled.closed() => {
153 break;
154 }
155 }
156 }
157 });
158 Self { rx, _cancel_handle }
159 }
160 async fn next(&mut self) -> Option<OutputLine> {
161 self.rx.recv().await
162 }
163}
164
165struct WarnHandler;
166impl Handler for WarnHandler {
167 fn handle_line(&mut self, e: &str) {
168 warn!(target: "nix", "{e}")
169 }
170}
171
172impl NixSessionInner {
173 async fn new(flake: &OsStr, extra_args: impl IntoIterator<Item = &OsStr>) -> Result<Self> {
174 let mut cmd = Command::new("nix");
175 cmd.arg("repl")
176 .arg(flake)
177 .arg("--log-format")
178 .arg("internal-json");
179 for arg in extra_args {
180 cmd.arg(arg);
181 }
182 cmd.stdin(Stdio::piped());
183 cmd.stdout(Stdio::piped());
184 cmd.stderr(Stdio::piped());
185 let cmd = cmd.spawn()?;
186 let stdout = cmd.stdout.unwrap();
187 let stderr = cmd.stderr.unwrap();
188 let mut out = OutputHandler::new(stdout, stderr);
189 let mut stdin = cmd.stdin.unwrap();
190 // Standard repl hello doesn't work with internal-json logger
191 stdin.write_all(REPL_DELIMITER.as_bytes()).await?;
192 stdin.write_all(b"\n").await?;
193 stdin.flush().await?;
194 let nix_handler = NixHandler::default();
195 let mut full_delimiter = None;
196 let mut errors = vec![];
197 while let Some(line) = out.next().await {
198 let line = match line {
199 OutputLine::Out(o) => o,
200 OutputLine::Err(_e) => {
201 // Handle startup errors, but skip repl hello?
202 errors.push(_e);
203 continue;
204 }
205 };
206 if line.contains(REPL_DELIMITER) {
207 debug!("discovered repl delimiter with added colors: {line}");
208 full_delimiter = Some(line.to_owned());
209 break;
210 }
211 }
212 let Some(full_delimiter) = full_delimiter else {
213 for e in errors {
214 error!("{e}");
215 }
216 bail!("failed to discover delimiter");
217 };
218 let mut res = Self {
219 full_delimiter,
220 nix_handler: ClonableHandler::new(nix_handler),
221 out,
222 stdin,
223 string_wrapping: Default::default(),
224 number_wrapping: Default::default(),
225
226 executing_command: Arc::new(Mutex::new(())),
227
228 next_id: 0,
229 free_list: vec![],
230 };
231 res.train().await?;
232 Ok(res)
233 }
234 async fn train(&mut self) -> Result<()> {
235 {
236 let full_string = self
237 .execute_expression_raw(TRAIN_STRING, &mut NoopHandler)
238 .await?;
239 let string_offset = full_string.find(TRAIN_STRING).expect("contained");
240 let string_prefix = &full_string[..string_offset];
241 let string_suffix = &full_string[string_offset + TRAIN_STRING.len()..];
242 self.string_wrapping = (string_prefix.to_owned(), string_suffix.to_owned());
243 }
244 {
245 let full_number = self
246 .execute_expression_raw(TRAIN_NUMBER, &mut NoopHandler)
247 .await?;
248 let number_offset = full_number.find(TRAIN_NUMBER).expect("contained");
249 let number_prefix = &full_number[..number_offset];
250 let number_suffix = &full_number[number_offset + TRAIN_NUMBER.len()..];
251 self.number_wrapping = (number_prefix.to_owned(), number_suffix.to_owned());
252 }
253 Ok(())
254 }
255 async fn send_command(&mut self, cmd: impl AsRef<[u8]>) -> Result<()> {
256 if tracing::enabled!(Level::DEBUG) && cmd.as_ref() != REPL_DELIMITER.as_bytes() {
257 let cmd_str = String::from_utf8_lossy(cmd.as_ref());
258 tracing::debug!("{cmd_str}");
259 };
260 self.stdin.write_all(cmd.as_ref()).await?;
261 self.stdin.write_all(b"\n").await?;
262 Ok(())
263 }
264 async fn read_until_delimiter(&mut self, err_handler: &mut dyn Handler) -> Result<String> {
265 let mut out = String::new();
266 while let Some(line) = self.out.next().await {
267 let line = match line {
268 OutputLine::Out(out) => out,
269 OutputLine::Err(err) => {
270 err_handler.handle_line(&err);
271 continue;
272 }
273 };
274 if line == self.full_delimiter {
275 return Ok(out);
276 }
277 if !out.is_empty() {
278 out.push('\n');
279 }
280 out.push_str(&line);
281 }
282 bail!("didn't reached delimiter");
283 }
284 async fn execute_expression_number(&mut self, expr: impl AsRef<[u8]>) -> Result<u64> {
285 let num = self.number_wrapping.clone();
286 let n = self.execute_expression_wrapping(expr, &num).await?;
287 Ok(n.parse::<u64>()?)
288 }
289 async fn execute_expression_string(&mut self, expr: impl AsRef<[u8]>) -> Result<String> {
290 let num = self.string_wrapping.clone();
291 let n = self.execute_expression_wrapping(expr, &num).await?;
292 let str: String = serde_json::from_str(&n)?;
293 Ok(str)
294 }
295 async fn execute_expression_to_json<V: DeserializeOwned>(
296 &mut self,
297 expr: impl AsRef<[u8]>,
298 ) -> Result<V> {
299 let mut fexpr = b"builtins.toJSON (".to_vec();
300 fexpr.extend_from_slice(expr.as_ref());
301 fexpr.push(b')');
302 let v = self
303 .execute_expression_string(fexpr)
304 .await
305 .context("string expression")?;
306 serde_json::from_str(&v).context("json parse")
307 }
308 async fn execute_expression_wrapping(
309 &mut self,
310 expr: impl AsRef<[u8]>,
311 wrapping: &(String, String),
312 ) -> Result<String> {
313 let mut nix_handler = self.nix_handler.clone();
314 let mut collected = ErrorCollector::new(&mut nix_handler);
315 let res = self.execute_expression_raw(expr, &mut collected).await?;
316 if res.is_empty() {
317 collected.finish()?;
318 bail!("expected expression, got nothing")
319 } else {
320 collected.flush()
321 };
322 let Some(res) = res.strip_prefix(&wrapping.0) else {
323 bail!("invalid type")
324 };
325 let Some(res) = res.strip_suffix(&wrapping.1) else {
326 bail!("invalid type")
327 };
328 Ok(res.to_owned())
329 }
330 async fn execute_expression_empty(&mut self, expr: impl AsRef<[u8]>) -> Result<()> {
331 let mut nix_handler = self.nix_handler.clone();
332 let mut collected = ErrorCollector::new(&mut nix_handler);
333 let v = self.execute_expression_raw(expr, &mut collected).await?;
334 collected.finish()?;
335 ensure!(v.is_empty(), "unexpected expression result");
336 Ok(())
337 }
338 async fn execute_expression_raw(
339 &mut self,
340 expr: impl AsRef<[u8]>,
341 err_handler: &mut dyn Handler,
342 ) -> Result<String> {
343 // Prevent two commands from being executed in parallel, messing with each other.
344 let _lock = self.executing_command.clone();
345 let _guard = _lock.lock().await;
346
347 self.send_command(expr).await?;
348 // It will be echoed
349 self.send_command(REPL_DELIMITER).await?;
350 self.read_until_delimiter(err_handler).await
351 }
352 async fn execute_assign(&mut self, expr: impl AsRef<str>) -> Result<u32> {
353 let id = self.allocate_id();
354 self.execute_expression_empty(format!("sess_field_{id} = {}", expr.as_ref()))
355 .await?;
356 Ok(id)
357 }
358
359 /// Id should be immediately used
360 fn allocate_id(&mut self) -> u32 {
361 if let Some(free) = self.free_list.pop() {
362 free
363 } else {
364 let v = self.next_id;
365 self.next_id += 1;
366 v
367 }
368 }
369 // Nix has no way to deallocate variable, yet GC will correct everything not reachable.
370 // async fn free_id(&mut self, id: u32) -> Result<()> {
371 // self.execute_expression_empty(format!("sess_field_{id} = null"))
372 // .await?;
373 // self.free_list.push(id);
374 // Ok(())
375 // }
376}
377
378#[derive(Clone)]
379pub struct NixSession(Arc<tokio::sync::Mutex<PooledConnection<NixSessionPoolInner>>>);
380
381#[derive(Clone)]
382pub struct NixExprBuilder {
383 out: String,
384 used_fields: Vec<Field>,
385}
386impl NixExprBuilder {
387 pub fn object() -> Self {
388 NixExprBuilder {
389 out: "{ ".to_owned(),
390 used_fields: Vec::new(),
391 }
392 }
393 pub fn string(s: &str) -> Self {
394 NixExprBuilder {
395 out: nixlike::serialize(s)
396 .expect("no problems with serializing_string")
397 .trim_end()
398 .to_owned(),
399 used_fields: Vec::new(),
400 }
401 }
402 pub fn serialized(v: impl Serialize) -> Self {
403 let serialized = nixlike::serialize(v).expect("invalid value for apply");
404 Self {
405 out: serialized.trim_end().to_owned(),
406 used_fields: Vec::new(),
407 }
408 }
409 pub fn field(f: Field) -> Self {
410 Self {
411 out: format!("sess_field_{}", f.0.value.expect("no value")),
412 used_fields: vec![f],
413 }
414 }
415 pub fn end_obj(&mut self) {
416 self.out.push('}');
417 }
418 pub fn obj_key(&mut self, name: Self, value: Self) {
419 self.out.push_str(r#""${"#);
420 self.extend(name);
421 self.out.push_str(r#"}" = "#);
422 self.extend(value);
423 self.out.push_str("; ");
424 }
425
426 pub fn extend(&mut self, e: Self) {
427 self.out.push_str(&e.out);
428 self.used_fields.extend(e.used_fields);
429 }
430
431 #[allow(dead_code)]
432 pub fn session(&self) -> NixSession {
433 let mut session = None;
434 for ele in &self.used_fields {
435 if session.is_none() {
436 session = Some(ele.0.session.clone());
437 continue;
438 }
439 let session = &session.as_ref().expect("checked").0;
440 let ele_sess = &ele.0.session.0;
441 assert!(
442 Arc::ptr_eq(session, ele_sess),
443 "can't mix fields from different session"
444 );
445 }
446 session.expect("expr without fields used")
447 }
448 #[allow(dead_code)]
449 pub fn index_attr(&mut self, s: &str) {
450 let escaped = nixlike::serialize(s).expect("string");
451 self.out.push('.');
452 self.out.push_str(escaped.trim_end());
453 }
454}
455
456#[macro_export]
457macro_rules! nix_expr_inner {
458 //(@munch_object FIXME: value should be arbitrary nix_expr_inner input... Time to write proc-macro?
459 (@obj($o:ident) $field:ident, $($tt:tt)*) => {{
460 $o.obj_key(
461 NixExprBuilder::string(stringify!($field)),
462 NixExprBuilder::field($field),
463 );
464 nix_expr_inner!(@obj($o) $($tt)*);
465 }};
466 (@obj($o:ident) $field:ident: $v:block, $($tt:tt)*) => {{
467 $o.obj_key(
468 NixExprBuilder::string(stringify!($field)),
469 NixExprBuilder::serialized(&$v),
470 );
471 nix_expr_inner!(@obj($o) $($tt)*);
472 }};
473 (@obj($o:ident)) => {{}};
474 (Obj { $($tt:tt)* }) => {{
475 use $crate::{better_nix_eval::NixExprBuilder, nix_expr_inner};
476 let mut out = NixExprBuilder::object();
477 nix_expr_inner!(@obj(out) $($tt)*);
478 out.end_obj();
479 out
480 }};
481 (@field($o:ident) . $var:ident $($tt:tt)*) => {{
482 $o.index_attr(stringify!($var));
483 nix_expr_inner!(@field($o) $($tt)*);
484 }};
485 (@field($o:ident) [{ $v:expr }] $($tt:tt)*) => {{
486 $o.push(Index::attr(&$v));
487 nix_expr_inner!(@o($o) $($tt)*);
488 }};
489 (@field($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{
490 $o.push(Index::Expr($crate::nix_expr_inner!($($var)+)));
491 nix_expr_inner!(@o($o) $($tt)*);
492 }};
493 (@field($o:ident) ($($var:tt)*) $($tt:tt)*) => {
494 $o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));
495 nix_expr_inner!(@o($o) $($tt)*);
496 };
497 (@field($o:ident)) => {};
498 ($field:ident $($tt:tt)*) => {{
499 use $crate::{better_nix_eval::NixExprBuilder, nix_expr_inner};
500 #[allow(unused_mut, reason = "might be used if indexed")]
501 let mut out = NixExprBuilder::field($field.clone());
502 nix_expr_inner!(@field(out) $($tt)*);
503 out
504 }};
505 ($v:literal) => {{
506 use $crate::better_nix_eval::NixExprBuilder;
507 NixExprBuilder::string($v)
508 }};
509 ({$v:expr}) => {{
510 use $crate::better_nix_eval::NixExprBuilder;
511 NixExprBuilder::serialized(&$v)
512 }}
513}
514#[macro_export]
515macro_rules! nix_expr {
516 ($($tt:tt)+) => {{
517 use $crate::{better_nix_eval::{NixExprBuilder, Field}, nix_expr_inner};
518 let expr = nix_expr_inner!($($tt)+);
519 Field::new(expr.session(), expr.out)
520 }};
521}
522
523#[macro_export]
524macro_rules! nix_go {
525 (@o($o:ident) . $var:ident $($tt:tt)*) => {{
526 $o.push(Index::attr(stringify!($var)));
527 nix_go!(@o($o) $($tt)*);
528 }};
529 (@o($o:ident) [{ $v:expr }] $($tt:tt)*) => {{
530 $o.push(Index::attr(&$v));
531 nix_go!(@o($o) $($tt)*);
532 }};
533 (@o($o:ident) [ $($var:tt)+ ] $($tt:tt)*) => {{
534 $o.push(Index::Expr($crate::nix_expr_inner!($($var)+)));
535 nix_go!(@o($o) $($tt)*);
536 }};
537 (@o($o:ident) ($($var:tt)*) $($tt:tt)*) => {
538 $o.push(Index::ExprApply($crate::nix_expr_inner!($($var)+)));
539 nix_go!(@o($o) $($tt)*);
540 };
541 (@o($o:ident) | $($var:tt)*) => {
542 $o.push(Index::Pipe($crate::nix_expr_inner!($($var)+)));
543 };
544 (@o($o:ident)) => {};
545 ($field:ident $($tt:tt)+) => {{
546 use $crate::{nix_go, better_nix_eval::Index};
547 let field = $field.clone();
548 let mut out = vec![];
549 nix_go!(@o(out) $($tt)*);
550 field.select(out).await?
551 }}
552}
553#[macro_export]
554macro_rules! nix_go_json {
555 ($($tt:tt)*) => {{
556 $crate::nix_go!($($tt)*).as_json().await?
557 }};
558}
559
560#[derive(Clone)]
561pub enum Index {
562 Var(String),
563 String(String),
564 #[allow(dead_code)]
565 Apply(String),
566 #[allow(dead_code)]
567 Expr(NixExprBuilder),
568 ExprApply(NixExprBuilder),
569 Pipe(NixExprBuilder),
570}
571impl Index {
572 pub fn var(v: impl AsRef<str>) -> Self {
573 let v = v.as_ref();
574 assert!(
575 !(v.contains('.') | v.contains(' ')),
576 "bad variable name: {v}"
577 );
578 Self::Var(v.to_owned())
579 }
580 pub fn attr(v: impl AsRef<str>) -> Self {
581 Self::String(v.as_ref().to_owned())
582 }
583 #[allow(dead_code)]
584 pub fn apply(v: impl Serialize) -> Self {
585 let serialized = nixlike::serialize(v).expect("invalid value for apply");
586 Self::Apply(serialized.trim_end().to_owned())
587 }
588}
589impl Display for Index {
590 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
591 match self {
592 Index::Var(v) => {
593 write!(f, "{v}")
594 }
595 Index::String(k) => {
596 let v = nixlike::format_identifier(k.as_str());
597 write!(f, ".{v}")
598 }
599 Index::Apply(o) => {
600 write!(f, "<apply>({o})")
601 }
602 Index::Expr(e) => {
603 write!(f, "[{}]", e.out)
604 }
605 Index::ExprApply(e) => {
606 write!(f, "<apply>({})", e.out)
607 }
608 Index::Pipe(e) => {
609 write!(f, "<map>({})", e.out)
610 }
611 }
612 }
613}
614impl fmt::Debug for Index {
615 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
616 write!(f, "{self}")
617 }
618}
619struct PathDisplay<'i>(&'i [Index]);
620impl Display for PathDisplay<'_> {
621 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
622 for i in self.0 {
623 write!(f, "{i}")?;
624 }
625 Ok(())
626 }
627}
628struct FieldInner {
629 full_path: Option<Vec<Index>>,
630 session: NixSession,
631 value: Option<u32>,
632}
633fn context(op: &str, full_path: Option<&[Index]>, query: &str) -> String {
634 if let Some(full_path) = &full_path {
635 format!("on {op}, full path: {}", PathDisplay(full_path))
636 } else {
637 format!("query: {query:?}")
638 }
639}
640#[derive(Clone)]
641pub struct Field(Arc<FieldInner>);
642impl Field {
643 fn root(session: NixSession) -> Self {
644 Self(Arc::new(FieldInner {
645 full_path: Some(vec![]),
646 session,
647 value: None,
648 }))
649 }
650 async fn new(session: NixSession, query: &str) -> Result<Self> {
651 let vid = session
652 .0
653 .lock()
654 .await
655 .execute_assign(query)
656 .await
657 .with_context(|| context("new root", None, query))?;
658 Ok(Self(Arc::new(FieldInner {
659 full_path: None,
660 session,
661 value: Some(vid),
662 })))
663 }
664 pub async fn field(session: NixSession, field: &str) -> Result<Self> {
665 Self::root(session).select([Index::var(field)]).await
666 }
667 pub async fn select<'a>(&self, name: impl IntoIterator<Item = Index>) -> Result<Self> {
668 let mut used_fields = Vec::new();
669 let mut name = name.into_iter();
670
671 let mut full_path = self.0.full_path.clone();
672 let mut query = if let Some(id) = self.0.value {
673 format!("sess_field_{id}")
674 } else {
675 let first = name.next();
676 if let Some(Index::Var(i)) = first {
677 if let Some(full_path) = &mut full_path {
678 full_path.push(Index::Var(i.clone()));
679 }
680 i.clone()
681 } else {
682 panic!("first path item should be variable, got {first:?}")
683 }
684 };
685 for v in name {
686 if let Some(full_path) = &mut full_path {
687 full_path.push(v.clone());
688 }
689 match v {
690 Index::Var(_) => panic!("var item may only be first"),
691 Index::String(s) => {
692 let escaped = nixlike::serialize(s)?;
693 query.push('.');
694 query.push_str(escaped.trim());
695 }
696 Index::Apply(a) => {
697 // In cases like `a {}.b` first `{}.b` will be evaluated, so `a {}` should be encased in `()`
698 query = format!("({query} {a})");
699 }
700 Index::Expr(e) => {
701 let index = Field::new(self.0.session.clone(), &e.out).await?;
702 used_fields.push(index.clone());
703 query.push('.');
704 let index = format!("${{sess_field_{}}}", index.0.value.expect("value"));
705 query.push_str(&index);
706 }
707 Index::ExprApply(e) => {
708 let index = Field::new(self.0.session.clone(), &e.out).await?;
709 used_fields.push(index.clone());
710 query.push(' ');
711 let index = format!("sess_field_{}", index.0.value.expect("value"));
712 query.push_str(&index);
713 query = format!("({query})");
714 }
715 Index::Pipe(v) => {
716 let index = Field::new(self.0.session.clone(), &v.out).await?;
717 used_fields.push(index.clone());
718 let index = format!("sess_field_{}", index.0.value.expect("value"));
719 query = format!("({index} {query})");
720 }
721 }
722 }
723
724 let vid = self
725 .0
726 .session
727 .0
728 .lock()
729 .await
730 .execute_assign(&query)
731 .await
732 .with_context(|| {
733 if let Some(full_path) = &full_path {
734 format!("full path: {}", PathDisplay(full_path))
735 } else {
736 format!("query: {query:?}")
737 }
738 })?;
739 Ok(Self(Arc::new(FieldInner {
740 full_path,
741 session: self.0.session.clone(),
742 value: Some(vid),
743 })))
744 }
745 pub async fn as_json<V: DeserializeOwned>(&self) -> Result<V> {
746 let id = self.0.value.expect("can't serialize root field");
747 let query = format!("sess_field_{id}");
748 self.0
749 .session
750 .0
751 .lock()
752 .await
753 .execute_expression_to_json(&query)
754 .await
755 .with_context(|| context("as_json", self.0.full_path.as_deref(), &query))
756 }
757 #[allow(dead_code)]
758 pub async fn has_field(&self, name: &str) -> Result<bool> {
759 let id = self.0.value.expect("can't list root fields");
760 let key = nixlike::escape_string(name);
761 let query = format!("sess_field_{id} ? {key}");
762 self.0
763 .session
764 .0
765 .lock()
766 .await
767 .execute_expression_to_json(&query)
768 .await
769 .with_context(|| context("has_field", self.0.full_path.as_deref(), &query))
770 }
771 pub async fn list_fields(&self) -> Result<Vec<String>> {
772 let id = self.0.value.expect("can't list root fields");
773 let query = format!("builtins.attrNames sess_field_{id}");
774 self.0
775 .session
776 .0
777 .lock()
778 .await
779 .execute_expression_to_json(&query)
780 .await
781 .with_context(|| context("list field", self.0.full_path.as_deref(), &query))
782 }
783 pub async fn type_of(&self) -> Result<String> {
784 let id = self.0.value.expect("can't list root fields");
785 let query = format!("builtins.typeOf sess_field_{id}");
786 self.0
787 .session
788 .0
789 .lock()
790 .await
791 .execute_expression_to_json(&query)
792 .await
793 .with_context(|| context("type_of", self.0.full_path.as_deref(), &query))
794 }
795 #[allow(dead_code)]
796 pub async fn import(&self) -> Result<Self> {
797 let import = Self::new(self.0.session.clone(), "import").await?;
798 Ok(nix_go!(self | import))
799 }
800 pub async fn build(&self) -> Result<HashMap<String, PathBuf>> {
801 let id = self.0.value.expect("can't use build on not-value");
802 let query = format!(":b sess_field_{id}");
803 let vid = self
804 .0
805 .session
806 .0
807 .lock()
808 .await
809 .execute_expression_raw(&query, &mut NixHandler::default())
810 .await?;
811 ensure!(
812 !vid.is_empty(),
813 "build failed: {}",
814 context("build", self.0.full_path.as_deref(), &query),
815 );
816 let Some(vid) = vid.strip_prefix("This derivation produced the following outputs:\n")
817 else {
818 panic!("unexpected build output: {vid:?}");
819 };
820 let outputs = vid
821 .split('\n')
822 .filter(|v| !v.is_empty())
823 .map(|v| v.split_once(" -> ").expect("unexpected build output"))
824 .map(|(a, b)| (a.trim_start().to_owned(), PathBuf::from(b)))
825 .collect();
826 Ok(outputs)
827 }
828}
829impl Drop for FieldInner {
830 fn drop(&mut self) {
831 if let Some(id) = self.value {
832 if let Ok(mut lock) = self.session.0.try_lock() {
833 lock.free_list.push(id)
834 }
835 // Leaked
836 }
837 }
838}
839struct NixSessionPoolInner {
840 flake: OsString,
841 nix_args: Vec<OsString>,
842}
843
844#[derive(Debug)]
845pub struct NixPoolError(anyhow::Error);
846impl From<anyhow::Error> for NixPoolError {
847 fn from(value: anyhow::Error) -> Self {
848 Self(value)
849 }
850}
851impl std::error::Error for NixPoolError {}
852impl std::fmt::Display for NixPoolError {
853 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
854 self.0.fmt(f)
855 }
856}
857impl r2d2::ManageConnection for NixSessionPoolInner {
858 type Connection = NixSessionInner;
859 type Error = NixPoolError;
860 fn connect(&self) -> std::result::Result<Self::Connection, Self::Error> {
861 let _v = TOKIO_RUNTIME
862 .get()
863 .expect("missed tokio runtime init!")
864 .enter();
865 Ok(futures::executor::block_on(NixSessionInner::new(
866 self.flake.as_os_str(),
867 self.nix_args.iter().map(OsString::as_os_str),
868 ))?)
869 }
870
871 fn is_valid(&self, conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> {
872 let _v = TOKIO_RUNTIME
873 .get()
874 .expect("missed tokio runtime init!")
875 .enter();
876 let res = futures::executor::block_on(conn.execute_expression_number("2 + 2"))?;
877 if res != 4 {
878 return Err(anyhow!("sanity check failed").into());
879 };
880 Ok(())
881 }
882
883 fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
884 false
885 }
886}
887pub struct NixSessionPool(Pool<NixSessionPoolInner>);
888impl NixSessionPool {
889 pub async fn new(flake: OsString, nix_args: Vec<OsString>) -> Result<Self> {
890 let inner = tokio::task::block_in_place(|| {
891 r2d2::Builder::<NixSessionPoolInner>::new()
892 .min_idle(Some(0))
893 .build(NixSessionPoolInner { flake, nix_args })
894 })?;
895 Ok(Self(inner))
896 }
897 pub async fn get(&self) -> Result<NixSession> {
898 let v = tokio::task::block_in_place(|| self.0.get())?;
899 Ok(NixSession(Arc::new(tokio::sync::Mutex::new(v))))
900 }
901}
902
903pub static TOKIO_RUNTIME: OnceLock<tokio::runtime::Handle> = OnceLock::new();
90422
23
24
modifiedcmds/fleet/src/cmds/build_systems.rsdiffbeforeafterboth
44
5use crate::command::MyCommand;5use crate::command::MyCommand;
6use crate::host::{Config, ConfigHost};6use crate::host::{Config, ConfigHost};
7use crate::nix_go;
8use anyhow::{anyhow, Result};7use anyhow::{anyhow, Result};
9use clap::{Parser, ValueEnum};8use clap::{Parser, ValueEnum};
10use itertools::Itertools as _;9use itertools::Itertools as _;
10use nix_eval::nix_go;
11use tokio::{task::LocalSet, time::sleep};11use tokio::{task::LocalSet, time::sleep};
12use tracing::{error, field, info, info_span, warn, Instrument};12use tracing::{error, field, info, info_span, warn, Instrument};
1313
modifiedcmds/fleet/src/cmds/info.rsdiffbeforeafterboth
1use std::collections::BTreeSet;1use std::collections::BTreeSet;
22
3use crate::host::Config;3use crate::host::Config;
4use crate::nix_go_json;
5use anyhow::{ensure, Result};4use anyhow::{ensure, Result};
6use clap::Parser;5use clap::Parser;
6use nix_eval::nix_go_json;
77
8#[derive(Parser)]8#[derive(Parser)]
9pub struct Info {9pub struct Info {
modifiedcmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth
11use crossterm::{terminal, tty::IsTty};11use crossterm::{terminal, tty::IsTty};
12use fleet_shared::SecretData;12use fleet_shared::SecretData;
13use itertools::Itertools;13use itertools::Itertools;
14use nix_eval::{nix_go, nix_go_json, Value};
14use owo_colors::OwoColorize;15use owo_colors::OwoColorize;
15use serde::Deserialize;16use serde::Deserialize;
16use tabled::{Table, Tabled};17use tabled::{Table, Tabled};
17use tokio::{fs::read, process::Command};18use tokio::{fs::read, process::Command};
18use tracing::{error, info, info_span, warn, Instrument};19use tracing::{error, info, info_span, warn, Instrument};
1920
20use crate::{21use crate::{
21 better_nix_eval::Field,
22 fleetdata::{encrypt_secret_data, FleetSecret, FleetSecretPart, FleetSharedSecret},22 fleetdata::{encrypt_secret_data, FleetSecret, FleetSecretPart, FleetSharedSecret},
23 host::Config,23 host::Config,
24 nix_go, nix_go_json,
25};24};
2625
27#[derive(Parser)]26#[derive(Parser)]
130 secret_name: &str,129 secret_name: &str,
131 config: &Config,130 config: &Config,
132 mut secret: FleetSharedSecret,131 mut secret: FleetSharedSecret,
133 field: Field,132 field: Value,
134 updated_set: &[String],133 updated_set: &[String],
135 prefer_identities: &[String],134 prefer_identities: &[String],
136) -> Result<FleetSharedSecret> {135) -> Result<FleetSharedSecret> {
197async fn generate_pure(196async fn generate_pure(
198 _config: &Config,197 _config: &Config,
199 _display_name: &str,198 _display_name: &str,
200 _secret: Field,199 _secret: Value,
201 _default_generator: Field,200 _default_generator: Value,
202 _owners: &[String],201 _owners: &[String],
203) -> Result<FleetSecret> {202) -> Result<FleetSecret> {
204 bail!("pure generators are broken for now")203 bail!("pure generators are broken for now")
205}204}
206async fn generate_impure(205async fn generate_impure(
207 config: &Config,206 config: &Config,
208 _display_name: &str,207 _display_name: &str,
209 secret: Field,208 secret: Value,
210 default_generator: Field,209 default_generator: Value,
211 owners: &[String],210 owners: &[String],
212) -> Result<FleetSecret> {211) -> Result<FleetSecret> {
213 let generator = nix_go!(secret.generator);212 let generator = nix_go!(secret.generator);
289async fn generate(288async fn generate(
290 config: &Config,289 config: &Config,
291 display_name: &str,290 display_name: &str,
292 secret: Field,291 secret: Value,
293 owners: &[String],292 owners: &[String],
294) -> Result<FleetSecret> {293) -> Result<FleetSecret> {
295 let generator = nix_go!(secret.generator);294 let generator = nix_go!(secret.generator);
332async fn generate_shared(331async fn generate_shared(
333 config: &Config,332 config: &Config,
334 display_name: &str,333 display_name: &str,
335 secret: Field,334 secret: Value,
336 expected_owners: Vec<String>,335 expected_owners: Vec<String>,
337) -> Result<FleetSharedSecret> {336) -> Result<FleetSharedSecret> {
338 // let owners: Vec<String> = nix_go_json!(secret.expectedOwners);337 // let owners: Vec<String> = nix_go_json!(secret.expectedOwners);
modifiedcmds/fleet/src/host.rsdiffbeforeafterboth
12use anyhow::{anyhow, bail, ensure, Context, Result};12use anyhow::{anyhow, bail, ensure, Context, Result};
13use clap::{ArgGroup, Parser};13use clap::{ArgGroup, Parser};
14use fleet_shared::SecretData;14use fleet_shared::SecretData;
15use nix_eval::{nix_go, nix_go_json, NixSessionPool, Value};
15use openssh::SessionBuilder;16use openssh::SessionBuilder;
16use serde::de::DeserializeOwned;17use serde::de::DeserializeOwned;
17use tempfile::NamedTempFile;18use tempfile::NamedTempFile;
1819
19use crate::{20use crate::{
20 better_nix_eval::{Field, NixSessionPool},
21 command::MyCommand,21 command::MyCommand,
22 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},22 fleetdata::{FleetData, FleetSecret, FleetSharedSecret},
23 nix_go, nix_go_json,
24};23};
2524
26pub struct FleetConfigInternals {25pub struct FleetConfigInternals {
30 pub data: Mutex<FleetData>,29 pub data: Mutex<FleetData>,
31 pub nix_args: Vec<OsString>,30 pub nix_args: Vec<OsString>,
32 /// fleet_config.config31 /// fleet_config.config
33 pub config_field: Field,32 pub config_field: Value,
34 /// fleet_config.unchecked.config33 /// fleet_config.unchecked.config
35 pub config_unchecked_field: Field,34 pub config_unchecked_field: Value,
3635
37 /// import nixpkgs {system = local};36 /// import nixpkgs {system = local};
38 pub default_pkgs: Field,37 pub default_pkgs: Value,
39}38}
4039
41#[derive(Clone)]40#[derive(Clone)]
55 pub local: bool,54 pub local: bool,
56 pub session: OnceLock<Arc<openssh::Session>>,55 pub session: OnceLock<Arc<openssh::Session>>,
5756
58 pub nixos_config: Option<Field>,57 pub nixos_config: Option<Value>,
59}58}
60impl ConfigHost {59impl ConfigHost {
61 async fn open_session(&self) -> Result<Arc<openssh::Session>> {60 async fn open_session(&self) -> Result<Arc<openssh::Session>> {
201 }200 }
202 Ok(out)201 Ok(out)
203 }202 }
204 pub async fn secret_field(&self, name: &str) -> Result<Field> {203 pub async fn secret_field(&self, name: &str) -> Result<Value> {
205 let Some(nixos) = &self.nixos_config else {204 let Some(nixos) = &self.nixos_config else {
206 bail!("host is virtual and has no secrets");205 bail!("host is virtual and has no secrets");
207 };206 };
208 Ok(nix_go!(nixos.secrets[{ name }]))207 Ok(nix_go!(nixos.secrets[{ name }]))
209 }208 }
210209
211 /// Packages for this host, resolved with nixpkgs overlays210 /// Packages for this host, resolved with nixpkgs overlays
212 pub async fn pkgs(&self) -> Result<Field> {211 pub async fn pkgs(&self) -> Result<Value> {
213 let Some(nixos) = &self.nixos_config else {212 let Some(nixos) = &self.nixos_config else {
214 return Ok(self.config.default_pkgs.clone());213 return Ok(self.config.default_pkgs.clone());
215 };214 };
261 }260 }
262 Ok(out)261 Ok(out)
263 }262 }
264 pub async fn system_config(&self, host: &str) -> Result<Field> {263 pub async fn system_config(&self, host: &str) -> Result<Value> {
265 let fleet_field = &self.config_unchecked_field;264 let fleet_field = &self.config_unchecked_field;
266 Ok(nix_go!(fleet_field.hosts[{ host }].nixosSystem.config))265 Ok(nix_go!(fleet_field.hosts[{ host }].nixosSystem.config))
267 }266 }
275 /// Shared secrets configured in fleet.nix or in flake274 /// Shared secrets configured in fleet.nix or in flake
276 pub async fn list_configured_shared(&self) -> Result<Vec<String>> {275 pub async fn list_configured_shared(&self) -> Result<Vec<String>> {
277 let config_field = &self.config_unchecked_field;276 let config_field = &self.config_unchecked_field;
278 nix_go!(config_field.sharedSecrets).list_fields().await277 Ok(nix_go!(config_field.sharedSecrets).list_fields().await?)
279 }278 }
280 /// Shared secrets configured in fleet.nix279 /// Shared secrets configured in fleet.nix
281 pub fn list_shared(&self) -> Vec<String> {280 pub fn list_shared(&self) -> Vec<String> {
389 let pool = NixSessionPool::new(directory.as_os_str().to_owned(), nix_args.clone()).await?;388 let pool = NixSessionPool::new(directory.as_os_str().to_owned(), nix_args.clone()).await?;
390 let root_field = pool.get().await?;389 let root_field = pool.get().await?;
391390
392 let builtins_field = Field::field(root_field.clone(), "builtins").await?;391 let builtins_field = Value::binding(root_field.clone(), "builtins").await?;
393 if self.local_system == "detect" {392 if self.local_system == "detect" {
394 self.local_system = nix_go_json!(builtins_field.currentSystem);393 self.local_system = nix_go_json!(builtins_field.currentSystem);
395 }394 }
396 let local_system = self.local_system.clone();395 let local_system = self.local_system.clone();
397396
398 let fleet_root = Field::field(root_field, "fleetConfigurations").await?;397 let fleet_root = Value::binding(root_field, "fleetConfigurations").await?;
399 let fleet_field = nix_go!(fleet_root.default);398 let fleet_field = nix_go!(fleet_root.default);
400399
401 let config_field = nix_go!(fleet_field.config);400 let config_field = nix_go!(fleet_field.config);
modifiedcmds/fleet/src/main.rsdiffbeforeafterboth
1#![recursion_limit = "512"]1#![recursion_limit = "512"]
2#![feature(try_blocks, lint_reasons)]2#![feature(try_blocks)]
33
4pub(crate) mod cmds;4pub(crate) mod cmds;
5pub(crate) mod command;5pub(crate) mod command;
173 setup_logging();173 setup_logging();
174 if let Err(e) = main_real().await {174 if let Err(e) = main_real().await {
175 // If I remove this line, the next error!() line gets eaten.175 // If I remove this line, the next error!() line gets eaten.
176 // This is a bug in indicatif, it needs to be fixed
177 #[cfg(feature = "indicatif")]
176 info!("fixme: this line gets eaten by tracing-indicatif on levels info+");178 info!("fixme: this line gets eaten by tracing-indicatif on levels info+");
177 error!("{e:#}");179 error!("{e:#}");
178 return ExitCode::FAILURE;180 return ExitCode::FAILURE;
181}183}
182184
183async fn main_real() -> Result<()> {185async fn main_real() -> Result<()> {
184 let _ = better_nix_eval::TOKIO_RUNTIME.set(tokio::runtime::Handle::current());186 nix_eval::init_tokio();
185187
186 let nix_args = std::env::var_os("NIX_ARGS")188 let nix_args = std::env::var_os("NIX_ARGS")
187 .map(|a| extra_args::parse_os(&a))189 .map(|a| extra_args::parse_os(&a))
addedcmds/generator-helper/Cargo.tomldiffbeforeafterboth

no changes

addedcmds/generator-helper/src/main.rsdiffbeforeafterboth

no changes

modifiedcmds/install-secrets/Cargo.tomldiffbeforeafterboth
66
77
8[dependencies]8[dependencies]
9age = { version = "0.10.0", features = ["ssh"] }9clap.workspace = true
10anyhow = "1.0.79"10fleet-shared.workspace = true
11tracing-subscriber = { version = "0.3", features = ["env-filter"] }11age.workspace = true
12tracing = "0.1"12anyhow.workspace = true
13nix = {version = "0.27.1", features = ["user", "fs"]}13tracing.workspace = true
14serde = { version = "1.0.196", features = ["derive"] }14tracing-subscriber.workspace = true
15serde_json = "1.0.113"15serde.workspace = true
16clap = { version = ">=4.4, <4.5", features = [16serde_json.workspace = true
17 "derive",
18 "env",
19 "wrap_help",
20 "unicode",
21] }
22tempfile = "3.10.0"17tempfile.workspace = true
23fleet-shared.workspace = true18nix.workspace = true
2419
modifiedcmds/remowt-agent/Cargo.tomldiffbeforeafterboth
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77
8[dependencies]8[dependencies]
9iroh-net = "0.17.0"
10tracing.workspace = true
911
addedcrates/nix-eval/Cargo.tomldiffbeforeafterboth

no changes

addedcrates/nix-eval/src/lib.rsdiffbeforeafterboth

no changes

addedcrates/nix-eval/src/macros.rsdiffbeforeafterboth

no changes

addedcrates/nix-eval/src/pool.rsdiffbeforeafterboth

no changes

addedcrates/nix-eval/src/session.rsdiffbeforeafterboth

no changes

addedcrates/nix-eval/src/value.rsdiffbeforeafterboth

no changes

modifiedcrates/nixlike/src/lib.rsdiffbeforeafterboth
1//! Serialization/deserialization for nix subset usable for static configurations1//! Serialization/deserialization for nix subset usable for static configurations
2//!
2//! Serialized results from this library are readable by both this library and standard nix tools3//! Serialized results from this library are readable by both this library and standard nix tools.
4//! Nix produced output should also be readable by this library, however, you can't write arbitrary nix
5//! expressions and expect it to work, only basic primitives are supported, and there is no
6//! variables/recursive records, interpolation, e.t.c.
37
4use linked_hash_map::LinkedHashMap;8use linked_hash_map::LinkedHashMap;
5use peg::str::LineCol;9use peg::str::LineCol;
198202
199#[test]203#[test]
200fn parse_multiline() {204fn parse_multiline() {
205 // First line is ignored, unless there is a significant characters.
201 assert_eq!(nixlike::multiline_string("''\n''").expect("parse"), "");206 assert_eq!(nixlike::multiline_string("''\n''").expect("parse"), "");
207 // Rest of the lines are processed normally.
202 assert_eq!(nixlike::multiline_string("''\n\n''").expect("parse"), "\n");208 assert_eq!(nixlike::multiline_string("''\n\n''").expect("parse"), "\n");
209 // Example with significant character on first line.
203 assert_eq!(nixlike::multiline_string("''t\n''").expect("parse"), "t\n");210 assert_eq!(nixlike::multiline_string("''t\n''").expect("parse"), "t\n");
211 // There might be nothing in multiline string block.
204 assert_eq!(nixlike::multiline_string("''''").expect("parse"), "");212 assert_eq!(nixlike::multiline_string("''''").expect("parse"), "");
213 // And there also might just be spaces, they are removed due to dedent, and output is empty because
214 // first line was also ignored due to missing significant characters.
205 assert_eq!(nixlike::multiline_string("'' ''").expect("parse"), "");215 assert_eq!(nixlike::multiline_string("'' ''").expect("parse"), "");
206}216}
207217
modifiedflake.lockdiffbeforeafterboth
7 ]7 ]
8 },8 },
9 "locked": {9 "locked": {
10 "lastModified": 1715274763,10 "lastModified": 1716569590,
11 "narHash": "sha256-3Iv1PGHJn9sV3HO4FlOVaaztOxa9uGLfOmUWrH7v7+A=",11 "narHash": "sha256-5eDbq8TuXFGGO3mqJFzhUbt5zHVTf5zilQoyW5jnJwo=",
12 "owner": "ipetkov",12 "owner": "ipetkov",
13 "repo": "crane",13 "repo": "crane",
14 "rev": "27025ab71bdca30e7ed0a16c88fd74c5970fc7f5",14 "rev": "109987da061a1bf452f435f1653c47511587d919",
15 "type": "github"15 "type": "github"
16 },16 },
17 "original": {17 "original": {
40 },40 },
41 "nixpkgs": {41 "nixpkgs": {
42 "locked": {42 "locked": {
43 "lastModified": 1715619775,43 "lastModified": 1716658583,
44 "narHash": "sha256-c1XVqTH9IeUukc4LcWLzHCSpMfo4Dj4K8t/kLV3c80c=",44 "narHash": "sha256-A93mYmlLvCz0YjQiQ5Tc3DpLrP6Brs+gAlK9nlnSOVg=",
45 "owner": "nixos",45 "owner": "nixos",
46 "repo": "nixpkgs",46 "repo": "nixpkgs",
47 "rev": "0cb78770f66945bb3130f762aef05373e283f2b9",47 "rev": "3e280884c0b0e8222ec6b05a99db01505964e1c3",
48 "type": "github"48 "type": "github"
49 },49 },
50 "original": {50 "original": {
54 "type": "github"54 "type": "github"
55 }55 }
56 },56 },
57 "nixpkgs-stable-for-tests": {
58 "locked": {
59 "lastModified": 1716361217,
60 "narHash": "sha256-mzZDr00WUiUXVm1ujBVv6A0qRd8okaITyUp4ezYRgc4=",
61 "owner": "nixos",
62 "repo": "nixpkgs",
63 "rev": "46397778ef1f73414b03ed553a3368f0e7e33c2f",
64 "type": "github"
65 },
66 "original": {
67 "owner": "nixos",
68 "ref": "nixos-23.11",
69 "repo": "nixpkgs",
70 "type": "github"
71 }
72 },
57 "root": {73 "root": {
58 "inputs": {74 "inputs": {
59 "crane": "crane",75 "crane": "crane",
60 "flake-utils": "flake-utils",76 "flake-utils": "flake-utils",
61 "nixpkgs": "nixpkgs",77 "nixpkgs": "nixpkgs",
78 "nixpkgs-stable-for-tests": "nixpkgs-stable-for-tests",
62 "rust-overlay": "rust-overlay"79 "rust-overlay": "rust-overlay"
63 }80 }
64 },81 },
72 ]89 ]
73 },90 },
74 "locked": {91 "locked": {
75 "lastModified": 1715566659,92 "lastModified": 1716603336,
76 "narHash": "sha256-OpI0TnN+uE0vvxjPStlTzf5RTohIXVSMwrP9NEgMtaY=",93 "narHash": "sha256-81u/zd7V+XRTq88zwRLxw5GnwZyEiAvGA2BvAXUe864=",
77 "owner": "oxalica",94 "owner": "oxalica",
78 "repo": "rust-overlay",95 "repo": "rust-overlay",
79 "rev": "6c465248316cd31502c82f81f1a3acf2d621b01c",96 "rev": "4d0f1e4d5d65c23cdbb77e4b0d91940be7309bd4",
80 "type": "github"97 "type": "github"
81 },98 },
82 "original": {99 "original": {
modifiedflake.nixdiffbeforeafterboth
33
4 inputs = {4 inputs = {
5 nixpkgs.url = "github:nixos/nixpkgs/master";5 nixpkgs.url = "github:nixos/nixpkgs/master";
6 nixpkgs-stable-for-tests.url = "github:nixos/nixpkgs/nixos-23.11";
6 rust-overlay = {7 rust-overlay = {
7 url = "github:oxalica/rust-overlay";8 url = "github:oxalica/rust-overlay";
8 inputs = {9 inputs = {
21 rust-overlay,22 rust-overlay,
22 flake-utils,23 flake-utils,
23 nixpkgs,24 nixpkgs,
25 nixpkgs-stable-for-tests,
24 crane,26 crane,
25 }:27 }:
26 with nixpkgs.lib;28 with nixpkgs.lib;
37 rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;39 rust = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
38 craneLib = (crane.mkLib pkgs).overrideToolchain rust;40 craneLib = (crane.mkLib pkgs).overrideToolchain rust;
39 in {41 in {
42 packages = let
40 packages = import ./pkgs {43 packages = import ./pkgs {
41 inherit (pkgs) callPackage;44 inherit (pkgs) callPackage;
42 inherit craneLib;45 inherit craneLib;
43 };46 };
47 in
48 packages // {default = packages.fleet;};
49
50 checks = let
51 packages = import ./pkgs {
52 inherit (pkgs) callPackage;
53 craneLib = crane.mkLib (import nixpkgs {inherit system;});
54 };
55 packages-with-nixpkgs-stable = import ./pkgs {
56 inherit (pkgs) callPackage;
57 craneLib = crane.mkLib (import nixpkgs-stable-for-tests {inherit system;});
58 };
59 prefixAttrs = prefix: attrs:
60 nixpkgs.lib.attrsets.mapAttrs' (name: value: {
61 name = "${prefix}${name}";
62 value = value.overrideAttrs (prev: {
63 pname = "${prefix}${prev.pname}";
64 });
65 })
66 attrs;
67 in
68 # `fleet` crate wants nightly rust, also little sense of supporting it on stable nixpkgs.
69 (prefixAttrs "nixpkgs-" (removeAttrs packages ["fleet"]))
70 // (prefixAttrs "nixpkgs-stable-" (removeAttrs packages-with-nixpkgs-stable ["fleet"]));
71
44 devShell = craneLib.devShell {72 devShells.default = craneLib.devShell {
45 nativeBuildInputs = with pkgs; [73 nativeBuildInputs = with pkgs; [
46 alejandra74 alejandra
47 lld75 lld
deletednixos/fleetPkgs.nixdiffbeforeafterboth

no changes

modifiedpkgs/default.nixdiffbeforeafterboth
1{1{
2 callPackage,2 callPackage,
3 craneLib,3 craneLib,
4}: rec {4}: {
5 default = fleet;
6
7 fleet-install-secrets = callPackage ./fleet-install-secrets.nix {inherit craneLib;};5 fleet-install-secrets = callPackage ./fleet-install-secrets.nix {inherit craneLib;};
8 fleet = callPackage ./fleet.nix {inherit craneLib;};6 fleet = callPackage ./fleet.nix {inherit craneLib;};
addedpkgs/generator-helper.nixdiffbeforeafterboth

no changes

modifiedrust-toolchain.tomldiffbeforeafterboth
1[toolchain]1[toolchain]
2channel = "nightly-2024-02-10"2channel = "nightly-2024-05-01"
3components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]3components = ["rustfmt", "clippy", "rust-analyzer", "rust-src"]
44