restore old files now!

This commit is contained in:
Qyriad 2026-02-16 18:02:39 +01:00
parent 76b5ac628d
commit dfdf027bc6
11 changed files with 1676 additions and 16 deletions

920
Cargo.lock generated Normal file
View file

@ -0,0 +1,920 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
[[package]]
name = "anstream"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "cfg_aliases"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "clap"
version = "4.5.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394"
dependencies = [
"clap_builder",
"clap_derive",
]
[[package]]
name = "clap_builder"
version = "4.5.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "command-error"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b6ac3abfcf15b4536b079bcee923683fe3dc1173b70be5e05ccf28ca112862e"
dependencies = [
"dyn-clone",
"process-wrap",
"shell-words",
"utf8-command",
]
[[package]]
name = "dyn-clone"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "dynix"
version = "0.1.0"
dependencies = [
"clap",
"command-error",
"fs-err",
"itertools",
"libc",
"serde",
"serde_json",
"tap",
"tracing",
"tracing-human-layer",
"tracing-subscriber",
]
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "fs-err"
version = "3.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf68cef89750956493a66a10f512b9e58d9db21f2a573c079c0bdf1207a54a7"
dependencies = [
"autocfg",
]
[[package]]
name = "hashbrown"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "indexmap"
version = "2.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "is-terminal"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "is_ci"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
[[package]]
name = "matchers"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
dependencies = [
"regex-automata",
]
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags",
"cfg-if",
"cfg_aliases",
"libc",
]
[[package]]
name = "nu-ansi-term"
version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "owo-colors"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
dependencies = [
"supports-color 2.1.0",
"supports-color 3.0.2",
]
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link 0.2.1",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
[[package]]
name = "proc-macro2"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
dependencies = [
"unicode-ident",
]
[[package]]
name = "process-wrap"
version = "8.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1"
dependencies = [
"indexmap",
"nix",
"tracing",
"windows",
]
[[package]]
name = "quote"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "regex-automata"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
[[package]]
name = "rustix"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.61.2",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]]
name = "shell-words"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77"
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "smawk"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "supports-color"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
dependencies = [
"is-terminal",
"is_ci",
]
[[package]]
name = "supports-color"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
dependencies = [
"is_ci",
]
[[package]]
name = "syn"
version = "2.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "terminal_size"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
dependencies = [
"rustix",
"windows-sys 0.60.2",
]
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"smawk",
"terminal_size",
"unicode-linebreak",
"unicode-width",
]
[[package]]
name = "thread_local"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
]
[[package]]
name = "tracing"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-human-layer"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b285fd79bba4659408f5d290b3f30fd69d428c630d8c00bb4ba255f2501d50e3"
dependencies = [
"itertools",
"owo-colors",
"parking_lot",
"textwrap",
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"parking_lot",
"regex-automata",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-ident"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-width"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "utf8-command"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4b151524c94cda49046b29e6d20b03092ff9363b02acc1bf3994da60910c55b"
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "valuable"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "windows"
version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
"windows-collections",
"windows-core",
"windows-future",
"windows-link 0.1.3",
"windows-numerics",
]
[[package]]
name = "windows-collections"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
"windows-core",
]
[[package]]
name = "windows-core"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.1.3",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-future"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
"windows-core",
"windows-link 0.1.3",
"windows-threading",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-numerics"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
"windows-core",
"windows-link 0.1.3",
]
[[package]]
name = "windows-result"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link 0.2.1",
"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",
]
[[package]]
name = "windows-threading"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "zmij"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65"

25
Cargo.toml Normal file
View file

@ -0,0 +1,25 @@
[package]
name = "dynix"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "dynix"
path = "src/main.rs"
[lib]
name = "dynix"
path = "src/lib.rs"
[dependencies]
clap = { version = "4.5.54", features = ["color", "derive"] }
command-error = "0.8.0"
fs-err = "3.2.2"
itertools = "0.14.0"
libc = { version = "0.2.180", features = ["extra_traits"] }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
tap = "1.0.1"
tracing = { version = "0.1.44", features = ["attributes"] }
tracing-human-layer = "0.2.1"
tracing-subscriber = { version = "0.3.22", default-features = false, features = ["std", "env-filter", "fmt", "ansi", "registry", "parking_lot"] }

View file

@ -1,38 +1,65 @@
{ {
lib, lib,
stdenvNoCC, clangStdenv,
callPackage, callPackage,
linkFarm, linkFarm,
rustHooks,
rustPackages,
versionCheckHook,
}: lib.callWith' rustPackages ({
rustPlatform,
cargo,
}: let }: let
stdenv = stdenvNoCC; stdenv = clangStdenv;
cargoToml = lib.importTOML ./Cargo.toml;
cargoPackage = cargoToml.package;
in stdenv.mkDerivation (finalAttrs: let in stdenv.mkDerivation (finalAttrs: let
self = finalAttrs.finalPackage; self = finalAttrs.finalPackage;
in { in {
name = "dynix-modules"; pname = cargoPackage.name;
version = cargoPackage.version;
strictDeps = true; strictDeps = true;
__structuredAttrs = true; __structuredAttrs = true;
outputs = [ "out" "modules" ]; outputs = [ "out" "modules" ];
src = lib.fileset.toSource { doCheck = true;
doInstallCheck = true;
modulesSrc = lib.fileset.toSource {
root = ./modules/dynamicism; root = ./modules/dynamicism;
fileset = lib.fileset.unions [ fileset = lib.fileset.unions [
./modules/dynamicism ./modules/dynamicism
]; ];
}; };
phases = [ "unpackPhase" "patchPhase" "installPhase" ]; src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./Cargo.toml
./Cargo.lock
./src
];
};
cargoDeps = rustPlatform.importCargoLock {
lockFile = ./Cargo.lock;
};
nativeBuildInputs = rustHooks.asList ++ [
cargo
];
nativeInstallCheckInputs = [
versionCheckHook
];
modulesOut = "${placeholder "modules"}/share/nixos/modules/dynix"; modulesOut = "${placeholder "modules"}/share/nixos/modules/dynix";
installPhase = lib.dedent '' postInstall = lib.dedent ''
runHook preInstall mkdir -p "$modulesOut"
mkdir -p "$out" cp -r "$modulesSrc/"* "$modulesOut/"
cp -r * "$out/"
mkdir -p "$modules/share/nixos/modules/dynix"
cp --reflink=auto -r "$out/"* "$modulesOut/"
''; '';
passthru.mkDevShell = { passthru.mkDevShell = {
@ -46,7 +73,12 @@ in {
]); ]);
in mkShell' { in mkShell' {
name = "devshell-for-${self.name}"; name = "devshell-for-${self.name}";
packages = [ pyEnv ]; inputsFrom = [ self ];
packages = [
pyEnv
rustPackages.rustc
rustPackages.rustfmt
];
env.PYTHONPATH = [ env.PYTHONPATH = [
"${pyEnv}/${pyEnv.sitePackages}" "${pyEnv}/${pyEnv.sitePackages}"
# Cursed. # Cursed.
@ -55,6 +87,7 @@ in {
}; };
passthru.modulesPath = self.modules + "/share/nixos/modules"; passthru.modulesPath = self.modules + "/share/nixos/modules";
passthru.dynix = self.modulesPath + "/dynix";
passthru.tests = lib.fix (callPackage ./tests { passthru.tests = lib.fix (callPackage ./tests {
dynix = self; dynix = self;
@ -67,6 +100,7 @@ in {
Default output contains the modules at top-level, meant for `import`. Default output contains the modules at top-level, meant for `import`.
The `modules` output contains the modules prefixed under `/share/nixos/modules/dynix`. The `modules` output contains the modules prefixed under `/share/nixos/modules/dynix`.
''; '';
outputsToInstall = [ "modules" ]; mainProgram = "dynix";
outputsToInstall = [ "out" "modules" ];
}; };
}) }))

97
src/args.rs Normal file
View file

@ -0,0 +1,97 @@
use std::sync::Arc;
use clap::ColorChoice;
use crate::prelude::*;
//#[derive(Debug, Clone, PartialEq)]
//#[derive(clap::Args)]
//#[group(required = true, multiple = false)]
//pub enum Config
//{
// Flake,
//}
#[derive(Debug, Clone, PartialEq)]
pub struct NixOsOption {
name: String,
value: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct NixOptionParseError(pub Box<str>);
impl Display for NixOptionParseError {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(f, "{}", self.0)
}
}
impl From<String> for NixOptionParseError {
fn from(value: String) -> Self {
Self(value.into_boxed_str())
}
}
impl StdError for NixOptionParseError {}
impl FromStr for NixOsOption {
type Err = NixOptionParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// FIXME: allow escaping equals sign?
let Some(delim) = s.find('=') else {
return Err(format!("equals sign not found in {}", s).into());
};
todo!();
}
}
#[derive(Debug, Clone, PartialEq, clap::Parser)]
pub struct AppendCmd {
#[arg(required = true)]
pub name: Arc<str>,
#[arg(required = true)]
pub value: Arc<str>,
}
#[derive(Debug, Clone, PartialEq, clap::Parser)]
pub struct DeltaCmd {}
#[derive(Debug, Clone, PartialEq, clap::Subcommand)]
#[command(flatten_help = true)]
pub enum Subcommand {
Append(AppendCmd),
// TODO: rename
Delta(DeltaCmd),
}
#[derive(Debug, Clone, PartialEq, clap::Parser)]
#[command(version, about, author)]
#[command(arg_required_else_help(true), args_override_self(true))]
#[command(propagate_version = true)]
pub struct Args {
#[arg(long, global(true), default_value = "auto")]
pub color: ColorChoice,
// FIXME: default to /etc/configuration.nix, or something?
#[arg(long, global(true), default_value = "./configuration.nix")]
pub file: Arc<OsStr>,
#[command(subcommand)]
pub subcommand: Subcommand,
}
///// Flakeref to a base configuration to modify.
//#[arg(group = "config", long, default_value("."))]
//#[arg(long, default_value(Some(".")))]
//flake: Option<Option<Box<OsStr>>>,
//
//#[arg(group = "config", long)]
//expr: Option<String>,
//impl Parser {
// fn eval_cmd(&self) {
// todo!();
// }
//}

53
src/color.rs Normal file
View file

@ -0,0 +1,53 @@
use std::{
env,
sync::{LazyLock, OnceLock},
};
#[allow(unused_imports)]
use crate::prelude::*;
/// The actual, final value for whether color should be used, based on CLI and environment values.
pub static SHOULD_COLOR: LazyLock<bool> = LazyLock::new(|| is_clicolor_forced() || is_color_reqd());
/// Initialized from the `--color` value from the CLI, along with `io::stdin().is_terminal()`.
pub static _CLI_ENABLE_COLOR: OnceLock<bool> = OnceLock::new();
fn is_color_reqd() -> bool {
_CLI_ENABLE_COLOR.get().copied().unwrap_or(false)
}
fn is_clicolor_forced() -> bool {
env::var("CLICOLOR_FORCE")
.map(|value| {
if value.is_empty() || value == "0" {
false
} else {
true
}
})
.unwrap_or(false)
}
/// Silly wrapper around LazyLock<&'static str> to impl Display.
pub(crate) struct _LazyLockDisplay(LazyLock<&'static str>);
impl Display for _LazyLockDisplay {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
Display::fmt(&*self.0, f)
}
}
pub(crate) const ANSI_GREEN: _LazyLockDisplay = _LazyLockDisplay(LazyLock::new(|| {
SHOULD_COLOR.then_some("\x1b[32m").unwrap_or_default()
}));
pub(crate) const ANSI_MAGENTA: _LazyLockDisplay = _LazyLockDisplay(LazyLock::new(|| {
SHOULD_COLOR.then_some("\x1b[35m").unwrap_or_default()
}));
pub(crate) const ANSI_CYAN: _LazyLockDisplay = _LazyLockDisplay(LazyLock::new(|| {
SHOULD_COLOR.then_some("\x1b[36m").unwrap_or_default()
}));
pub(crate) const ANSI_RESET: _LazyLockDisplay = _LazyLockDisplay(LazyLock::new(|| {
SHOULD_COLOR.then_some("\x1b[0m").unwrap_or_default()
}));

179
src/lib.rs Normal file
View file

@ -0,0 +1,179 @@
use std::{iter, sync::Arc};
pub(crate) mod prelude {
#![allow(unused_imports)]
pub use std::{
error::Error as StdError,
ffi::{OsStr, OsString},
fmt::{Display, Formatter, Result as FmtResult},
io::{Error as IoError, Read, Seek, SeekFrom, Write},
path::{Path, PathBuf},
process::{Command, ExitCode},
str::FromStr,
};
#[cfg(unix)]
pub use std::os::{
fd::AsRawFd,
unix::ffi::{OsStrExt, OsStringExt},
};
pub type BoxDynError = Box<dyn StdError + Send + Sync + 'static>;
pub use command_error::{CommandExt, OutputLike};
pub use fs_err::File;
#[cfg(unix)]
pub use fs_err::os::unix::fs::{FileExt, OpenOptionsExt};
pub use tap::{Pipe, Tap};
pub use tracing::{Level, debug, error, info, trace, warn};
}
use prelude::*;
pub mod args;
pub use args::{AppendCmd, Args, DeltaCmd};
mod color;
pub use color::{_CLI_ENABLE_COLOR, SHOULD_COLOR};
pub mod line;
mod nixcmd;
pub use line::Line;
pub mod source;
pub use source::SourceLine;
use serde::{Deserialize, Serialize};
use crate::source::SourceFile;
pub const ASCII_WHITESPACE: &[char] = &['\t', '\n', '\x0C', '\r', ' '];
#[tracing::instrument(level = "debug")]
pub fn do_delta(args: Arc<Args>, delta_args: DeltaCmd) -> Result<(), BoxDynError> {
todo!();
}
#[tracing::instrument(level = "debug")]
pub fn do_append(args: Arc<Args>, append_args: AppendCmd) -> Result<(), BoxDynError> {
let filepath = Path::new(&args.file);
let filepath: PathBuf = if filepath.is_relative() && !filepath.starts_with("./") {
iter::once(OsStr::new("./"))
.chain(filepath.iter())
.collect()
} else {
filepath.to_path_buf()
};
// Get what file that thing is defined in.
let def_path = get_where(&append_args.name, &filepath)?;
let mut opts = File::options();
opts.read(true)
.write(true)
.create(false)
.custom_flags(libc::O_CLOEXEC);
let source_file = SourceFile::open_from(Arc::from(def_path), opts)?;
let pri = get_highest_prio(&append_args.name, source_file.clone())?;
let new_pri = pri - 1;
let new_pri_line = get_next_prio_line(
source_file.clone(),
append_args.name.into(),
new_pri,
append_args.value.into(),
)?;
eprintln!("new_pri_line={new_pri_line}");
write_next_prio(source_file, new_pri_line)?;
Ok(())
}
#[derive(Debug, Clone, PartialEq, Hash, Serialize, Deserialize)]
pub struct DefinitionWithLocation {
pub file: Box<Path>,
pub value: Box<serde_json::Value>,
}
pub fn expr_for_configuration(source_file: &Path) -> OsString {
[
OsStr::new("import <nixpkgs/nixos> { configuration = "),
source_file.as_os_str(),
OsStr::new("; }"),
]
.into_iter()
.collect()
}
pub fn get_where(option_name: &str, configuration_nix: &Path) -> Result<Box<Path>, BoxDynError> {
let expr = expr_for_configuration(configuration_nix);
let attrpath = format!("options.{}.definitionsWithLocations", option_name);
let output = nixcmd::NixEvalExpr { expr, attrpath }
.into_command()
.output_checked_utf8()?;
let stdout = output.stdout();
let definitions: Box<[DefinitionWithLocation]> = serde_json::from_str(&stdout)?;
let last_location = definitions.into_iter().last().unwrap();
Ok(Box::from(last_location.file))
}
pub fn get_highest_prio(option_name: &str, source: SourceFile) -> Result<i64, BoxDynError> {
// Get the current highest priority.
let expr = expr_for_configuration(&source.path());
// Get the highest priority, and the file its defined in.
let attrpath = format!("options.{}.highestPrio", option_name);
let output = nixcmd::NixEvalExpr { expr, attrpath }
.into_command()
.output_checked_utf8()?;
let stdout = output.stdout();
let highest_prio = i64::from_str(stdout.trim())?;
Ok(highest_prio)
}
pub fn get_next_prio_line(
source: SourceFile,
option_name: Arc<str>,
new_prio: i64,
new_value: Arc<str>,
) -> Result<SourceLine, BoxDynError> {
let source_lines = source.lines()?;
let last_line = source_lines.last();
assert_eq!(last_line.map(SourceLine::text).as_deref(), Some("]"));
let last_line = last_line.unwrap();
let new_line = SourceLine {
line: last_line.line,
path: source.path(),
text: Arc::from(format!(
" {option_name} = lib.mkOverride ({new_prio}) ({new_value});",
)),
};
Ok(new_line)
}
pub fn write_next_prio(mut source: SourceFile, new_line: SourceLine) -> Result<(), BoxDynError> {
let new_mod_start = SourceLine {
line: new_line.line.prev(),
path: source.path(),
text: Arc::from(" {"),
};
let new_mod_end = SourceLine {
line: new_line.line.next(),
path: source.path(),
text: Arc::from(" }"),
};
source.insert_lines(&[new_mod_start, new_line, new_mod_end])?;
Ok(())
}

43
src/line.rs Normal file
View file

@ -0,0 +1,43 @@
use std::num::NonZeroU64;
#[allow(unused_imports)]
use crate::prelude::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Line(pub u64);
/// Constructors.
impl Line {
pub const fn from_index(index: u64) -> Self {
Self(index)
}
pub const fn from_linenr(linenr: NonZeroU64) -> Self {
Self(linenr.get() - 1)
}
pub const fn next(self) -> Self {
Self::from_index(self.index() + 1)
}
/// Panics if self is line index 0.
pub const fn prev(self) -> Self {
Self::from_index(self.index() - 1)
}
}
/// Getters.
impl Line {
/// 0-indexed
pub const fn index(self) -> u64 {
self.0
}
/// 1-indexed
pub const fn linenr(self) -> u64 {
self.0 + 1
}
}
pub struct Lines(Vec<Line>);

48
src/main.rs Normal file
View file

@ -0,0 +1,48 @@
use std::io::{self, IsTerminal};
use std::process::ExitCode;
use std::{error::Error as StdError, sync::Arc};
use clap::{ColorChoice, Parser as _};
use tracing_human_layer::HumanLayer;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{EnvFilter, layer::SubscriberExt};
fn main_wrapped() -> Result<(), Box<dyn StdError + Send + Sync + 'static>> {
let args = Arc::new(dynix::Args::parse());
let success = dynix::_CLI_ENABLE_COLOR.set(match args.color {
ColorChoice::Always => true,
ColorChoice::Auto => io::stdin().is_terminal(),
ColorChoice::Never => false,
});
if cfg!(debug_assertions) {
success.expect("logic error in CLI_ENABLE_COLOR");
}
tracing_subscriber::registry()
.with(HumanLayer::new().with_color_output(*dynix::SHOULD_COLOR))
.with(EnvFilter::from_default_env())
.init();
tracing::debug!("Parsed command-line arguments: {args:?}");
{
use dynix::args::Subcommand::*;
match &args.subcommand {
Append(append_args) => dynix::do_append(args.clone(), append_args.clone())?,
Delta(delta_args) => dynix::do_delta(args.clone(), delta_args.clone())?,
};
}
Ok(())
}
fn main() -> ExitCode {
match main_wrapped() {
Ok(_) => ExitCode::SUCCESS,
Err(e) => {
eprintln!("dynix: error: {}", e);
ExitCode::FAILURE
}
}
}

27
src/nixcmd.rs Normal file
View file

@ -0,0 +1,27 @@
#[allow(unused_imports)]
use crate::prelude::*;
#[derive(Debug, Clone, PartialEq, Hash)]
pub(crate) struct NixEvalExpr<E, A> {
pub(crate) expr: E,
pub(crate) attrpath: A,
}
impl<E, A> NixEvalExpr<E, A>
where
E: AsRef<OsStr>,
A: AsRef<OsStr>,
{
pub(crate) fn into_command(self) -> Command {
let mut cmd = Command::new("nix-instantiate");
cmd.arg("--eval")
.arg("--json")
.arg("--strict")
.arg("--expr")
.arg(self.expr)
.arg("-A")
.arg(self.attrpath);
cmd
}
}

234
src/source.rs Normal file
View file

@ -0,0 +1,234 @@
use std::{
cell::{Ref, RefCell},
hash::Hash,
io::{BufRead, BufReader, BufWriter},
ops::Deref,
ptr,
sync::{Arc, Mutex, OnceLock},
};
use crate::Line;
use crate::color::{ANSI_CYAN, ANSI_GREEN, ANSI_MAGENTA, ANSI_RESET};
#[allow(unused_imports)]
use crate::prelude::*;
use fs_err::OpenOptions;
use itertools::Itertools;
pub fn replace_file<'a>(
path: &Path,
contents: impl IntoIterator<Item = &'a [u8]>,
) -> Result<(), IoError> {
let tmp_path = path.with_added_extension(".tmp");
let tmp_file = File::options()
.create(true)
.write(true)
.truncate(true)
.custom_flags(libc::O_EXCL | libc::O_CLOEXEC)
.open(&tmp_path)?;
let mut writer = BufWriter::new(tmp_file);
for slice in contents {
writer.write_all(slice)?;
}
writer.flush()?;
drop(writer);
// Rename the temporary file to the new file, which is atomic (TODO: I think).
fs_err::rename(&tmp_path, &path)?;
Ok(())
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub struct SourceLine {
pub line: Line,
pub path: Arc<Path>,
pub text: Arc<str>,
}
impl SourceLine {
pub fn text(&self) -> Arc<str> {
Arc::clone(&self.text)
}
pub fn text_ref(&self) -> &str {
&self.text
}
pub fn text_bytes(&self) -> Arc<[u8]> {
let len: usize = self.text.as_bytes().len();
// We need to consume an Arc, but we are &self.
let text = Arc::clone(&self.text);
let str_ptr: *const str = Arc::into_raw(text);
let start: *const u8 = str_ptr.cast();
let slice_ptr: *const [u8] = ptr::slice_from_raw_parts(start, len);
unsafe { Arc::<[u8]>::from_raw(slice_ptr) }
}
pub fn text_bytes_ref(&self) -> &[u8] {
self.text.as_bytes()
}
pub fn path(&self) -> Arc<Path> {
Arc::clone(&self.path)
}
}
impl Display for SourceLine {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
write!(
f,
"{ANSI_MAGENTA}{}{ANSI_RESET}:{ANSI_GREEN}{}{ANSI_RESET}: `{ANSI_CYAN}{}{ANSI_RESET}`",
self.path.display(),
self.line.linenr(),
self.text.trim(),
)
}
}
#[derive(Debug, Clone)]
pub struct SourceFile {
path: Arc<Path>,
file: Arc<Mutex<File>>,
/// References to `SourceFile` do not prevent mutating `lines`.
/// Also `lines` is lazily initialized.
lines: Arc<OnceLock<RefCell<Vec<SourceLine>>>>,
}
impl SourceFile {
/// Panics if `path` is a directory path instead of a file path.
pub fn open_from(path: Arc<Path>, options: OpenOptions) -> Result<Self, IoError> {
trace!(
"SourceFile::open_from(path={:?}, options={:?})",
path,
options.options(),
);
assert!(path.file_name().is_some());
let file = Arc::new(Mutex::new(options.open(&*path)?));
Ok(Self {
path,
file,
lines: Default::default(),
})
}
pub fn buf_reader(&mut self) -> Result<BufReader<&mut File>, IoError> {
let file_mut = Arc::get_mut(&mut self.file)
.unwrap_or_else(|| panic!("'File' for {} has existing handle", self.path.display()))
.get_mut()
.unwrap_or_else(|e| {
panic!("'File' for {} was mutex-poisoned: {e}", self.path.display())
});
let reader = BufReader::new(file_mut);
Ok(reader)
}
fn _lines(&self) -> Result<Ref<'_, [SourceLine]>, IoError> {
if let Some(lines) = self.lines.get() {
let as_slice = Ref::map(lines.borrow(), |lines| lines.as_slice());
return Ok(as_slice);
}
let lines = BufReader::new(&*self.file.lock().unwrap())
.lines()
.enumerate()
.map(|(index, line_res)| {
line_res.map(|line| SourceLine {
line: Line::from_index(index as u64),
path: Arc::clone(&self.path),
text: Arc::from(line),
})
})
.collect::<Result<Vec<SourceLine>, IoError>>()?;
// Mutex should have dropped by now.
debug_assert!(self.file.try_lock().is_ok());
self.lines.set(RefCell::new(lines)).unwrap();
Ok(self._lines_slice())
}
pub fn lines(&self) -> Result<impl Deref<Target = [SourceLine]> + '_, IoError> {
self._lines()
}
pub fn line(&self, line: Line) -> Result<impl Deref<Target = SourceLine> + '_, IoError> {
let lines_lock = self._lines()?;
let line = Ref::map(lines_lock, |lines| &lines[line.index() as usize]);
Ok(line)
}
/// `lines` but already be initialized.
fn _lines_slice(&self) -> Ref<'_, [SourceLine]> {
debug_assert!(self.lines.get().is_some());
Ref::map(self.lines.get().unwrap().borrow(), |lines| lines.as_slice())
}
/// With debug assertions, panics if `lines` are not contiguous.
pub fn insert_lines(&mut self, new_lines: &[SourceLine]) -> Result<(), IoError> {
if new_lines.is_empty() {
return Ok(());
}
let num_lines_before_new = new_lines.last().unwrap().line.prev().index() as usize;
debug_assert!(new_lines.is_sorted_by(|lhs, rhs| lhs.line.next() == rhs.line));
let path = self.path();
let cur_lines = self.lines()?;
let first_half = cur_lines
.iter()
.take(num_lines_before_new)
.map(SourceLine::text);
let middle = new_lines.iter().map(SourceLine::text);
let second_half = cur_lines
.iter()
.skip(num_lines_before_new)
.map(SourceLine::text);
let final_lines: Vec<SourceLine> = first_half
.chain(middle)
.chain(second_half)
.enumerate()
.map(|(idx, text)| SourceLine {
line: Line::from_index(idx as u64),
text,
path: self.path(),
})
.collect();
// Assert lines are continuous.
debug_assert!(final_lines.is_sorted_by(|lhs, rhs| lhs.line.next() == rhs.line));
debug_assert_eq!(cur_lines.len() + new_lines.len(), final_lines.len());
drop(cur_lines);
let data = final_lines
.iter()
.map(SourceLine::text_bytes_ref)
.pipe(|iterator| Itertools::intersperse(iterator, b"\n"));
replace_file(&path, data)?;
// Finally, update state.
self.lines.get().unwrap().replace(final_lines);
Ok(())
}
pub fn path(&self) -> Arc<Path> {
Arc::clone(&self.path)
}
}
impl PartialEq for SourceFile {
fn eq(&self, other: &Self) -> bool {
*self.path == *other.path
}
}

View file

@ -32,7 +32,7 @@
./module-allow-rebuild-in-vm.nix ./module-allow-rebuild-in-vm.nix
# For the VM node, and the in-VM configuration.nix # For the VM node, and the in-VM configuration.nix
./dynix-vm-configuration.nix ./dynix-vm-configuration.nix
(toString dynix) dynix.dynix
]; ];
systemd.services."install-dynix" = { systemd.services."install-dynix" = {