diff options
372 files changed, 16856 insertions, 8896 deletions
diff --git a/.gitreview b/.gitreview new file mode 100644 index 000000000000..6139d7bdadb8 --- /dev/null +++ b/.gitreview @@ -0,0 +1,5 @@ +[gerrit] +host=cl.tvl.fyi +port=29418 +project=depot +defaultbranch=canon diff --git a/.mailmap b/.mailmap index 06e6c9a44997..a583a1ea96ae 100644 --- a/.mailmap +++ b/.mailmap @@ -1 +1,2 @@ Alyssa Ross <hi@alyssa.is> +Aspen Smith <root@gws.fyi> <aspen@gws.fyi> <grfn@gws.fyi> diff --git a/README.md b/README.md index f58f937cef38..2ef7592688f7 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,9 @@ partially see this as [an experiment][] in tooling for monorepos. ## Services -* Source code is available primarily through Sourcegraph on - [cs.tvl.fyi](https://cs.tvl.fyi), where it is searchable and even semantically - indexed. A lower-tech view of the repository is also available via cgit-pink - on [code.tvl.fyi](https://code.tvl.fyi). +* Source code can be viewed primarily via `cgit-pink` on + [code.tvl.fyi](https://code.tvl.fyi), with code search being available through + Livegrep on [grep.tvl.fyi](https://grep.tvl.fyi). The repository can be cloned using `git` from `https://cl.tvl.fyi/depot`. diff --git a/corp/rih/backend/Cargo.lock b/corp/rih/backend/Cargo.lock index afbe6fbc0bf4..97b76ca60ca0 100644 --- a/corp/rih/backend/Cargo.lock +++ b/corp/rih/backend/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ "getrandom", "once_cell", @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "ascii" @@ -42,13 +42,13 @@ checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -69,9 +69,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-creds" @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "aws-region" -version = "0.25.3" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056557a61427d0e5ba29dd931031c8ffed4ee7a550e7cd55692a9d8deb0a9dba" +checksum = "e9aed3f9c7eac9be28662fdb3b0f4d1951e812f7c64fed4f0327ba702f459b3b" dependencies = [ "thiserror", ] @@ -107,9 +107,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -132,21 +132,30 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.79" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -156,33 +165,33 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "winapi", + "windows-targets", ] [[package]] name = "chunked_transfer" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -198,6 +207,16 @@ dependencies = [ ] [[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -236,44 +255,30 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] name = "fastrand" -version = "1.9.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", - "windows-sys 0.48.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] @@ -284,9 +289,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -303,9 +308,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -323,18 +328,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -353,9 +349,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -364,28 +360,28 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -399,76 +395,67 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", ] [[package]] -name = "instant" -version = "0.1.12" +name = "itoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "io-lifetimes" -version = "1.0.11" +name = "js-sys" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", + "wasm-bindgen", ] [[package]] -name = "itoa" -version = "1.0.6" +name = "libc" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] -name = "js-sys" -version = "0.3.63" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "wasm-bindgen", + "bitflags", + "libc", + "redox_syscall", ] [[package]] -name = "libc" -version = "0.2.144" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.18" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "maybe-async" -version = "0.2.7" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -479,9 +466,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -491,9 +478,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -518,38 +505,44 @@ dependencies = [ ] [[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ordered-multimap" @@ -563,21 +556,30 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -600,9 +602,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -639,30 +641,21 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] @@ -689,13 +682,28 @@ dependencies = [ "cc", "libc", "once_cell", - "spin", - "untrusted", + "spin 0.5.2", + "untrusted 0.7.1", "web-sys", "winapi", ] [[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin 0.9.8", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] name = "rouille" version = "3.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -758,35 +766,34 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ "log", - "ring", + "ring 0.16.20", "sct", "webpki", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safemem" @@ -796,56 +803,57 @@ checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] name = "serde" -version = "1.0.163" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -853,33 +861,34 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "spin" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] -name = "subtle" -version = "2.5.0" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "syn" -version = "1.0.109" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.18" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -888,35 +897,35 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "once_cell", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", ] [[package]] @@ -930,13 +939,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", "libc", + "num-conv", "num_threads", + "powerfmt", "serde", "time-core", "time-macros", @@ -944,16 +956,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -971,9 +984,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -995,36 +1008,36 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -1036,10 +1049,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] name = "url" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1048,9 +1067,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "serde", @@ -1058,9 +1077,9 @@ dependencies = [ [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1070,34 +1089,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1105,28 +1125,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -1134,12 +1154,12 @@ dependencies = [ [[package]] name = "webpki" -version = "0.22.0" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring", - "untrusted", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -1174,142 +1194,113 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.42.2", + "windows-targets", ] [[package]] name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "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_aarch64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.48.0" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "zerocopy" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +name = "zerocopy-derive" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/corp/rih/frontend/Cargo.lock b/corp/rih/frontend/Cargo.lock index 40641d5de343..9ce686ff35d6 100644 --- a/corp/rih/frontend/Cargo.lock +++ b/corp/rih/frontend/Cargo.lock @@ -1500,19 +1500,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1537,9 +1538,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1547,9 +1548,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1560,9 +1561,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/corp/rih/frontend/Cargo.toml b/corp/rih/frontend/Cargo.toml index 1b9d5009791b..193fa919b45e 100644 --- a/corp/rih/frontend/Cargo.toml +++ b/corp/rih/frontend/Cargo.toml @@ -19,7 +19,7 @@ yew-router = "0.17" wasm-bindgen-futures = "0.4" # needs to be in sync with nixpkgs -wasm-bindgen = "= 0.2.92" +wasm-bindgen = "= 0.2.93" uuid = { version = "1.3.3", features = ["v4", "serde"] } [dependencies.serde] diff --git a/corp/russian/predlozhnik/Cargo.lock b/corp/russian/predlozhnik/Cargo.lock index 6874e3554c56..514050e55340 100644 --- a/corp/russian/predlozhnik/Cargo.lock +++ b/corp/russian/predlozhnik/Cargo.lock @@ -363,19 +363,20 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -400,9 +401,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -410,9 +411,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -423,9 +424,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/corp/russian/predlozhnik/Cargo.toml b/corp/russian/predlozhnik/Cargo.toml index 0b099ac927a3..63760812470a 100644 --- a/corp/russian/predlozhnik/Cargo.toml +++ b/corp/russian/predlozhnik/Cargo.toml @@ -9,4 +9,4 @@ lazy_static = "1.4" yew = "0.19" # needs to be in sync with nixpkgs -wasm-bindgen = "= 0.2.92" +wasm-bindgen = "= 0.2.93" diff --git a/docs/importing-projects.md b/docs/importing-projects.md new file mode 100644 index 000000000000..c68c8b1906ae --- /dev/null +++ b/docs/importing-projects.md @@ -0,0 +1,91 @@ +Importing projects into depot +============================= + +Before importing an existing `git`-based project into depot, a few questions +need to be answered: + + +* Is the project licensed under a free software license, or public domain? +* Do you need to import existing history? +* Do you need to export new history with hashes that continue on from the old + history? (e.g. importing an existing repository, and exporting from depot to + the old upstream) + +Think about this and then pick an approach below: + +## Import with no history (just commit) + +Simply copy the files to where you want them to be in depot, and commit. Nothing +else to do! + +## Import without continuous history (subtree merge) + +This import approach lets you drop an existing project into depot, keep its +existing history, but not retain the ability to continue external history. + +This means that if you, for example, import a project from a different git host +using this method, and then continue to commit to it inside of depot, you will +not be able to export a history consistent with your previous hashes using +`josh`. + +Commit hashes before the import will exist in depot and be valid. + +Still, this approach might be viable if a project "moves into" depot, or has +nothing depending on it externally. + +1. Pick a location in depot where you want your project to be (`$loc` from now on). +2. Fetch your project into the same git store as your depot clone (e.g. by + adding it as an upstream and fetching it). +3. Pick the commit you want to merge (`$commit` from now on). +4. Run `git subtree add --prefix=$loc $commit`, which will create the correct + merge commit. +5. Ensure Gerrit [knows about your commit](#preparing-merges-in-gerrit) for the + parent that is being merged. +6. Modify the merge commit's message to start with `subtree($project_name):`. + Gerrit **will not** allow merge commits that do not follow this format. +7. Push your subtree commit for review as normal. + +## Import with continuous history + +This approach imports the history using `josh`, which means that external +history before/after the import is consistent (you can continue committing in +`depot`, export the history back out, and from an external perspective nothing +changes). + +This is what we did with repositories like `nix-1p` and `nixery`. + +Note: Inside of depot, the pre-import commit hashes will **not make sense**. +`josh` will rewrite them in such a way that exporting the project will yield the +same hashes, but this rewriting changes the hashes of your commits inside of +depot. + +1. Pick a location in depot where you want your project to be (`$loc`). +2. Fetch your project into the same git store as your depot clone (e.g. by + adding it as an upstream and fetching it). +3. Check out the commit you want to merge into depot. +4. Run `josh-filter ":prefix=$loc"`, and take note of the `FILTERED_HEAD` ref + that it produces (`$filtered` from now on). +5. Ensure Gerrit [knows about the filtered commit](#preparing-merges-in-gerrit). +6. Merge the filtered commit into depot using a standard merge, but make sure to + add the `--allow-unrelated-histories` flag. Your commit message **must** + start with `subtree($project_name):`, otherwise Gerrit will not let you push + a merge. +7. Push the merge commit for review as usual. + +------------------------------------------------------ + +## Preparing merges in Gerrit + +When pushing a merge to Gerrit, it needs to know about all ancestors of the +merge, otherwise it will try to interpret commits as new CLs and reject them for +not having a change ID (or create a huge number of CLs, if they do have one). + +To prevent this, we have a special git ref called `subtree-staging` which you +can push external trees to. + +Access to `subtree-staging` has to be granted by a TVL admin, so ping tazjin, +lukegb, flokli, sterni and so on before proceeding. + +1. Determine the commit you want to merge (`$commit`). +2. Run `git push -f $commit origin/subtree-staging` (or replace `origin` with + whatever the TVL Gerrit remote is called in your clone). diff --git a/nix/writers/default.nix b/nix/writers/default.nix index 55355913a9f4..e849f1cb0e24 100644 --- a/nix/writers/default.nix +++ b/nix/writers/default.nix @@ -23,7 +23,6 @@ let { name , dependencies ? [ ] , doCheck ? true - , }: src: (if doCheck then testRustSimple else pkgs.lib.id) (pkgs.buildRustCrate ({ diff --git a/ops/besadii/default.nix b/ops/besadii/default.nix index 1199c56cfb94..424fa19b2b44 100644 --- a/ops/besadii/default.nix +++ b/ops/besadii/default.nix @@ -1,5 +1,5 @@ # This program is used as a Gerrit hook to trigger builds on -# Buildkite, Sourcegraph reindexing and other maintenance tasks. +# Buildkite and perform other maintenance tasks. { depot, ... }: depot.nix.buildGo.program { diff --git a/ops/besadii/main.go b/ops/besadii/main.go index 809acc29e8b4..aacd8f176ecf 100644 --- a/ops/besadii/main.go +++ b/ops/besadii/main.go @@ -8,7 +8,6 @@ // // Gerrit (ref-updated) hook: // - Trigger Buildkite CI builds -// - Trigger SourceGraph repository index updates // // Buildkite (post-command) hook: // - Submit CL verification status back to Gerrit @@ -55,10 +54,6 @@ type config struct { BuildkiteProject string `json:"buildkiteProject"` BuildkiteToken string `json:"buildkiteToken"` GerritChangeName string `json:"gerritChangeName"` - - // Optional configuration for Sourcegraph trigger updates. - SourcegraphUrl string `json:"sourcegraphUrl"` - SourcegraphToken string `json:"sourcegraphToken"` } // buildTrigger represents the information passed to besadii when it @@ -154,11 +149,6 @@ func loadConfig() (*config, error) { return nil, fmt.Errorf("invalid 'gerritChangeName': %s", cfg.GerritChangeName) } - // Rudimentary config validation logic - if cfg.SourcegraphUrl != "" && cfg.SourcegraphToken == "" { - return nil, fmt.Errorf("'SourcegraphToken' must be set if 'SourcegraphUrl' is set") - } - if cfg.Repository == "" || cfg.Branch == "" { return nil, fmt.Errorf("missing repository configuration (required: repository, branch)") } @@ -299,26 +289,6 @@ func triggerBuild(cfg *config, log *syslog.Writer, trigger *buildTrigger) error return nil } -// Trigger a Sourcegraph repository index update. -// -// https://docs.sourcegraph.com/admin/repo/webhooks -func triggerIndexUpdate(cfg *config, log *syslog.Writer) error { - req, err := http.NewRequest("POST", cfg.SourcegraphUrl, nil) - if err != nil { - return err - } - - req.Header.Add("Authorization", "token "+cfg.SourcegraphToken) - - _, err = http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to trigger Sourcegraph index update: %w", err) - } - - log.Info("triggered sourcegraph index update") - return nil -} - // Gerrit passes more flags than we want, but Rob Pike decided[0] in // 2013 that the Go art project will not allow users to ignore flags // because he "doesn't like it". This function allows users to ignore @@ -458,13 +428,6 @@ func gerritHookMain(cfg *config, log *syslog.Writer, trigger *buildTrigger) { if err != nil { log.Err(fmt.Sprintf("failed to trigger Buildkite build: %s", err)) } - - if cfg.SourcegraphUrl != "" && trigger.ref == cfg.Branch { - err = triggerIndexUpdate(cfg, log) - if err != nil { - log.Err(fmt.Sprintf("failed to trigger sourcegraph index update: %s", err)) - } - } } func postCommandMain(cfg *config) { diff --git a/ops/buildkite/tvl.tf b/ops/buildkite/tvl.tf index 4c45909a0c36..ee032a5143cb 100644 --- a/ops/buildkite/tvl.tf +++ b/ops/buildkite/tvl.tf @@ -8,7 +8,9 @@ terraform { } backend "s3" { - endpoint = "https://objects.dc-sto1.glesys.net" + endpoints = { + s3 = "https://objects.dc-sto1.glesys.net" + } bucket = "tvl-state" key = "terraform/tvl-buildkite" region = "glesys" @@ -16,6 +18,8 @@ terraform { skip_credentials_validation = true skip_region_validation = true skip_metadata_api_check = true + skip_requesting_account_id = true + skip_s3_checksum = true } } diff --git a/ops/journaldriver/Cargo.lock b/ops/journaldriver/Cargo.lock index 97bbe16ceb4c..eaf87cc525e3 100644 --- a/ops/journaldriver/Cargo.lock +++ b/ops/journaldriver/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "base64" @@ -25,9 +25,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "build-env" @@ -37,11 +37,11 @@ checksum = "e068f31938f954b695423ecaf756179597627d0828c0d3e48c0a722a8b23cf9e" [[package]] name = "cc" -version = "1.0.84" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.44" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" +checksum = "1e2161dd6eba090ff1594084e95fd67aeccf04382ffea77999ea94ed42ec67b6" dependencies = [ "curl-sys", "libc", @@ -83,14 +83,14 @@ dependencies = [ "openssl-sys", "schannel", "socket2", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "curl-sys" -version = "0.4.68+curl-8.4.0" +version = "0.4.74+curl-8.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a0d18d88360e374b16b2273c832b5e57258ffc1d4aa4f96b108e0738d5752f" +checksum = "8af10b986114528fcdc4b63b6f5f021b7057618411046a4de2ba0f0149a097bf" dependencies = [ "cc", "libc", @@ -98,14 +98,14 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -125,16 +125,6 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -178,9 +168,9 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "humantime" @@ -190,20 +180,20 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ "hermit-abi", - "rustix", - "windows-sys", + "libc", + "windows-sys 0.52.0", ] [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "journaldriver" @@ -224,15 +214,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libsystemd-sys" @@ -247,9 +237,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "libc", @@ -258,16 +248,10 @@ dependencies = [ ] [[package]] -name = "linux-raw-sys" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" - -[[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "medallion" @@ -285,21 +269,27 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags", "cfg-if", @@ -329,9 +319,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -341,9 +331,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "powerfmt" @@ -353,27 +343,27 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -383,9 +373,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -394,52 +384,39 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rustix" -version = "0.38.21" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "serde" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -448,30 +425,37 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "socket2" -version = "0.4.10" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "syn" -version = "2.0.39" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -494,21 +478,22 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -523,10 +508,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -549,54 +535,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "winapi" -version = "0.3.9" +name = "winapi-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-sys 0.59.0", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "winapi", + "windows-targets", ] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] name = "windows-sys" -version = "0.48.0" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", @@ -605,42 +579,48 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/ops/keycloak/main.tf b/ops/keycloak/main.tf index 923ac1939712..d5698700ce58 100644 --- a/ops/keycloak/main.tf +++ b/ops/keycloak/main.tf @@ -10,20 +10,29 @@ terraform { } backend "s3" { - endpoint = "https://objects.dc-sto1.glesys.net" - bucket = "tvl-state" - key = "terraform/tvl-keycloak" - region = "glesys" + endpoints = { + s3 = "https://objects.dc-sto1.glesys.net" + } + bucket = "tvl-state" + key = "terraform/tvl-keycloak" + region = "glesys" skip_credentials_validation = true skip_region_validation = true skip_metadata_api_check = true + skip_requesting_account_id = true + skip_s3_checksum = true } } provider "keycloak" { client_id = "terraform" url = "https://auth.tvl.fyi" + # NOTE: Docs mention this applies to "users of the legacy distribution of keycloak". + # However, we get a "failed to perform initial login to Keycloak: error + # sending POST request to https://auth.tvl.fyi/realms/master/protocol/openid-connect/token: 404 Not Found" + # if we don't set this. + base_path = "/auth" } resource "keycloak_realm" "tvl" { diff --git a/ops/keycloak/user_sources.tf b/ops/keycloak/user_sources.tf index 01307fff8df5..7fa71e36fbb2 100644 --- a/ops/keycloak/user_sources.tf +++ b/ops/keycloak/user_sources.tf @@ -22,6 +22,13 @@ resource "keycloak_ldap_user_federation" "tvl_ldap" { "inetOrgPerson", "organizationalPerson", ] + + lifecycle { + # Without this, terraform wants to recreate the resource. + ignore_changes = [ + delete_default_mappers + ] + } } # keycloak_oidc_identity_provider.github will be destroyed @@ -29,7 +36,7 @@ resource "keycloak_ldap_user_federation" "tvl_ldap" { resource "keycloak_oidc_identity_provider" "github" { alias = "github" provider_id = "github" - client_id = "6d7f8bb2e82bb6739556" + client_id = "Iv23liXfGNIr7InMg5Uo" client_secret = var.github_client_secret realm = keycloak_realm.tvl.id backchannel_supported = false diff --git a/ops/kontemplate/util/util.go b/ops/kontemplate/util/util.go index 56fa1e3fc9c5..f96f5c1d7aa4 100644 --- a/ops/kontemplate/util/util.go +++ b/ops/kontemplate/util/util.go @@ -29,13 +29,29 @@ func Merge(in1 *map[string]interface{}, in2 *map[string]interface{}) *map[string return in1 } + // The maps are map[string]interface{} with unknown depth. + // Loop over both maps into every level and merge them. new := make(map[string]interface{}) + for k, v := range *in1 { new[k] = v } for k, v := range *in2 { - new[k] = v + if existing, ok := new[k]; ok { + // If both values are maps, merge them recursively + if existingMap, ok := existing.(map[string]interface{}); ok { + if newMap, ok := v.(map[string]interface{}); ok { + new[k] = *Merge(&existingMap, &newMap) + } else { + new[k] = v + } + } else { + new[k] = v + } + } else { + new[k] = v + } } return &new diff --git a/ops/kontemplate/util/util_test.go b/ops/kontemplate/util/util_test.go index 53c56081758c..328add3d250f 100644 --- a/ops/kontemplate/util/util_test.go +++ b/ops/kontemplate/util/util_test.go @@ -47,6 +47,9 @@ func TestMergeWithNilMap(t *testing.T) { func TestMergeMaps(t *testing.T) { map1 := map[string]interface{}{ "foo": "bar", + "baz": map[string]interface{}{ + "qux": "quux", + }, } map2 := map[string]interface{}{ @@ -56,6 +59,9 @@ func TestMergeMaps(t *testing.T) { result := Merge(&map1, &map2) expected := map[string]interface{}{ "foo": "bar", + "baz": map[string]interface{}{ + "qux": "quux", + }, "bar": "baz", } diff --git a/ops/machines/all-systems.nix b/ops/machines/all-systems.nix index c4382fbddb2a..5df09fa0bd30 100644 --- a/ops/machines/all-systems.nix +++ b/ops/machines/all-systems.nix @@ -3,6 +3,8 @@ (with depot.ops.machines; [ sanduny whitby + nixery-01 + volgasprint-cache ]) ++ (with depot.users.tazjin.nixos; [ diff --git a/ops/machines/volgasprint-cache/default.nix b/ops/machines/volgasprint-cache/default.nix new file mode 100644 index 000000000000..88f2f2863dde --- /dev/null +++ b/ops/machines/volgasprint-cache/default.nix @@ -0,0 +1,153 @@ +# temporary machine for local binary cache proxy during VolgaSprint + +{ depot, lib, pkgs, ... }: # readTree options +{ config, ... }: # passed by module system + +let + mod = name: depot.path.origSrc + ("/ops/modules/" + name); +in +{ + imports = [ + (mod "tvl-users.nix") + ]; + + boot = { + kernelPackages = pkgs.linuxKernel.packages.linux_rpi4; + initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" ]; + loader = { + grub.enable = false; + generic-extlinux-compatible.enable = true; + }; + }; + + depot.auto-deploy = { + enable = true; + interval = "hourly"; + }; + + fileSystems = { + "/" = { + device = "/dev/disk/by-label/NIXOS_SD"; + fsType = "ext4"; + options = [ "noatime" ]; + }; + "/var/public-nix-cache" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; + }; + + networking = { + firewall = { + enable = true; + allowedTCPPorts = [ 80 443 8098 ]; + }; + + hostName = "volgacache"; + domain = "volgasprint.org"; + + wireless = { + enable = true; + networks.VolgaSprint.psk = "nixos-unstable"; + interfaces = [ "wlan0" ]; + }; + + wg-quick.interfaces = { + wg0 = { + address = [ "10.10.10.2/24" "fd42::1/128" ]; + dns = [ "1.1.1.1" ]; + privateKeyFile = "/etc/wireguard_private_key"; + + peers = [ + { + publicKey = "2MZzEGJzA3HrwkHf91TaKJEHwCNyVvsTLWoIYHrCxhY="; + presharedKeyFile = "/etc/wireguard_preshared_key"; + allowedIPs = [ "0.0.0.0/0" "::/0" ]; + endpoint = "195.201.63.240:8098"; + persistentKeepalive = 15; + } + ]; + }; + }; + }; + + services.openssh.enable = true; + + services.nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + + appendHttpConfig = '' + proxy_cache_path /tmp/pkgcache levels=1:2 keys_zone=cachecache:100m max_size=20g inactive=365d use_temp_path=off; + + # Cache only success status codes; in particular we don't want to cache 404s. + # See https://serverfault.com/a/690258/128321 + map $status $cache_header { + 200 "public"; + 302 "public"; + default "no-cache"; + } + access_log /var/log/nginx/access.log; + ''; + + virtualHosts."cache.volgasprint.org" = { + sslCertificate = "/etc/ssl/cache.volgasprint.org/key.pem"; + sslCertificateKey = "/etc/ssl/cache.volgasprint.org/key.pem"; + sslTrustedCertificate = "/etc/ssl/cache.volgasprint.org/chain.pem"; + + locations."/" = { + root = "/var/public-nix-cache"; + extraConfig = '' + expires max; + add_header Cache-Control $cache_header always; + # Ask the upstream server if a file isn't available locally + error_page 404 = @fallback; + ''; + }; + + extraConfig = '' + # Using a variable for the upstream endpoint to ensure that it is + # resolved at runtime as opposed to once when the config file is loaded + # and then cached forever (we don't want that): + # see https://tenzer.dk/nginx-with-dynamic-upstreams/ + # This fixes errors like + # nginx: [emerg] host not found in upstream "upstream.example.com" + # when the upstream host is not reachable for a short time when + # nginx is started. + resolver 80.67.169.12; # fdn dns + set $upstream_endpoint http://cache.nixos.org; + ''; + + locations."@fallback" = { + proxyPass = "$upstream_endpoint"; + extraConfig = '' + proxy_cache cachecache; + proxy_cache_valid 200 302 60d; + expires max; + add_header Cache-Control $cache_header always; + ''; + }; + + # We always want to copy cache.nixos.org's nix-cache-info file, + # and ignore our own, because `nix-push` by default generates one + # without `Priority` field, and thus that file by default has priority + # 50 (compared to cache.nixos.org's `Priority: 40`), which will make + # download clients prefer `cache.nixos.org` over our binary cache. + locations."= /nix-cache-info" = { + # Note: This is duplicated with the `@fallback` above, + # would be nicer if we could redirect to the @fallback instead. + proxyPass = "$upstream_endpoint"; + extraConfig = '' + proxy_cache cachecache; + proxy_cache_valid 200 302 60d; + expires max; + add_header Cache-Control $cache_header always; + ''; + }; + }; + }; + + hardware.enableRedistributableFirmware = true; + system.stateVersion = "23.11"; +} diff --git a/ops/machines/whitby/default.nix b/ops/machines/whitby/default.nix index 4c2fd0f2f533..3181ccde451c 100644 --- a/ops/machines/whitby/default.nix +++ b/ops/machines/whitby/default.nix @@ -11,6 +11,7 @@ in imports = [ (mod "atward.nix") (mod "cgit.nix") + (mod "cheddar.nix") (mod "clbot.nix") (mod "gerrit-autosubmit.nix") (mod "irccat.nix") @@ -24,7 +25,6 @@ in (mod "paroxysm.nix") (mod "restic.nix") (mod "smtprelay.nix") - (mod "sourcegraph.nix") (mod "teleirc.nix") (mod "tvl-buildkite.nix") (mod "tvl-slapd/default.nix") @@ -306,6 +306,9 @@ in agentCount = 32; }; + # Run Markdown/code renderer + services.depot.cheddar.enable = true; + # Start a local SMTP relay to Gmail (used by gerrit) services.depot.smtprelay = { enable = true; @@ -374,9 +377,6 @@ in }; services.depot = { - # Run a SourceGraph code search instance - sourcegraph.enable = true; - # Run a livegrep code search instance livegrep.enable = true; diff --git a/ops/modules/cheddar.nix b/ops/modules/cheddar.nix new file mode 100644 index 000000000000..8c3036978988 --- /dev/null +++ b/ops/modules/cheddar.nix @@ -0,0 +1,29 @@ +{ depot, config, pkgs, lib, ... }: + +let + cfg = config.services.depot.cheddar; + description = "cheddar - markdown/highlighting server"; +in +{ + options.services.depot.cheddar = with lib; { + enable = mkEnableOption description; + port = mkOption { + description = "Port on which cheddar should listen"; + type = types.int; + default = 4238; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.cheddar-server = { + inherit description; + wantedBy = [ "multi-user.target" ]; + script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.port} --sourcegraph-server"; + + serviceConfig = { + DynamicUser = true; + Restart = "always"; + }; + }; + }; +} diff --git a/ops/modules/sourcegraph.nix b/ops/modules/sourcegraph.nix deleted file mode 100644 index cbf836ab64d5..000000000000 --- a/ops/modules/sourcegraph.nix +++ /dev/null @@ -1,60 +0,0 @@ -# Run sourcegraph, including its entire machinery, in a container. -# Running it outside of a container is a futile endeavour for now. -{ depot, config, pkgs, lib, ... }: - -let - cfg = config.services.depot.sourcegraph; -in -{ - options.services.depot.sourcegraph = with lib; { - enable = mkEnableOption "SourceGraph code search engine"; - - port = mkOption { - description = "Port on which SourceGraph should listen"; - type = types.int; - default = 3463; - }; - - cheddarPort = mkOption { - description = "Port on which cheddar should listen"; - type = types.int; - default = 4238; - }; - }; - - config = lib.mkIf cfg.enable { - # Run a cheddar syntax highlighting server - systemd.services.cheddar-server = { - wantedBy = [ "multi-user.target" ]; - script = "${depot.tools.cheddar}/bin/cheddar --listen 0.0.0.0:${toString cfg.cheddarPort} --sourcegraph-server"; - - serviceConfig = { - DynamicUser = true; - Restart = "always"; - }; - }; - - virtualisation.oci-containers.containers.sourcegraph = { - image = "sourcegraph/server:3.40.0"; - - ports = [ - "127.0.0.1:${toString cfg.port}:7080" - ]; - - volumes = [ - "/var/lib/sourcegraph/etc:/etc/sourcegraph" - "/var/lib/sourcegraph/data:/var/opt/sourcegraph" - ]; - - # TODO(tazjin): Figure out what changed in the protocol. - # environment.SRC_SYNTECT_SERVER = "http://172.17.0.1:${toString cfg.cheddarPort}"; - - # Sourcegraph needs a higher nofile limit, it logs warnings - # otherwise (unclear whether it actually affects the service). - extraOptions = [ - "--ulimit" - "nofile=10000:10000" - ]; - }; - }; -} diff --git a/ops/modules/www/cs.tvl.fyi.nix b/ops/modules/www/cs.tvl.fyi.nix index fac814baf064..9555acf9ac47 100644 --- a/ops/modules/www/cs.tvl.fyi.nix +++ b/ops/modules/www/cs.tvl.fyi.nix @@ -1,3 +1,5 @@ +# This configuration redirects from the previous Sourcegraph instance to +# livegrep/cgit where appropriate. { config, ... }: { @@ -13,17 +15,50 @@ forceSSL = true; extraConfig = '' - location = / { - return 301 https://cs.tvl.fyi/depot; + set $lineno ""; + + # depot root + location = /depot { + return 301 https://code.tvl.fyi/tree/; } - location / { - proxy_set_header X-Sg-Auth "Anonymous"; - proxy_pass http://localhost:${toString config.services.depot.sourcegraph.port}; + # folder/file on canon + location ~ ^/depot/-/(blob|tree)/([^\s]*)$ { + set $path $2; + if ($args ~ ^L(\d+)(-\d+)?$) { + set $lineno "#n$1"; + } + + return 302 https://code.tvl.fyi/tree/$path$lineno; + } + + # folder/file on specific commit + location ~ ^/depot@([a-f0-9]+)/-/(blob|tree)/([^\s]*)$ { + set $commit $1; + set $path $3; + + if ($args ~ ^L(\d+)(-\d+)?$) { + set $lineno "#n$1"; + } + + return 302 https://code.tvl.fyi/tree/$path?id=$commit$lineno; + } + + # commit info + location ~ ^/depot/-/commit/([a-f0-9]+)$ { + set $commit $1; + return 302 https://code.tvl.fyi/commit/?id=$commit; } - location /users/Anonymous/settings { - return 301 https://cs.tvl.fyi; + # search handler + # This only redirects to the new search, it doesn't try to parse and + # rewrite the query. + location /search { + return 302 https://grep.tvl.fyi/search; + } + + location / { + return 404 "TVL code search has moved to grep.tvl.fyi and we could not figure out how to rewrite your query. Sorry!"; } ''; }; diff --git a/ops/modules/www/tazj.in.nix b/ops/modules/www/tazj.in.nix deleted file mode 100644 index 47eefca2a622..000000000000 --- a/ops/modules/www/tazj.in.nix +++ /dev/null @@ -1,54 +0,0 @@ -# serve tazjin's website & blog -{ depot, config, lib, pkgs, ... }: - -{ - imports = [ - ./base.nix - ]; - - config = { - services.nginx.virtualHosts."tazj.in" = { - enableACME = true; - forceSSL = true; - root = depot.users.tazjin.homepage; - serverAliases = [ "www.tazj.in" ]; - - extraConfig = '' - location = /en/rss.xml { - return 301 https://tazj.in/feed.atom; - } - - ${depot.users.tazjin.blog.oldRedirects} - location /blog/ { - alias ${depot.users.tazjin.blog.rendered}/; - - if ($request_uri ~ ^/(.*)\.html$) { - return 302 /$1; - } - - try_files $uri $uri.html $uri/ =404; - } - - location = /predlozhnik { - return 302 https://predlozhnik.ru; - } - - # redirect for easier entry on a TV - location = /tv { - return 302 https://tazj.in/blobs/play.html; - } - - # Temporary place for serving static files. - location /blobs/ { - alias /var/lib/tazjins-blobs/; - } - ''; - }; - - services.nginx.virtualHosts."git.tazj.in" = { - enableACME = true; - forceSSL = true; - extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; - }; - }; -} diff --git a/ops/nixos.nix b/ops/nixos.nix index 1442d89b30c1..c0410046c626 100644 --- a/ops/nixos.nix +++ b/ops/nixos.nix @@ -63,5 +63,6 @@ in rec { whitbySystem = (nixosFor depot.ops.machines.whitby).system; sandunySystem = (nixosFor depot.ops.machines.sanduny).system; nixeryDev01System = (nixosFor depot.ops.machines.nixery-01).system; + volgaSprintCacheSystem = (nixosFor depot.ops.machines.volgasprint-cache).system; meta.ci.targets = [ "sandunySystem" "whitbySystem" "nixeryDev01System" ]; } diff --git a/ops/pipelines/static-pipeline.yaml b/ops/pipelines/static-pipeline.yaml index af4f9d784e60..a7eea2eb97d8 100644 --- a/ops/pipelines/static-pipeline.yaml +++ b/ops/pipelines/static-pipeline.yaml @@ -88,10 +88,12 @@ steps: continue_on_failure: true # Exit with success or failure depending on whether any other steps - # failed. + # failed (but not retried). # # This information is checked by querying the Buildkite GraphQL API - # and fetching the count of failed steps. + # and fetching all failed steps, then filtering out the ones that were + # retried (retried jobs create new jobs, which would also show up in the + # query). # # This step must be :duck: (yes, really!) because the post-command # hook will inspect this name. @@ -109,8 +111,8 @@ steps: readonly FAILED_JOBS=$(curl 'https://graphql.buildkite.com/v1' \ --silent \ -H "Authorization: Bearer $(cat ${BUILDKITE_TOKEN_PATH})" \ - -d "{\"query\": \"query BuildStatusQuery { build(uuid: \\\"$BUILDKITE_BUILD_ID\\\") { jobs(passed: false) { count } } }\"}" | \ - jq -r '.data.build.jobs.count') + -d "{\"query\": \"query BuildStatusQuery { build(uuid: \\\"$BUILDKITE_BUILD_ID\\\") { jobs(passed: false, first: 500 ) { edges { node { ... on JobTypeCommand { retried } } } } } }\"}" | \ + jq -r '.data.build.jobs.edges | map(select(.node.retried == false)) | length') echo "$$FAILED_JOBS build jobs failed." diff --git a/ops/secrets/tf-keycloak.age b/ops/secrets/tf-keycloak.age index 237b9377bd79..7d470a6a304e 100644 --- a/ops/secrets/tf-keycloak.age +++ b/ops/secrets/tf-keycloak.age Binary files differdiff --git a/ops/users/default.nix b/ops/users/default.nix index 7bd36d9df4ad..a911954fd806 100644 --- a/ops/users/default.nix +++ b/ops/users/default.nix @@ -22,6 +22,11 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$5NEYPJ19nDITK5sGr4bzhQ$Xzpzth6y4w+HGvioHiYgzqFiwMDx0B7HAh+PVbkRuuk"; } { + username = "azahi"; + email = "azat@bahawi.net"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$BVRzgfs8YIorOTq62B00CQ$5UXHyG/Ivn5TqB7UNgfjYJMxTjun3NDvAStWFom4oas"; + } + { username = "chickadee"; email = "matthewktromp@gmail.com"; password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$HoZjVdJ90JmTEJf1MMLuDg$5Pa8kpJdFVsIxgoOTDsH0gv6CLumSIkMqYEn5UVfjwU"; @@ -37,11 +42,21 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=4,p=1$TxjbMGenhEmkyYLrg5uGhbr60THB86YeRZg5bPdiTJo$k9gbRlAPjmxwdUwzbavvsAVkckgQZ0jS2oTtvZBPysk"; } { + username = "domenkozar"; + email = "domen@cachix.org"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$c9WgMrTqPJZenOr5+wlnnQ$XOpRZRTkduzP2+NJBxkg2jhffurg7PDla4/RoAyclwI"; + } + { username = "edef"; email = "edef@edef.eu"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$OORx4ERbkgvTmuYCJA8cIw$i5qaBzHkRVw7Tl+wZsTFTDqJwF0vuZqhW3VpknMYMc0"; } { + username = "elle"; + email = "lnajt4@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$b5Bfq6u+fEKbtpixOl+yPw$nCyTLbSDYsw30ZiSxhJ6N99IIPQAnS2XRNlpEx9os+0"; + } + { username = "ericvolp12"; email = "ericvolp12@gmail.com"; password = "{SSHA}pSepaQ+/5KBLfJtRR5rfxGU8goAsXgvk"; @@ -112,6 +127,11 @@ password = "{SSHA}7a85VNhpFElFw+N5xcjgGmt4HnBsaGp4"; } { + username = "mrflos"; + email = "mrflos@yeswiki.pro"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$/D1y+6n3+0GigG9mCMqK8A$9PseWm3+QATxN/M3Wu4JM+CnIppLD/LbQaVEKLItv9o"; + } + { username = "noteed"; email = "noteed@gmail.com"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$rcLfF9xXysSx5sahVQLiMA$EgRgAVXn8+r2Csa3XgIHIEBf3hX4Y58pOHf2eDaBUnA"; @@ -154,6 +174,11 @@ password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$wOPEl9D3kSke//oLtbvqrg$j0npwwXgaXQ/emefKUwL59tH8hdmtzbgH2rQzWSmE2Y"; } { + username = "yl3dy"; + email = "aleksandr.kiselyov@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$vPvOa0/7RzDLuD/icQuIzQ$IVMSI7hh/frihuL11sNRj6Jz8TTn1wZZHjZZGszz3pI"; + } + { username = "implr"; email = "implr@hackerspace.pl"; password = "{ARGON2}$argon2id$v=19$m=65536,t=2,p=1$SHRFps5sVgyUXYdmqGPw9g$tEx9DwKK1RjWlw52GLwOZ/iHep+QJboaZE83f1pXSwQ"; @@ -259,4 +284,24 @@ email = "tvix@sinavir.fr"; password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$5GXvoN/enVljV97yE/Zasg$OrgY9/ge2LoxNm9OOqxh/kKLxoAvU54MbQa9WWiT0jY"; } + { + username = "emery"; + email = "emery@dmz.rs"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$b2k5UpTJafqM7yjHfVRjBg$zFGy/ZeI9Hb71TUfJwFp7qDKyUl8tdyFDUK1uNBYfUI"; + } + { + username = "aziz"; + email = "abd.aziz89@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$xTvdtTF+gavMfF8556CiiQ$IshnauhlEr80skpv5s6ueJLkQxlynzBt6oCp3cQrNCY"; + } + { + username = "nikiv"; + email = "nikita@nikiv.dev"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$79mMAD2XYa5dg7D9ueWMpw$Edf5WODrFpkNDyWaMdLKcgcErFLx4khmPIk8wzmYGUE"; + } + { + username = "ein-shved"; + email = "mestofel13@gmail.com"; + password = "{ARGON2}$argon2id$v=19$m=19456,t=2,p=1$D4wzfJoyFye48QNdrC66VA$aBJ/ZaL+rTgXoQa/nFdpHap3G/Oju8WlHaWTii95X8E"; + } ] diff --git a/third_party/chicago95/default.nix b/third_party/chicago95/default.nix new file mode 100644 index 000000000000..8703ec3548ad --- /dev/null +++ b/third_party/chicago95/default.nix @@ -0,0 +1,47 @@ +# A rendition of everyone's favourite computer theme. +{ pkgs, ... }: + +let + # Chicago95 has no GTK-4 theme (because GTK-4 removed important features that + # it needs), but there is a project with an approximation. + # + # This is a bit of a hack, but I inject that project's GTK-4 theme as if it + # was a part of Chicago95. + # + # This other project is GPL-3.0, under which Chicago95 is also distributed. + gtk4ProjectSrc = pkgs.fetchFromGitHub { + owner = "B00merang-Project"; + repo = "Windows-95"; + rev = "055abd7a3608afdcb2ef021732e07020f2b416b2"; + hash = "sha256:1li6wzyn3y09d188xki1h96pmn4xcx2lklfc4rkiq2y2r22wx7kz"; + }; +in +pkgs.stdenvNoCC.mkDerivation { + pname = "Chicago95"; + version = "master"; + + src = pkgs.fetchFromGitHub { + owner = "grassmunk"; + repo = "Chicago95"; + rev = "bdf5cf36a16102aaac297f3de887c601c2b1146f"; + hash = "sha256:11fsy3bam1rhp1292zflvzmf1432z1p0ncwy3601wl2f8rnvfdfm"; + }; + + # The project has a Makefile, but it's broken in all sorts of ways, so we just + # copy the important stuff manually. + dontBuild = true; + installPhase = '' + mkdir -p $out/share/{icons,fonts,themes,sounds,qt5ct/colors} + + cp -r Theme/Chicago95 $out/share/themes + cp -r Icons/* $out/share/icons + cp -r Cursors/* $out/share/icons + cp -r Fonts/* $out/share/fonts + cp Extras/Chicago95_qt.conf $out/share/qt5ct/colors + + cp -r ${gtk4ProjectSrc}/gtk-4.0 $out/share/themes/Chicago95 + ''; + + meta.license = pkgs.lib.licenses.gpl3; +} + diff --git a/third_party/gitignoreSource/default.nix b/third_party/gitignoreSource/default.nix index 150de7c990e4..78a7414ed3ad 100644 --- a/third_party/gitignoreSource/default.nix +++ b/third_party/gitignoreSource/default.nix @@ -1,15 +1,7 @@ -{ pkgs, ... }: +{ depot, lib, ... }: let - gitignoreNix = import - (pkgs.fetchFromGitHub { - owner = "hercules-ci"; - repo = "gitignore"; - rev = "f9e996052b5af4032fe6150bba4a6fe4f7b9d698"; - sha256 = "0jrh5ghisaqdd0vldbywags20m2cxpkbbk5jjjmwaw0gr8nhsafv"; - }) - { inherit (pkgs) lib; }; - + gitignoreNix = import depot.third_party.sources."gitignore.nix" { inherit lib; }; in { __functor = _: gitignoreNix.gitignoreSource; diff --git a/third_party/nixpkgs/default.nix b/third_party/nixpkgs/default.nix index 03dc7b267c98..3ec49ea084d8 100644 --- a/third_party/nixpkgs/default.nix +++ b/third_party/nixpkgs/default.nix @@ -58,6 +58,9 @@ let # the big lis package change breaks everything in //3p/lisp, undo it for now. lispPackages = stableNixpkgs.lispPackages; + + # mypaint is broken on stable (2024-09-05) + mypaint = stableNixpkgs.mypaint; }; # Overlay to expose the nixpkgs commits we are using to other Nix code. diff --git a/third_party/overlays/patches/cbtemulator-uds.patch b/third_party/overlays/patches/cbtemulator-uds.patch deleted file mode 100644 index a19255306f88..000000000000 --- a/third_party/overlays/patches/cbtemulator-uds.patch +++ /dev/null @@ -1,140 +0,0 @@ -commit 1397e10225d8c6fd079a86fccd58fb5d0f4200bc -Author: Florian Klink <flokli@flokli.de> -Date: Fri Mar 29 10:06:34 2024 +0100 - - feat(bigtable/emulator): allow listening on Unix Domain Sockets - - cbtemulator listening on unix domain sockets is much easier than trying - to allocate free TCP ports, especially if many cbtemulators are run at - the same time in integration tests. - - This adds an additional flag, address, which has priority if it's set, - rather than host:port. - - `NewServer` already takes a `laddr string`, so we simply check for it to - contain slashes, and if so, listen on unix, rather than TCP. - -diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go -index 556abc2a85..33e4bf2667 100644 ---- a/bttest/inmem.go -+++ b/bttest/inmem.go -@@ -40,6 +40,7 @@ import ( - "math" - "math/rand" - "net" -+ "os" - "regexp" - "sort" - "strings" -@@ -106,7 +107,15 @@ type server struct { - // The Server will be listening for gRPC connections, without TLS, - // on the provided address. The resolved address is named by the Addr field. - func NewServer(laddr string, opt ...grpc.ServerOption) (*Server, error) { -- l, err := net.Listen("tcp", laddr) -+ var l net.Listener -+ var err error -+ -+ // If the address contains slashes, listen on a unix domain socket instead. -+ if strings.Contains(laddr, "/") { -+ l, err = net.Listen("unix", laddr) -+ } else { -+ l, err = net.Listen("tcp", laddr) -+ } - if err != nil { - return nil, err - } -diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go -index 144c09ffb1..deaf69b717 100644 ---- a/cmd/emulator/cbtemulator.go -+++ b/cmd/emulator/cbtemulator.go -@@ -27,8 +27,9 @@ import ( - ) - - var ( -- host = flag.String("host", "localhost", "the address to bind to on the local machine") -- port = flag.Int("port", 9000, "the port number to bind to on the local machine") -+ host = flag.String("host", "localhost", "the address to bind to on the local machine") -+ port = flag.Int("port", 9000, "the port number to bind to on the local machine") -+ address = flag.String("address", "", "address:port number or unix socket path to listen on. Has priority over host/port") - ) - - const ( -@@ -42,7 +43,15 @@ func main() { - grpc.MaxRecvMsgSize(maxMsgSize), - grpc.MaxSendMsgSize(maxMsgSize), - } -- srv, err := bttest.NewServer(fmt.Sprintf("%s:%d", *host, *port), opts...) -+ -+ var laddr string -+ if *address != "" { -+ laddr = *address -+ } else { -+ laddr = fmt.Sprintf("%s:%d", *host, *port) -+ } -+ -+ srv, err := bttest.NewServer(laddr, opts...) - if err != nil { - log.Fatalf("failed to start emulator: %v", err) - } -commit ce16f843d6c93159d86b3807c6d9ff66e43aac67 -Author: Florian Klink <flokli@flokli.de> -Date: Fri Mar 29 11:53:15 2024 +0100 - - feat(bigtable): clean up unix socket on close - - Call srv.Close when receiving an interrupt, and delete the unix domain - socket in that function. - -diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go -index 33e4bf2667..0dc96024b1 100644 ---- a/bttest/inmem.go -+++ b/bttest/inmem.go -@@ -148,6 +148,11 @@ func (s *Server) Close() { - - s.srv.Stop() - s.l.Close() -+ -+ // clean up unix socket -+ if strings.Contains(s.Addr, "/") { -+ _ = os.Remove(s.Addr) -+ } - } - - func (s *server) CreateTable(ctx context.Context, req *btapb.CreateTableRequest) (*btapb.Table, error) { -diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go -index deaf69b717..5a9e8f7a8c 100644 ---- a/cmd/emulator/cbtemulator.go -+++ b/cmd/emulator/cbtemulator.go -@@ -18,9 +18,12 @@ cbtemulator launches the in-memory Cloud Bigtable server on the given address. - package main - - import ( -+ "context" - "flag" - "fmt" - "log" -+ "os" -+ "os/signal" - - "cloud.google.com/go/bigtable/bttest" - "google.golang.org/grpc" -@@ -51,11 +54,18 @@ func main() { - laddr = fmt.Sprintf("%s:%d", *host, *port) - } - -+ ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) -+ defer stop() -+ - srv, err := bttest.NewServer(laddr, opts...) - if err != nil { - log.Fatalf("failed to start emulator: %v", err) - } - - fmt.Printf("Cloud Bigtable emulator running on %s\n", srv.Addr) -- select {} -+ select { -+ case <-ctx.Done(): -+ srv.Close() -+ stop() -+ } - } diff --git a/third_party/overlays/tvl.nix b/third_party/overlays/tvl.nix index 8d541f103da2..a7cc68b2d994 100644 --- a/third_party/overlays/tvl.nix +++ b/third_party/overlays/tvl.nix @@ -90,13 +90,6 @@ depot.nix.readTree.drvTargets { }; })); - # https://github.com/googleapis/google-cloud-go/pull/9665 - cbtemulator = super.cbtemulator.overrideAttrs (old: { - patches = old.patches or [ ] ++ [ - ./patches/cbtemulator-uds.patch - ]; - }); - crate2nix = super.crate2nix.overrideAttrs (old: { patches = old.patches or [ ] ++ [ # TODO(Kranzes): Remove in next release. diff --git a/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch new file mode 100644 index 000000000000..0f4a6219b298 --- /dev/null +++ b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch @@ -0,0 +1,78 @@ +From cc4718cbea1bd70de21a2be515a944802246ffc7 Mon Sep 17 00:00:00 2001 +From: Vincent Ambo <mail@tazj.in> +Date: Sun, 15 Sep 2024 03:08:28 +0300 +Subject: [PATCH] remove dependency on plausible + +We don't need spyware, thanks. +--- + package-lock.json | 9 --------- + package.json | 1 - + src/App.svelte | 8 -------- + 3 files changed, 18 deletions(-) + +diff --git a/package-lock.json b/package-lock.json +index d52de6c0..d96e342f 100644 +--- a/package-lock.json ++++ b/package-lock.json +@@ -29,7 +29,6 @@ + "marked-katex-extension": "^5.1.1", + "marked-linkify-it": "^3.1.11", + "md5": "^2.3.0", +- "plausible-tracker": "^0.3.9", + "svelte": "^4.2.19", + "twemoji": "^14.0.2", + "zod": "^3.23.8" +@@ -3697,14 +3696,6 @@ + "url": "https://github.com/sponsors/jonschlinkert" + } + }, +- "node_modules/plausible-tracker": { +- "version": "0.3.9", +- "resolved": "https://registry.npmjs.org/plausible-tracker/-/plausible-tracker-0.3.9.tgz", +- "integrity": "sha512-hMhneYm3GCPyQon88SZrVJx+LlqhM1kZFQbuAgXPoh/Az2YvO1B6bitT9qlhpiTdJlsT5lsr3gPmzoVjb5CDXA==", +- "engines": { +- "node": ">=10" +- } +- }, + "node_modules/playwright": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", +diff --git a/package.json b/package.json +index 6d569ad9..61e8d892 100644 +--- a/package.json ++++ b/package.json +@@ -73,7 +73,6 @@ + "marked-katex-extension": "^5.1.1", + "marked-linkify-it": "^3.1.11", + "md5": "^2.3.0", +- "plausible-tracker": "^0.3.9", + "svelte": "^4.2.19", + "twemoji": "^14.0.2", + "zod": "^3.23.8" +diff --git a/src/App.svelte b/src/App.svelte +index 8161c390..4281ba61 100644 +--- a/src/App.svelte ++++ b/src/App.svelte +@@ -1,6 +1,4 @@ + <script lang="ts"> +- import Plausible from "plausible-tracker"; +- + import * as router from "@app/lib/router"; + import { unreachable } from "@app/lib/utils"; + +@@ -28,12 +26,6 @@ + + void router.loadFromLocation(); + +- if (import.meta.env.PROD) { +- const plausible = Plausible({ domain: "app.radicle.xyz" }); +- +- plausible.enableAutoPageviews(); +- } +- + $: document.documentElement.setAttribute("data-codefont", $codeFont); + $: document.documentElement.setAttribute("data-theme", $theme); + </script> +-- +2.46.0 + diff --git a/third_party/radicle-explorer/default.nix b/third_party/radicle-explorer/default.nix new file mode 100644 index 000000000000..7bf7dc3798d9 --- /dev/null +++ b/third_party/radicle-explorer/default.nix @@ -0,0 +1,66 @@ +# radicle-explorer is the web UI for Radicle. +# +# They have an upstream Nix derivation, but it only works with experimental +# features Nix and is quite messy, so this is a copy of the relevant parts. +{ lib, pkgs, ... }: + +let + twemoji-assets = pkgs.fetchFromGitHub { + owner = "twitter"; + repo = "twemoji"; + rev = "v14.0.2"; + hash = "sha256-YoOnZ5uVukzi/6bLi22Y8U5TpplPzB7ji42l+/ys5xI="; + }; + + httpdSrc = pkgs.radicle-httpd.src; +in +lib.fix (self: pkgs.buildNpmPackage rec { + pname = "radicle-explorer"; + version = (builtins.fromJSON (builtins.readFile "${src}/package.json")).version; + + # source should be synced with the httpd, which is already in nixpkgs + src = pkgs.fetchgit { + inherit (httpdSrc) url rev; + hash = "sha256:09m13238h6j7g02r6332ihgyyzbjx90pgz14rz29pgv7936h6il8"; + }; + + # This might change during nixpkgs bumps and will need updating. Need to fix + # upstream so that there is a normal, callable derivation. + npmDepsHash = "sha256:1hbrzfjkfc0q8qk03yi6qb9zqm57h7hnkn7fl0yxkrzbrljaljaz"; + + patches = [ + ./0001-remove-dependency-on-plausible.patch + ]; + + postPatch = '' + patchShebangs --build ./scripts + mkdir -p "public/twemoji" + cp -t public/twemoji -r -- ${twemoji-assets}/assets/svg/* + : >scripts/install-twemoji-assets + ''; + dontConfigure = true; + doCheck = false; + + installPhase = '' + runHook preInstall + mkdir -p "$out" + cp -r -t "$out" build/* + runHook postInstall + ''; + + # Override the build-time configuration with other preferred seeds which are + # displayed on the landing page. + passthru.withPreferredSeeds = seeds: + let + originalConfig = builtins.fromJSON (builtins.readFile "${src}/config/default.json"); + config = originalConfig // { + preferredSeeds = seeds; + }; + newConfig = pkgs.writeText "local.json" (builtins.toJSON config); + in + self.overrideAttrs (_: { + preBuild = '' + cp ${newConfig} config/local.json + ''; + }); +}) diff --git a/third_party/rust-crates/default.nix b/third_party/rust-crates/default.nix index 697e47cddefc..a473a8346a6b 100644 --- a/third_party/rust-crates/default.nix +++ b/third_party/rust-crates/default.nix @@ -292,130 +292,4 @@ depot.nix.readTree.drvTargets rec{ sha256 = "1kd047p8jv6mhmfzddjvfa2nwkfrb3l1wml6lfm51n1cr06cc9lz"; }; - libz-sys = buildRustCrate { - pname = "libz-sys"; - version = "1.1.2"; - sha256 = "1y7v6bkwr4b6yaf951p1ns7mx47b29ziwdd5wziaic14gs1gwq30"; - buildDependencies = [ - cc - pkg-config - ]; - }; - - libgit2-sys = buildRustCrate { - pname = "libgit2-sys"; - version = "0.16.2+1.7.2"; - sha256 = "0bs446idbmg8s13jvb0ck6qmrskcdn2mp3d4mn9ggxbmiw4ryd3g"; - dependencies = [ - libc - libz-sys - ]; - libPath = "lib.rs"; - libName = "libgit2_sys"; - # TODO: this should be available via `pkgs.defaultCrateOverrides`, - # I thought that was included by default? - nativeBuildInputs = [ pkg-config ]; - buildInputs = [ pkgs.zlib pkgs.libgit2 ]; - buildDependencies = [ - cc - pkg-config - ]; - env.LIBGIT2_NO_VENDOR = "1"; - }; - - matches = buildRustCrate { - pname = "matches"; - version = "0.1.8"; - sha256 = "03hl636fg6xggy0a26200xs74amk3k9n0908rga2szn68agyz3cv"; - libPath = "lib.rs"; - }; - - percent-encoding = buildRustCrate { - pname = "percent-encoding"; - version = "2.1.0"; - sha256 = "0i838f2nr81585ckmfymf8l1x1vdmx6n8xqvli0lgcy60yl2axy3"; - libPath = "lib.rs"; - }; - - form_urlencoded = buildRustCrate { - pname = "form_urlencoded"; - version = "1.0.1"; - sha256 = "0rhv2hfrzk2smdh27walkm66zlvccnnwrbd47fmf8jh6m420dhj8"; - dependencies = [ - matches - percent-encoding - ]; - }; - - tinyvec_macros = buildRustCrate { - pname = "tinyvec_macros"; - version = "0.1.0"; - sha256 = "0aim73hyq5g8b2hs9gjq2sv0xm4xzfbwp5fdyg1frljqzkapq682"; - }; - - tinyvec = buildRustCrate { - pname = "tinyvec"; - version = "1.2.0"; - sha256 = "1c95nma20kiyrjwfsk7hzd5ir6yy4bm63fmfbfb4dm9ahnlvdp3y"; - features = [ "alloc" ]; - dependencies = [ - tinyvec_macros - ]; - }; - - unicode-normalization = buildRustCrate { - pname = "unicode-normalization"; - version = "0.1.17"; - sha256 = "0w4s0avzlf7pzcclhhih93aap613398sshm6jrxcwq0f9lhis11c"; - dependencies = [ - tinyvec - ]; - }; - - unicode-bidi = buildRustCrate { - pname = "unicode-bidi"; - version = "0.3.5"; - sha256 = "193jzlxj1dfcms2381lyd45zh4ywlicj9lzcfpid1zbkmfarymkz"; - dependencies = [ - matches - ]; - }; - - idna = buildRustCrate { - pname = "idna"; - version = "0.2.3"; - sha256 = "0hwypd0fpym9lmd4bbqpwyr5lhrlvmvzhi1vy9asc5wxwkzrh299"; - dependencies = [ - matches - unicode-normalization - unicode-bidi - ]; - }; - - url = buildRustCrate { - pname = "url"; - version = "2.2.1"; - sha256 = "1ci1djafh83qhpzbmxnr9w5gcrjs3ghf8rrxdy4vklqyji6fvn5v"; - dependencies = [ - form_urlencoded - idna - matches - percent-encoding - ]; - }; - - - git2 = buildRustCrate { - pname = "git2"; - edition = "2018"; - version = "0.18.1"; - sha256 = "1d1wm8cn37svyxgvzfapwilkkc9d2x7fcrgciwn8b2pv9aqz102k"; - dependencies = [ - bitflags - libc - libgit2-sys - log - url - ]; - }; } diff --git a/third_party/sources/sources.json b/third_party/sources/sources.json index 14186dc4454e..dda541e780bc 100644 --- a/third_party/sources/sources.json +++ b/third_party/sources/sources.json @@ -5,10 +5,22 @@ "homepage": "https://matrix.to/#/#agenix:nixos.org", "owner": "ryantm", "repo": "agenix", - "rev": "de96bd907d5fbc3b14fc33ad37d1b9a3cb15edc6", - "sha256": "0rkcx72bq7fm5b1qy1nrzp8v93nv784wh11srgi3pi0m6sr9g03f", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "sha256": "1x8nd8hvsq6mvzig122vprwigsr3z2skanig65haqswn7z7amsvg", "type": "tarball", - "url": "https://github.com/ryantm/agenix/archive/de96bd907d5fbc3b14fc33ad37d1b9a3cb15edc6.tar.gz", + "url": "https://github.com/ryantm/agenix/archive/f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41.tar.gz", + "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" + }, + "gitignore.nix": { + "branch": "master", + "description": "Nix functions for filtering local git sources", + "homepage": "", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "sha256": "02wxkdpbhlm3yk5mhkhsp3kwakc16xpmsf2baw57nz1dg459qv8w", + "type": "tarball", + "url": "https://github.com/hercules-ci/gitignore.nix/archive/637db329424fd7e46cf4185293b9cc8c88c95394.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "home-manager": { @@ -17,10 +29,10 @@ "homepage": "https://nix-community.github.io/home-manager/", "owner": "nix-community", "repo": "home-manager", - "rev": "d0240a064db3987eb4d5204cf2400bc4452d9922", - "sha256": "0dnb7ph6v4vh30cxhx223xk23kjwfnfc87hz54pyv5ccb393sifs", + "rev": "e5fa72bad0c6f533e8d558182529ee2acc9454fe", + "sha256": "0sfnsa4sypbq6390jf0la7x6260cvpmml7d0855m9xfhc1x8y0z1", "type": "tarball", - "url": "https://github.com/nix-community/home-manager/archive/d0240a064db3987eb4d5204cf2400bc4452d9922.tar.gz", + "url": "https://github.com/nix-community/home-manager/archive/e5fa72bad0c6f533e8d558182529ee2acc9454fe.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "impermanence": { @@ -29,10 +41,10 @@ "homepage": "", "owner": "nix-community", "repo": "impermanence", - "rev": "23c1f06316b67cb5dabdfe2973da3785cfe9c34a", - "sha256": "1c99hc2mv0f5rjxj97wcypyrpi5i3xmpi3sd2fnw2481jxgqn5h3", + "rev": "63f4d0443e32b0dd7189001ee1894066765d18a5", + "sha256": "0xnshgwfg834dm9l14p2w3wmhjysjpqpgfk37im0vrk1qgva19g2", "type": "tarball", - "url": "https://github.com/nix-community/impermanence/archive/23c1f06316b67cb5dabdfe2973da3785cfe9c34a.tar.gz", + "url": "https://github.com/nix-community/impermanence/archive/63f4d0443e32b0dd7189001ee1894066765d18a5.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "naersk": { @@ -65,10 +77,10 @@ "homepage": "", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b73c2221a46c13557b1b3be9c2070cc42cf01eb3", - "sha256": "023rghcidsxfwa8hf3g7bi86cnjj03l9j1mmmvdn6lhb875b9r20", + "rev": "574d1eac1c200690e27b8eb4e24887f8df7ac27c", + "sha256": "0s6h7r9jin9sd8l85hdjwl3jsvzkddn3blggy78w4f21qa3chymz", "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/b73c2221a46c13557b1b3be9c2070cc42cf01eb3.tar.gz", + "url": "https://github.com/NixOS/nixpkgs/archive/574d1eac1c200690e27b8eb4e24887f8df7ac27c.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "nixpkgs-stable": { @@ -89,10 +101,10 @@ "homepage": "", "owner": "oxalica", "repo": "rust-overlay", - "rev": "9803f6e04ca37a2c072783e8297d2080f8d0e739", - "sha256": "1b566msx04y4s0hvwsza9gcv4djmni4fa6ik7q2m33b6x4vrb92w", + "rev": "c3c175c74cd0e8c2c40a0e22bc6e3005c4d28d64", + "sha256": "0hd5p42kg8xh1vv7dxlhncg33jfi8hli8w3m96flqpi50dam6nwr", "type": "tarball", - "url": "https://github.com/oxalica/rust-overlay/archive/9803f6e04ca37a2c072783e8297d2080f8d0e739.tar.gz", + "url": "https://github.com/oxalica/rust-overlay/archive/c3c175c74cd0e8c2c40a0e22bc6e3005c4d28d64.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" }, "rustsec-advisory-db": { @@ -101,10 +113,10 @@ "homepage": "https://rustsec.org", "owner": "RustSec", "repo": "advisory-db", - "rev": "9d024c07ee8c18609b43436bc865abf46636e250", - "sha256": "0fyxx52yfaaniqgihhf5zgapgx3s6fsjdrf0rjm8z028svj121pp", + "rev": "7fbf1e630ae52b7b364791a107b5bee5ff929496", + "sha256": "05qmglwbffxsv18w6rw638gaf7ynldqcw8pf7k5brrgfnwsca9s2", "type": "tarball", - "url": "https://github.com/RustSec/advisory-db/archive/9d024c07ee8c18609b43436bc865abf46636e250.tar.gz", + "url": "https://github.com/RustSec/advisory-db/archive/7fbf1e630ae52b7b364791a107b5bee5ff929496.tar.gz", "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" } } diff --git a/tools/cheddar/Cargo.lock b/tools/cheddar/Cargo.lock index 41632ea15927..c88cba580a08 100644 --- a/tools/cheddar/Cargo.lock +++ b/tools/cheddar/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "adler32" @@ -16,9 +16,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -64,50 +64,51 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -129,9 +130,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" @@ -141,9 +142,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bincode" @@ -177,9 +178,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -192,9 +193,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -223,17 +224,23 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.84" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ - "libc", + "shlex", ] [[package]] @@ -258,21 +265,21 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] name = "chunked_transfer" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cca491388666e04d7248af3f60f0c40cfb0991c72205595d7c396e3510207d1a" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" [[package]] name = "clap" @@ -291,9 +298,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.8" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -301,22 +308,22 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.8" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.10.0", + "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -326,15 +333,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "comrak" @@ -342,7 +349,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c11e55664fcff7f4d37cc2adf3a1996913692f037312f4ab0909047fdd2bf962" dependencies = [ - "clap 4.4.8", + "clap 4.5.16", "entities", "memchr", "once_cell", @@ -358,24 +365,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -402,9 +409,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -433,12 +440,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.6" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -453,27 +460,27 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys", + "libredox", + "windows-sys 0.59.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", @@ -487,9 +494,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -506,9 +513,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -526,15 +533,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -547,15 +554,15 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -565,9 +572,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -588,9 +595,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -598,48 +605,56 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] -name = "line-wrap" -version = "0.1.1" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "safemem", + "bitflags 2.6.0", + "libc", + "redox_syscall", ] [[package]] @@ -650,21 +665,21 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -674,9 +689,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -684,11 +699,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -710,10 +725,16 @@ dependencies = [ ] [[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -724,24 +745,24 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "num_threads" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "onig" @@ -767,15 +788,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -784,9 +805,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -794,9 +815,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -807,9 +828,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -818,19 +839,18 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "indexmap", - "line-wrap", "quick-xml", "serde", "time", @@ -844,15 +864,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -865,18 +888,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -913,56 +936,41 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rouille" @@ -990,22 +998,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safemem" @@ -1024,18 +1032,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -1044,20 +1052,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -1077,6 +1086,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1084,15 +1099,15 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.39" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1101,9 +1116,9 @@ dependencies = [ [[package]] name = "syntect" -version = "5.1.0" +version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" dependencies = [ "bincode", "bitflags 1.3.2", @@ -1113,8 +1128,9 @@ dependencies = [ "once_cell", "onig", "plist", - "regex-syntax 0.7.5", + "regex-syntax", "serde", + "serde_derive", "serde_json", "thiserror", "walkdir", @@ -1123,15 +1139,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1141,7 +1157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1155,18 +1171,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -1184,13 +1200,14 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", "libc", + "num-conv", "num_threads", "powerfmt", "serde", @@ -1206,10 +1223,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -1227,9 +1245,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1278,9 +1296,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -1290,18 +1308,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode_categories" @@ -1311,9 +1329,9 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "url" -version = "2.4.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -1322,9 +1340,9 @@ dependencies = [ [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vec_map" @@ -1334,15 +1352,15 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1356,19 +1374,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1381,9 +1400,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1391,9 +1410,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1404,9 +1423,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "winapi" @@ -1426,11 +1445,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -1441,11 +1460,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -1454,7 +1473,25 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1463,13 +1500,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1479,42 +1532,90 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] name = "xdg" version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1528,3 +1629,24 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/tools/depot-deps.nix b/tools/depot-deps.nix index c2f1cd302ce8..5fa1fe23be20 100644 --- a/tools/depot-deps.nix +++ b/tools/depot-deps.nix @@ -8,6 +8,7 @@ depot.nix.lazy-deps { depotfmt.attr = "tools.depotfmt"; fetch-depot-inbox.attr = "tools.fetch-depot-inbox"; git-r.attr = "tools.git-r"; + git-review.attr = "third_party.nixpkgs.git-review"; gerrit-update.attr = "tools.gerrit-update"; gerrit.attr = "tools.gerrit-cli"; hash-password.attr = "tools.hash-password"; diff --git a/tools/depotfmt.nix b/tools/depotfmt.nix index e40001018c37..7c45f8be44b4 100644 --- a/tools/depotfmt.nix +++ b/tools/depotfmt.nix @@ -1,24 +1,14 @@ # Builds treefmt for depot, with a hardcoded configuration that # includes the right paths to formatters. -{ depot, pkgs, ... }: +{ pkgs, ... }: let - # terraform fmt can't handle multiple paths at once, but treefmt - # expects this - terraformat = pkgs.writeShellScript "terraformat" '' - echo "$@" | xargs -n1 ${pkgs.terraform}/bin/terraform fmt - ''; - config = pkgs.writeText "depot-treefmt-config" '' [formatter.go] - command = "${depot.nix.buildGo.go}/bin/gofmt" + command = "${pkgs.go}/bin/gofmt" options = [ "-w" ] includes = ["*.go"] - [formatter.tf] - command = "${terraformat}" - includes = [ "*.tf" ] - [formatter.nix] command = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt" includes = [ "*.nix" ] @@ -31,6 +21,7 @@ let options = ["--edition", "2021"] includes = [ "*.rs" ] excludes = [ + "users/emery/*", "users/tazjin/*", ] ''; diff --git a/tools/eaglemode/commands/B.nix b/tools/eaglemode/commands/B.nix new file mode 100644 index 000000000000..bca3d3a87a87 --- /dev/null +++ b/tools/eaglemode/commands/B.nix @@ -0,0 +1,23 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; +in +em.mkCommand { + name = "9 B"; + hotkey = "Ctrl+E"; + icon = "${./plan9.tga}"; + + description = '' + Plumb target to Sam or Acme + ''; + + code = '' + ErrorIfNotSingleTarget(); + + my @tgt=GetTgt(); + my $dir=$tgt[0]; + + ExecOrError('${pkgs.plan9port}/bin/9', 'B', $dir); + ''; +} diff --git a/tools/eaglemode/commands/emacsclient.nix b/tools/eaglemode/commands/emacsclient.nix new file mode 100644 index 000000000000..bac3674120ee --- /dev/null +++ b/tools/eaglemode/commands/emacsclient.nix @@ -0,0 +1,26 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + icon = em.mkTGA "emacs" "${pkgs.emacs}/share/icons/hicolor/128x128/apps/emacs.png"; +in +em.mkCommand { + name = "Emacsclient"; + hotkey = "Ctrl+E"; + icon = "${icon}"; + + description = '' + Open target in Emacsclient. + + Emacs server must be running already for this to have any effect. + ''; + + code = '' + ErrorIfNotSingleTarget(); + + my @tgt=GetTgt(); + my $dir=$tgt[0]; + + ExecOrError('${pkgs.emacs}/bin/emacsclient', '-n', $dir); + ''; +} diff --git a/tools/eaglemode/commands/plan9.tga b/tools/eaglemode/commands/plan9.tga new file mode 100644 index 000000000000..55d002221a9b --- /dev/null +++ b/tools/eaglemode/commands/plan9.tga Binary files differdiff --git a/tools/eaglemode/default.nix b/tools/eaglemode/default.nix new file mode 100644 index 000000000000..30983f5d5018 --- /dev/null +++ b/tools/eaglemode/default.nix @@ -0,0 +1,146 @@ +# Helper functions for extending Eagle Mode with useful stuff. +# +# Eagle Mode's customisation usually expects people to copy the entire +# configuration into their user folder, which we can automate fairly easily +# using Nix, letting users choose whether to keep upstream config or not. +{ depot, lib, pkgs, ... }: + +let + mkDesc = d: lib.concatMapStringsSep "\n" + (x: "# Descr =${x}") + (builtins.filter (s: s != "") (lib.splitString "\n" d)); + + configWrapper = pkgs.runCommand "eaglemode-config-wrapper" { } '' + cp ${./wrapper.go} wrapper.go + export HOME=$PWD + ${pkgs.go}/bin/go build wrapper.go + install -Dm755 wrapper $out/bin/wrapper + ''; +in +rec { + # mkCommand creates an Eagle Mode command for the file browser. + # + # Commands are basically little Perl scripts with a command standard library + # available. They receive the user's selected target from Eagle Mode. + mkCommand = lib.makeOverridable ( + { + # Name of the command. + name + , # User-facing description, displayed in Eagle Mode UI. Can be multi-line. + description + , # Verbatim Perl code of the command. Command library is already available. + code + , # Caption for the UI button (defaults to name). + caption ? name + , icon ? "terminal.tga" + , # TODO: what's a good default? + hotkey ? "" + , order ? 1.0 + }: pkgs.writeTextDir "emFileMan/Commands/${name}.pl" ('' + #!${pkgs.perl}/bin/perl + #[[BEGIN PROPERTIES]] + # Type = Command + # Interpreter = perl + # DefaultFor = directory + # Caption = ${caption} + # Order = ${toString order} + # Icon = ${icon} + '' + + (lib.optionalString (description != "") "${mkDesc description}\n") + + (lib.optionalString (hotkey != "") "# Hotkey = ${hotkey}\n") + + '' + #[[END PROPERTIES]] + + use strict; + use warnings; + BEGIN { require "$ENV{'EM_DIR'}/res/emFileMan/scripts/cmd-util.pl"; } + + ${if builtins.isString code + then code + else (if builtins.isPath code + then builtins.readFile code + else throw "code must be a string (literal code) or path to file")} + '') + ); + + # mkTGA converts the given image to a TGA image. + mkTGA = name: path: pkgs.runCommand "${name}.tga" { } '' + ${pkgs.imagemagick}/bin/convert ${path} $out + ''; + + buildPlugin = lib.makeOverridable ( + { name + , src + , version + , eaglemode ? pkgs.eaglemode + , target ? name + , extraNativeBuildInputs ? [ ] + , extraBuildInputs ? [ ] + }: + pkgs.stdenv.mkDerivation { + pname = "eaglemode-plugin-${name}"; + inherit src version; + # inherit (eaglemode.drvAttrs) dontPatchELF; + + nativeBuildInputs = eaglemode.drvAttrs.nativeBuildInputs ++ extraNativeBuildInputs; + buildInputs = eaglemode.drvAttrs.buildInputs ++ extraBuildInputs ++ [ eaglemode ]; + + buildPhase = '' + runHook preBuild + + # merge eaglemode & plugin folders + cp -r ${pkgs.srcOnly eaglemode} merged-src && chmod -R u+rw merged-src + cp -r $src/* merged-src && chmod -R u+rw merged-src + cd merged-src + + export NIX_LDFLAGS="$NIX_LDFLAGS -lXxf86vm -lXext -lXinerama" + perl make.pl build projects=${target} continue=no + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib + cp -r lib/lib${target}.so $out/lib + + if [ -d "$src/etc" ]; then + cp -r $src/etc/* $out + fi + + runHook postInstall + ''; + } + ); + + # etcDir creates a directory layout suitable for use in the EM_USER_CONFIG_DIR + # environment variable. + # + # Note that Eagle Mode requires the value of that variable to be mutable at + # runtime (it is the same place where it persists all of its user-controlled + # state), so the results of this function can not be used directly. + etcDir = + { eaglemode ? pkgs.eaglemode + , extraPaths ? [ ] + }: pkgs.runCommand "eaglemode-config" { } '' + mkdir $out + + ${ + lib.concatMapStringsSep "\n" (s: "cp -rT ${s} $out/\nchmod -R u+rw $out/\n") ([ "${eaglemode}/etc"] ++ extraPaths) + } + ''; + + # withConfig creates an Eagle Mode wrapper that runs it with the given + # configuration. + withConfig = { eaglemode ? pkgs.eaglemode, config }: pkgs.writeShellScriptBin "eaglemode" '' + ${configWrapper}/bin/wrapper --em-config "${config}" + + if [ -d "${config}/lib" ]; then + export LD_LIBRARY_PATH="${config}/lib:$LD_LIBRARY_PATH" + exec ${eaglemode}/bin/eaglemode "$@" + fi + + exec ${eaglemode}/bin/eaglemode "$@" + ''; +} diff --git a/tools/eaglemode/plugins/avif/default.nix b/tools/eaglemode/plugins/avif/default.nix new file mode 100644 index 000000000000..07577c685cc7 --- /dev/null +++ b/tools/eaglemode/plugins/avif/default.nix @@ -0,0 +1,10 @@ +{ depot, pkgs, ... }: + +depot.tools.eaglemode.buildPlugin { + name = "avif"; + version = "canon"; + src = ./.; + target = "PlAvif"; + extraBuildInputs = [ pkgs.libavif ]; + extraNativeBuildInputs = [ pkgs.pkg-config ]; +} diff --git a/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin new file mode 100644 index 000000000000..61615f9fd391 --- /dev/null +++ b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".avif" } +Priority = 1.0 +Library = "PlAvif" +Function = "PlAvifFpPluginFunc" diff --git a/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm new file mode 100644 index 000000000000..00b927805a72 --- /dev/null +++ b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm @@ -0,0 +1,64 @@ +package PlAvif; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingrules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + my @libAvifFlags=(); + if ($options{'avif-inc-dir'} eq '' && $options{'avif-lib-dir'} eq '') { + @libAvifFlags=split("\n",readpipe( + "perl \"".$options{'utils'}."/PkgConfig.pl\" libavif" + )); + } + if (!@libAvifFlags) { + if ($options{'avif-inc-dir'} ne '') { + push(@libAvifFlags, "--inc-search-dir", $options{'avif-inc-dir'}); + } + if ($options{'avif-lib-dir'} ne '') { + push(@libAvifFlags, "--lib-search-dir", $options{'avif-lib-dir'}); + } + push(@libAvifFlags, "--link", "avif"); + } + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + @libAvifFlags, + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlAvif", + "src/PlAvif.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/avif/src/PlAvif.cpp b/tools/eaglemode/plugins/avif/src/PlAvif.cpp new file mode 100644 index 000000000000..e4807bacd49a --- /dev/null +++ b/tools/eaglemode/plugins/avif/src/PlAvif.cpp @@ -0,0 +1,190 @@ +#include <emCore/emFpPlugin.h> +#include <emCore/emImageFile.h> + +#include "avif/avif.h" + +class PlAvifImageFileModel : public emImageFileModel +{ +public: + + static emRef<PlAvifImageFileModel> Acquire( + emContext & context, const emString & name, bool common=true + ); + +protected: + PlAvifImageFileModel(emContext & context, const emString & name); + virtual ~PlAvifImageFileModel(); + virtual void TryStartLoading(); + virtual bool TryContinueLoading(); + virtual void QuitLoading(); + virtual void TryStartSaving(); + virtual bool TryContinueSaving(); + virtual void QuitSaving(); + virtual emUInt64 CalcMemoryNeed(); + virtual double CalcFileProgress(); + +private: + struct LoadingState; + LoadingState * L = NULL; +}; + + +struct PlAvifImageFileModel::LoadingState { + avifRGBImage rgb; + avifDecoder * decoder; +}; + + +emRef<PlAvifImageFileModel> PlAvifImageFileModel::Acquire( + emContext & context, const emString & name, bool common +) +{ + EM_IMPL_ACQUIRE(PlAvifImageFileModel, context, name, common) +} + + +PlAvifImageFileModel::PlAvifImageFileModel( + emContext & context, const emString & name +) + : emImageFileModel(context, name) +{ +} + + +PlAvifImageFileModel::~PlAvifImageFileModel() +{ + PlAvifImageFileModel::QuitLoading(); + PlAvifImageFileModel::QuitSaving(); +} + + +void PlAvifImageFileModel::TryStartLoading() +{ + avifResult result; + + L = new LoadingState; + memset(L, 0, sizeof(LoadingState)); + + L->decoder = avifDecoderCreate(); + if (L->decoder == NULL) { + throw emException("failed to create AVIF decoder"); + } + + result = avifDecoderSetIOFile(L->decoder, GetFilePath()); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + result = avifDecoderParse(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + FileFormatInfo = emString::Format( + "AVIF %s %ubpc", + avifPixelFormatToString(L->decoder->image->yuvFormat), + L->decoder->image->depth + ); + + + Signal(ChangeSignal); +} + + +bool PlAvifImageFileModel::TryContinueLoading() +{ + avifResult result; + + if (!Image.GetHeight()) { + Image.Setup( + L->decoder->image->width, + L->decoder->image->height, + L->decoder->alphaPresent ? 4 : 3 + ); + } + + result = avifDecoderNextImage(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + avifRGBImageSetDefaults(&L->rgb, L->decoder->image); + L->rgb.format = L->decoder->alphaPresent ? + AVIF_RGB_FORMAT_RGBA : AVIF_RGB_FORMAT_RGB; + L->rgb.pixels = Image.GetWritableMap(); + L->rgb.width = Image.GetWidth(); + L->rgb.height = Image.GetHeight(); + L->rgb.depth = 8; + L->rgb.rowBytes = Image.GetWidth() * Image.GetChannelCount(); + + result = avifImageYUVToRGB(L->decoder->image, &L->rgb); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + Signal(ChangeSignal); + return true; +} + + +void PlAvifImageFileModel::QuitLoading() +{ + if (L) { + if (L->decoder) avifDecoderDestroy(L->decoder); + delete L; + L = NULL; + } +} + + +void PlAvifImageFileModel::TryStartSaving() +{ + throw emException("PlAvifImageFileModel: Saving not implemented."); +} + + +bool PlAvifImageFileModel::TryContinueSaving() +{ + return false; +} + + +void PlAvifImageFileModel::QuitSaving() +{ +} + + +emUInt64 PlAvifImageFileModel::CalcMemoryNeed() +{ + return + (emUInt64) + L->decoder->image->width * + L->decoder->image->height * + (L->decoder->alphaPresent ? 4 : 3); +} + + +double PlAvifImageFileModel::CalcFileProgress() +{ + return 0.0; +} + +extern "C" { + emPanel * PlAvifFpPluginFunc( + emPanel::ParentArg parent, const emString & name, + const emString & path, emFpPlugin * plugin, + emString * errorBuf + ) + { + if (plugin->Properties.GetCount()) { + *errorBuf="PlAvifFpPlugin: No properties allowed."; + return NULL; + } + return new emImageFilePanel( + parent, name, + PlAvifImageFileModel::Acquire( + parent.GetRootContext(), path + ) + ); + } +} diff --git a/tools/eaglemode/plugins/example.nix b/tools/eaglemode/plugins/example.nix new file mode 100644 index 000000000000..b361971cc57e --- /dev/null +++ b/tools/eaglemode/plugins/example.nix @@ -0,0 +1,17 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = with pkgs; srcOnly eaglemode; +in +em.buildPlugin { + name = "example"; + version = "canon"; + + src = pkgs.runCommand "em-plugin-example-src" { } '' + set -ux + cp -r ${emSrc}/doc/examples/CppApiExamples/PluginExample $out + ''; + + target = "PlEx"; +} diff --git a/tools/eaglemode/plugins/qoi/default.nix b/tools/eaglemode/plugins/qoi/default.nix new file mode 100644 index 000000000000..8764ac39e88d --- /dev/null +++ b/tools/eaglemode/plugins/qoi/default.nix @@ -0,0 +1,12 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = pkgs.srcOnly pkgs.em; +in +em.buildPlugin { + name = "qoi"; + version = "canon"; + src = ./.; + target = "PlQoi"; +} diff --git a/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin b/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin new file mode 100644 index 000000000000..e27f37261d77 --- /dev/null +++ b/tools/eaglemode/plugins/qoi/etc/emCore/FpPlugins/PlQoi.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".qoi" } +Priority = 1.0 +Library = "PlQoi" +Function = "PlQoiFpPluginFunc" diff --git a/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm b/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm new file mode 100644 index 000000000000..c68b9bc6324b --- /dev/null +++ b/tools/eaglemode/plugins/qoi/makers/PlQoi.maker.pm @@ -0,0 +1,47 @@ +package PlQoi; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingrules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlQoi", + "src/PlQoi.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/qoi/src/PlQoi.cpp b/tools/eaglemode/plugins/qoi/src/PlQoi.cpp new file mode 100644 index 000000000000..1455712eff3a --- /dev/null +++ b/tools/eaglemode/plugins/qoi/src/PlQoi.cpp @@ -0,0 +1,273 @@ +#include <emCore/emFpPlugin.h> +#include <emCore/emImageFile.h> + +/* +QOI Utilities + +Copyright (c) 2021, Dominic Szablewski - https://phoboslab.org +SPDX-License-Identifier: MIT +*/ + +#define QOI_OP_INDEX 0x00 /* 00xxxxxx */ +#define QOI_OP_DIFF 0x40 /* 01xxxxxx */ +#define QOI_OP_LUMA 0x80 /* 10xxxxxx */ +#define QOI_OP_RUN 0xc0 /* 11xxxxxx */ +#define QOI_OP_RGB 0xfe /* 11111110 */ +#define QOI_OP_RGBA 0xff /* 11111111 */ + +#define QOI_MASK_2 0xc0 /* 11000000 */ + +#define QOI_COLOR_HASH(C) (C.GetRed()*3 + C.GetGreen()*5 + C.GetBlue()*7 + C.GetAlpha()*11) + +#define QOI_MAGIC \ + (((unsigned int)'q') << 24 | ((unsigned int)'o') << 16 | \ + ((unsigned int)'i') << 8 | ((unsigned int)'f')) + +#define QOI_HEADER_SIZE 14 + +static unsigned int qoi_read_32(const unsigned char *bytes, int *p) { + unsigned int a = bytes[(*p)++]; + unsigned int b = bytes[(*p)++]; + unsigned int c = bytes[(*p)++]; + unsigned int d = bytes[(*p)++]; + return a << 24 | b << 16 | c << 8 | d; +} + + +class PlQoiImageFileModel : public emImageFileModel +{ +public: + + static emRef<PlQoiImageFileModel> Acquire( + emContext & context, const emString & name, bool common=true + ); + +protected: + PlQoiImageFileModel(emContext & context, const emString & name); + virtual ~PlQoiImageFileModel(); + virtual void TryStartLoading(); + virtual bool TryContinueLoading(); + virtual void QuitLoading(); + virtual void TryStartSaving(); + virtual bool TryContinueSaving(); + virtual void QuitSaving(); + virtual emUInt64 CalcMemoryNeed(); + virtual double CalcFileProgress(); + +private: + struct LoadingState; + LoadingState * L = NULL; +}; + + +struct PlQoiImageFileModel::LoadingState { + FILE * file; + unsigned int width, height, channels; + size_t file_len; +}; + + +emRef<PlQoiImageFileModel> PlQoiImageFileModel::Acquire( + emContext & context, const emString & name, bool common +) +{ + EM_IMPL_ACQUIRE(PlQoiImageFileModel, context, name, common) +} + + +PlQoiImageFileModel::PlQoiImageFileModel( + emContext & context, const emString & name +) + : emImageFileModel(context, name) +{ +} + + +PlQoiImageFileModel::~PlQoiImageFileModel() +{ + PlQoiImageFileModel::QuitLoading(); + PlQoiImageFileModel::QuitSaving(); +} + + +void PlQoiImageFileModel::TryStartLoading() +{ + unsigned char header[QOI_HEADER_SIZE]; + unsigned int header_magic, colorspace; + int pos = 0; + + L = new LoadingState; + memset(L, 0, sizeof(LoadingState)); + L->file = fopen(GetFilePath(),"rb"); + if (!L->file) throw emException("%s",emGetErrorText(errno).Get()); + + if (fread(header, 1, sizeof(header), L->file) != sizeof(header)) { + if (ferror(L->file)) { + throw emException("%s",emGetErrorText(errno).Get()); + } + else { + throw emException("QOI header not found"); + } + } + + header_magic = qoi_read_32(header, &pos); + L->width = qoi_read_32(header, &pos); + L->height = qoi_read_32(header, &pos); + L->channels = header[pos++]; + colorspace = header[pos++]; + + if ( + L->width == 0 || L->height == 0 || + L->channels < 3 || L->channels > 4 || + colorspace > 1 || + header_magic != QOI_MAGIC + ) { + throw emException("QOI header not valid"); + } + + fseek(L->file, 0, SEEK_END); + L->file_len = ftell(L->file); + + if (L->file_len <= QOI_HEADER_SIZE || fseek(L->file, 0, SEEK_SET) != 0) { + throw emException("QOI data incomplete"); + } + + FileFormatInfo = "QOI "; + FileFormatInfo += ( + colorspace ? "all channels linear" : "sRGB with linear alpha" + ); + + Signal(ChangeSignal); +} + + +bool PlQoiImageFileModel::TryContinueLoading() +{ + emArray<unsigned char> data; + emColor index[64]; + emColor px { 0, 0, 0, 255 }; + int pos = QOI_HEADER_SIZE; + int run = 0; + + if (!Image.GetHeight()) { + Image.Setup(L->width, L->height, L->channels); + } + + data.SetCount(L->file_len); + if (fread(data.GetWritable(), 1, L->file_len, L->file) < L->file_len) { + if (ferror(L->file)) { + throw emException("%s",emGetErrorText(errno).Get()); + } + else { + throw emException("QOI data incomplete"); + } + } + + memset(index, 0, sizeof(index)); + + for (int px_y = 0; px_y < L->height; px_y++) { + for (int px_x = 0; px_x < L->width; px_x++) { + if (run > 0) { + run--; + } else if (pos < data.GetCount()) { + int b1 = data.Get(pos++); + + if (b1 == QOI_OP_RGB) { + px.SetRed( data.Get(pos++)); + px.SetGreen( data.Get(pos++)); + px.SetBlue( data.Get(pos++)); + } else if (b1 == QOI_OP_RGBA) { + px.SetRed( data.Get(pos++)); + px.SetGreen( data.Get(pos++)); + px.SetBlue( data.Get(pos++)); + px.SetAlpha( data.Get(pos++)); + } else if ((b1 & QOI_MASK_2) == QOI_OP_INDEX) { + px = index[b1]; + } else if ((b1 & QOI_MASK_2) == QOI_OP_DIFF) { + px.SetRed( + px.GetRed() + ((b1 >> 4) & 0x03) - 2); + px.SetGreen( + px.GetGreen() + ((b1 >> 2) & 0x03) - 2); + px.SetBlue( + px.GetBlue() + ( b1 & 0x03) - 2); + } else if ((b1 & QOI_MASK_2) == QOI_OP_LUMA) { + int b2 = data.Get(pos++); + int vg = (b1 & 0x3f) - 32; + px.SetRed( + px.GetRed() + vg - 8 + ((b2 >> 4) & 0x0f)); + px.SetGreen( + px.GetGreen() + vg); + px.SetBlue( + px.GetBlue() + vg - 8 + (b2 & 0x0f)); + } else if ((b1 & QOI_MASK_2) == QOI_OP_RUN) { + run = (b1 & 0x3f); + } + index[QOI_COLOR_HASH(px) % 64] = px; + } + Image.SetPixel(px_x, px_y, px); + } + } + + Signal(ChangeSignal); + return true; +} + + +void PlQoiImageFileModel::QuitLoading() +{ + if (L) { + if (L->file) fclose(L->file); + delete L; + L = NULL; + } +} + + +void PlQoiImageFileModel::TryStartSaving() +{ + throw emException("PlQoiImageFileModel: Saving not implemented."); +} + + +bool PlQoiImageFileModel::TryContinueSaving() +{ + return false; +} + + +void PlQoiImageFileModel::QuitSaving() +{ +} + + +emUInt64 PlQoiImageFileModel::CalcMemoryNeed() +{ + return + (emUInt64)L->width * L->height * L->channels + L->file_len; +} + + +double PlQoiImageFileModel::CalcFileProgress() +{ + return 0.0; +} + +extern "C" { + emPanel * PlQoiFpPluginFunc( + emPanel::ParentArg parent, const emString & name, + const emString & path, emFpPlugin * plugin, + emString * errorBuf + ) + { + if (plugin->Properties.GetCount()) { + *errorBuf="PlQoiFpPlugin: No properties allowed."; + return NULL; + } + return new emImageFilePanel( + parent, name, + PlQoiImageFileModel::Acquire( + parent.GetRootContext(), path + ) + ); + } +} diff --git a/tools/eaglemode/plugins/yatracker/default.nix b/tools/eaglemode/plugins/yatracker/default.nix new file mode 100644 index 000000000000..3ffc42029a03 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/default.nix @@ -0,0 +1,18 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = with pkgs; srcOnly eaglemode; +in +(em.buildPlugin { + name = "yatracker"; + version = "canon"; + src = ./.; + target = "PlYaTracker"; +}).overrideAttrs (_: { + postInstall = '' + mkdir -p $out/icons + ${pkgs.imagemagick}/bin/convert $src/logo.webp $out/icons/yandex-tracker.tga + ''; +}) + diff --git a/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin b/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin new file mode 100644 index 000000000000..637878844709 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/etc/emCore/FpPlugins/PlYaTracker.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".YaTracker" } +Priority = 1.0 +Library = "PlYaTracker" +Function = "PlYaTrackerPluginFunc" diff --git a/tools/eaglemode/plugins/yatracker/logo.webp b/tools/eaglemode/plugins/yatracker/logo.webp new file mode 100644 index 000000000000..460d57d72c33 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/logo.webp Binary files differdiff --git a/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm b/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm new file mode 100644 index 000000000000..ae954260a2d1 --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/makers/PlYaTracker.maker.pm @@ -0,0 +1,47 @@ +package PlYaTracker; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingRules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlYaTracker", + "src/PlYaTracker/PlYaTracker.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp b/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp new file mode 100644 index 000000000000..9bf05a17179f --- /dev/null +++ b/tools/eaglemode/plugins/yatracker/src/PlYaTracker/PlYaTracker.cpp @@ -0,0 +1,58 @@ +#include <emCore/emFilePanel.h> +#include <emCore/emFpPlugin.h> +#include <emCore/emRecFileModel.h> +#include <emCore/emToolkit.h> + +class PlYaTrackerConfig final : public emRecFileModel, public emStructRec { + public: + static emRef<PlYaTrackerConfig> Acquire(emContext& context, + const emString& name, + bool common = true); + + virtual const char* GetFormatName() const; + + emStringRec URL; + emStringRec Token; + + protected: + PlYaTrackerConfig(emContext& context, const emString& name); +}; + +emRef<PlYaTrackerConfig> PlYaTrackerConfig::Acquire(emContext& context, + const emString& name, + bool common) { + EM_IMPL_ACQUIRE(PlYaTrackerConfig, context, name, common) +} + +const char* PlYaTrackerConfig::GetFormatName() const { return "PlYaTracker"; } + +PlYaTrackerConfig::PlYaTrackerConfig(emContext& context, const emString& name) + : emRecFileModel(context, name), + emStructRec(), + URL(this, "URL"), + Token(this, "Token") { + PostConstruct(*this); +} + +class PlYaTrackerFilePanel : public emFilePanel { + public: + PlYaTrackerFilePanel(ParentArg parent, const emString& name, + emRef<PlYaTrackerConfig> config); + + private: + emRef<PlYaTrackerConfig> Config; +}; + +PlYaTrackerFilePanel::PlYaTrackerFilePanel(ParentArg parent, + const emString& name, + emRef<PlYaTrackerConfig> config) + : emFilePanel(parent, name, config), Config(config) {} + +extern "C" { +emPanel* PlYaTrackerPluginFunc(emPanel::ParentArg parent, const emString& name, + const emString& path, emFpPlugin* plugin, + emString* errorBuf) { + return new PlYaTrackerFilePanel( + parent, name, PlYaTrackerConfig::Acquire(parent.GetRootContext(), path)); +} +} diff --git a/tools/eaglemode/wrapper.go b/tools/eaglemode/wrapper.go new file mode 100644 index 000000000000..841642b6d93f --- /dev/null +++ b/tools/eaglemode/wrapper.go @@ -0,0 +1,156 @@ +// Eagle Mode configuration wrapper that recreates the required directory +// structure for Eagle Mode based on the output of depot.tools.eaglemode.etcDir +// +// This will replace *all* symlinks in the Eagle Mode configuration directory, +// but it will not touch actual files. Missing folders will be created. +package main + +import ( + "flag" + "fmt" + "io/fs" + "log" + "os" + "os/user" + "path" + "path/filepath" + "strings" +) + +func configDir() (string, error) { + v := os.Getenv("EM_USER_CONFIG_DIR") + if v != "" { + return v, nil + } + + usr, err := user.Current() + if err != nil { + return "", fmt.Errorf("failed to get current user: %w", err) + } + + return path.Join(usr.HomeDir, ".eaglemode"), nil +} + +// cleanupConfig removes *all* existing symlinks in the configuration which do +// not point into the right Nix store path. +func cleanupConfig(conf string, dir string) (map[string]bool, error) { + // In case of first launch, we might have to create the directory. + _ = os.MkdirAll(dir, 0755) + c := 0 + + currentFiles := map[string]bool{} + + walker := func(p string, d fs.DirEntry, e error) error { + if e != nil { + return fmt.Errorf("could not walk %s in config directory: %w", p, e) + } + + if d.Type()&fs.ModeSymlink != 0 { + target, err := os.Readlink(p) + if err != nil { + return fmt.Errorf("could not read link for %s: %w", p, err) + } + + if !strings.HasPrefix(target, conf) { + err = os.Remove(p) + c++ + if err != nil { + return fmt.Errorf("could not remove stale link %q: %w", p, err) + } + log.Printf("removed stale symlink %q", p) + } else { + currentFiles[p] = false + } + } + + if d.Type().IsRegular() { + currentFiles[p] = true + } + + return nil + } + + err := filepath.WalkDir(dir, walker) + if err != nil { + return nil, err + } + + if c > 0 { + log.Printf("removed %v stale symlinks", c) + } + + return currentFiles, nil +} + +// linkConfig traverses the given Eagle Mode configuration and links everything +// to the expected location in the user's configuration directory. +// +// If the user placed actual files in the configuration directory at paths that +// would be overwritten, they will not be touched. +func linkConfig(conf string, dir string, existing map[string]bool) error { + walker := func(p string, d fs.DirEntry, e error) error { + if e != nil { + return fmt.Errorf("could not walk %s in config directory: %w", p, e) + } + + target := path.Join(dir, strings.TrimPrefix(p, conf)) + + if d.Type().IsDir() { + err := os.MkdirAll(target, 0755) + if err != nil { + return fmt.Errorf("could not create directory %q: %w", target, err) + } + + return nil + } + + if shadow, exists := existing[target]; exists { + if shadow { + log.Printf("WARN: file %q already exists and shadows a file from configuration", target) + } + + return nil + } + + err := os.Symlink(p, target) + if err != nil { + return fmt.Errorf("failed to link %q: %w", target, err) + } + + return nil + } + + return filepath.WalkDir(conf, walker) +} + +func main() { + emConfig := flag.String("em-config", "", "path to em-config dir") + + flag.Parse() + log.Println("verifying current Eagle Mode configuration") + + if *emConfig == "" { + log.Fatalf("Eagle Mode configuration must be given") + } + + if !strings.HasPrefix(*emConfig, "/nix/store/") { + log.Fatalf("Eagle Mode configuration must be in Nix store") + } + + dir, err := configDir() + if err != nil { + log.Fatalf("could not determine Eagle Mode config dir: %v", err) + } + + currentFiles, err := cleanupConfig(*emConfig, dir) + if err != nil { + log.Fatalf("failed to remove stale symlinks: %v", err) + } + + err = linkConfig(*emConfig, dir, currentFiles) + if err != nil { + log.Fatalf("failed to link new configuration: %v", err) + } + + log.Println("Eagle Mode configuration updated") +} diff --git a/tvix/Cargo.lock b/tvix/Cargo.lock index 9bea027e4de3..7f92e885c3d1 100644 --- a/tvix/Cargo.lock +++ b/tvix/Cargo.lock @@ -67,47 +67,48 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.11" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -115,9 +116,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arc-swap" @@ -152,9 +153,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9eabd7a98fe442131a17c316bd9349c43695e49e730c3c8e12cfb5f4da2693" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "bzip2", "flate2", @@ -208,20 +209,22 @@ dependencies = [ [[package]] name = "async-process" -version = "2.1.0" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451e3cf68011bd56771c79db04a9e333095ab6349f7e47592b788e9b98720cc8" +checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" dependencies = [ "async-channel", "async-io", "async-lock 3.3.0", "async-signal", + "async-task", "blocking", "cfg-if", "event-listener 5.2.0", "futures-lite", "rustix", - "windows-sys 0.52.0", + "tracing", + "windows-sys 0.59.0", ] [[package]] @@ -261,7 +264,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -288,7 +291,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -305,46 +308,18 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" -dependencies = [ - "async-trait", - "axum-core 0.3.4", - "bitflags 1.3.2", - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", - "itoa", - "matchit 0.7.3", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper 0.1.2", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", - "axum-core 0.4.3", + "axum-core", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "itoa", "matchit 0.7.3", @@ -367,23 +342,6 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 0.2.11", - "http-body 0.4.6", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" @@ -391,8 +349,8 @@ dependencies = [ "async-trait", "bytes", "futures-util", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "mime", "pin-project-lite", @@ -439,43 +397,27 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bigtable_rs" version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ccba0acd0a82afb2b1fe89181b0776ff18aef5e355030631fe534c8ae8ec73" +source = "git+https://github.com/liufuyang/bigtable_rs?rev=1818355a5373a5bc2c84287e3a4e3807154ac8ef#1818355a5373a5bc2c84287e3a4e3807154ac8ef" dependencies = [ "gcp_auth", - "http 0.2.11", + "http", + "hyper-util", "log", - "prost 0.12.3", - "prost-build 0.12.3", - "prost-types 0.12.3", + "prost", + "prost-build", + "prost-types", "prost-wkt", - "prost-wkt-build", "prost-wkt-types", "serde", "serde_with", "thiserror", "tokio", - "tonic 0.11.0", - "tonic-build 0.11.0", + "tonic", + "tonic-build", "tower", ] [[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -483,21 +425,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "bitmaps" -version = "3.2.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "blake3" -version = "1.5.0" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" +checksum = "d82033247fd8e890df8f740e407ad4d038debb9eb1f40533fffb32e7d17dc6f7" dependencies = [ "arrayref", "arrayvec", @@ -505,7 +441,7 @@ dependencies = [ "cfg-if", "constant_time_eq", "digest", - "rayon", + "rayon-core", ] [[package]] @@ -535,12 +471,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.7", "serde", ] @@ -558,9 +494,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "bzip2" @@ -601,12 +537,13 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -627,7 +564,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -659,9 +596,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.18" +version = "4.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" dependencies = [ "clap_builder", "clap_derive", @@ -669,33 +606,33 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.18" +version = "4.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -726,9 +663,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "concurrent-queue" @@ -915,7 +852,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -938,8 +875,8 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", - "syn 2.0.48", + "strsim 0.10.0", + "syn 2.0.76", ] [[package]] @@ -950,7 +887,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -1070,9 +1007,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -1108,7 +1045,7 @@ checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" dependencies = [ "num-traits", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -1305,7 +1242,7 @@ dependencies = [ "lazy_static", "libc", "log", - "mio", + "mio 0.8.11", "nix 0.24.3", "vhost", "virtio-queue", @@ -1382,7 +1319,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -1432,19 +1369,22 @@ dependencies = [ [[package]] name = "gcp_auth" -version = "0.10.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2c71ea685b88a1aa50e9fb66fe0e1cb29d755f58cca41fb8c91ef604d4f4d4" +checksum = "536c79e79dde296a800738474691e97031769bed9b54e6dd0401b169d35d693d" dependencies = [ "async-trait", - "base64 0.21.7", + "base64 0.22.1", + "bytes", "chrono", "home", - "hyper 0.14.28", - "hyper-rustls 0.24.2", + "http", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", "ring", - "rustls 0.21.12", - "rustls-pemfile 1.0.4", + "rustls-pemfile", "serde", "serde_json", "thiserror", @@ -1452,7 +1392,6 @@ dependencies = [ "tracing", "tracing-futures", "url", - "which 5.0.0", ] [[package]] @@ -1521,25 +1460,6 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.11", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "h2" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" @@ -1549,7 +1469,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 1.1.0", + "http", "indexmap 2.1.0", "slab", "tokio", @@ -1586,10 +1506,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[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.3.4" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1614,17 +1540,6 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" @@ -1636,23 +1551,12 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.11", - "pin-project-lite", -] - -[[package]] -name = "http-body" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.1.0", + "http", ] [[package]] @@ -1663,8 +1567,8 @@ checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", "futures-core", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "pin-project-lite", ] @@ -1688,30 +1592,6 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.11", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" @@ -1719,9 +1599,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.4", - "http 1.1.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa", @@ -1733,56 +1613,29 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.11", - "hyper 0.14.28", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "tokio", - "tokio-rustls 0.24.1", -] - -[[package]] -name = "hyper-rustls" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", - "http 1.1.0", - "hyper 1.4.1", + "http", + "hyper", "hyper-util", - "rustls 0.23.7", - "rustls-native-certs 0.7.0", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tower-service", ] [[package]] name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper 0.14.28", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - -[[package]] -name = "hyper-timeout" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" dependencies = [ - "hyper 1.4.1", + "hyper", "hyper-util", "pin-project-lite", "tokio", @@ -1791,16 +1644,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.1.0", - "http-body 1.0.0", - "hyper 1.4.1", + "http", + "http-body", + "hyper", "pin-project-lite", "socket2", "tokio", @@ -1849,30 +1702,6 @@ dependencies = [ ] [[package]] -name = "imbl" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be8d8cd36f33a46b1849f31f837c44d9fa87223baee3b4bd96b8f11df81eb" -dependencies = [ - "bitmaps", - "imbl-sized-chunks", - "proptest", - "rand_core", - "rand_xoshiro", - "serde", - "version_check", -] - -[[package]] -name = "imbl-sized-chunks" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" -dependencies = [ - "bitmaps", -] - -[[package]] name = "indexmap" version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1941,6 +1770,12 @@ dependencies = [ ] [[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] name = "itertools" version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1951,18 +1786,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -1975,9 +1810,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -1993,9 +1828,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lexical-core" @@ -2063,9 +1898,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.152" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -2089,16 +1924,16 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litrs" @@ -2137,9 +1972,9 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown 0.14.3", ] @@ -2161,7 +1996,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a200ae03df8c3dce7a963f6eeaac8feb41bf9001cb7e5ab22e3205aec2f0373d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", "magic-sys", "thiserror", @@ -2275,6 +2110,18 @@ dependencies = [ ] [[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] name = "multimap" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2284,27 +2131,27 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" name = "nar-bridge" version = "0.1.0" dependencies = [ - "axum 0.7.5", + "axum", "bytes", "clap", "data-encoding", "futures", "hex-literal", - "itertools 0.12.0", + "itertools 0.12.1", "lru", "mimalloc", "nix-compat", "parking_lot 0.12.3", - "prost 0.13.1", - "prost-build 0.13.1", + "prost", + "prost-build", "rstest", "serde", "thiserror", "tokio", "tokio-listener", "tokio-util", - "tonic 0.12.1", - "tonic-build 0.12.1", + "tonic", + "tonic-build", "tower", "tower-http", "tracing", @@ -2365,7 +2212,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "cfg-if", "libc", ] @@ -2374,8 +2221,9 @@ dependencies = [ name = "nix-compat" version = "0.1.0" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bstr", + "bytes", "criterion", "data-encoding", "ed25519", @@ -2386,6 +2234,7 @@ dependencies = [ "hex-literal", "lazy_static", "mimalloc", + "nix-compat-derive", "nom", "num-traits", "pin-project-lite", @@ -2394,13 +2243,50 @@ dependencies = [ "serde", "serde_json", "sha2", + "smol_str", "thiserror", "tokio", "tokio-test", + "tracing", "zstd", ] [[package]] +name = "nix-compat-derive" +version = "0.1.0" +dependencies = [ + "hex-literal", + "nix-compat", + "pretty_assertions", + "proc-macro2", + "quote", + "rstest", + "syn 2.0.76", + "tokio", + "tokio-test", +] + +[[package]] +name = "nix-compat-derive-tests" +version = "0.1.0" +dependencies = [ + "hex-literal", + "nix-compat", + "nix-compat-derive", + "pretty_assertions", + "rstest", + "tokio", + "tokio-test", + "trybuild", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2437,9 +2323,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2472,9 +2358,9 @@ dependencies = [ [[package]] name = "object_store" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbebfd32c213ba1907fa7a9c9138015a8de2b43e30c5aa45b18f7deb46786ad6" +checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3" dependencies = [ "async-trait", "base64 0.22.1", @@ -2482,8 +2368,8 @@ dependencies = [ "chrono", "futures", "humantime", - "hyper 1.4.1", - "itertools 0.12.0", + "hyper", + "itertools 0.13.0", "md-5", "parking_lot 0.12.3", "percent-encoding", @@ -2491,7 +2377,7 @@ dependencies = [ "rand", "reqwest", "ring", - "rustls-pemfile 2.1.0", + "rustls-pemfile", "serde", "serde_json", "snafu", @@ -2556,7 +2442,7 @@ checksum = "ad31e9de44ee3538fb9d64fe3376c1362f406162434609e79aea2a41a0af78ab" dependencies = [ "async-trait", "bytes", - "http 1.1.0", + "http", "opentelemetry 0.24.0", ] @@ -2568,14 +2454,14 @@ checksum = "6b925a602ffb916fb7421276b86756027b37ee708f9dce2dbdcc51739f07e727" dependencies = [ "async-trait", "futures-core", - "http 1.1.0", + "http", "opentelemetry 0.24.0", "opentelemetry-proto", "opentelemetry_sdk 0.24.1", - "prost 0.13.1", + "prost", "thiserror", "tokio", - "tonic 0.12.1", + "tonic", ] [[package]] @@ -2586,8 +2472,8 @@ checksum = "30ee9f20bff9c984511a02f082dc8ede839e4a9bf15cc2487c8d6fea5ad850d9" dependencies = [ "opentelemetry 0.24.0", "opentelemetry_sdk 0.24.1", - "prost 0.13.1", - "tonic 0.12.1", + "prost", + "tonic", ] [[package]] @@ -2723,9 +2609,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.1.0", @@ -2748,14 +2634,14 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2873,80 +2759,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] name = "proc-macro2" -version = "1.0.76" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.2", + "bitflags 2.6.0", "lazy_static", "num-traits", "rand", "rand_chacha", "rand_xorshift", "regex-syntax 0.8.2", - "rusty-fork", "tempfile", "unarray", ] [[package]] name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive 0.12.3", -] - -[[package]] -name = "prost" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" dependencies = [ "bytes", - "prost-derive 0.13.1", -] - -[[package]] -name = "prost-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" -dependencies = [ - "bytes", - "heck", - "itertools 0.11.0", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost 0.12.3", - "prost-types 0.12.3", - "pulldown-cmark", - "pulldown-cmark-to-cmark", - "regex", - "syn 2.0.48", - "tempfile", - "which 4.4.2", + "prost-derive", ] [[package]] @@ -2956,53 +2805,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bb182580f71dd070f88d01ce3de9f4da5021db7115d2e1c3605a754153b77c1" dependencies = [ "bytes", - "heck", - "itertools 0.12.0", + "heck 0.4.1", + "itertools 0.10.5", "log", "multimap", "once_cell", "petgraph", "prettyplease", - "prost 0.13.1", - "prost-types 0.13.1", + "prost", + "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", "regex", - "syn 2.0.48", + "syn 2.0.76", "tempfile", ] [[package]] name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "prost-derive" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" dependencies = [ "anyhow", - "itertools 0.12.0", + "itertools 0.10.5", "proc-macro2", "quote", - "syn 2.0.48", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost 0.12.3", + "syn 2.0.76", ] [[package]] @@ -3011,18 +2840,18 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" dependencies = [ - "prost 0.13.1", + "prost", ] [[package]] name = "prost-wkt" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d8ef9c3f0f1dab910d2b7e2c24a8e4322e122eba6d7a1921eeebcebbc046c40" +checksum = "a8d84e2bee181b04c2bac339f2bfe818c46a99750488cc6728ce4181d5aa8299" dependencies = [ "chrono", "inventory", - "prost 0.12.3", + "prost", "serde", "serde_derive", "serde_json", @@ -3031,27 +2860,27 @@ dependencies = [ [[package]] name = "prost-wkt-build" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b31cae9a54ca84fee1504740a82eebf2479532905e106f63ca0c3bc8d780321" +checksum = "8a669d5acbe719010c6f62a64e6d7d88fdedc1fe46e419747949ecb6312e9b14" dependencies = [ - "heck", - "prost 0.12.3", - "prost-build 0.12.3", - "prost-types 0.12.3", + "heck 0.4.1", + "prost", + "prost-build", + "prost-types", "quote", ] [[package]] name = "prost-wkt-types" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435be4a8704091b4c5fb1d79799de7f2dbff53af05edf29385237f8cf7ab37ee" +checksum = "01ef068e9b82e654614b22e6b13699bd545b6c0e2e721736008b00b38aeb4f64" dependencies = [ "chrono", - "prost 0.12.3", - "prost-build 0.12.3", - "prost-types 0.12.3", + "prost", + "prost-build", + "prost-types", "prost-wkt", "prost-wkt-build", "regex", @@ -3066,7 +2895,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "memchr", "unicase", ] @@ -3081,16 +2910,10 @@ dependencies = [ ] [[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] name = "quick-xml" -version = "0.31.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" dependencies = [ "memchr", "serde", @@ -3107,7 +2930,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 1.1.0", - "rustls 0.23.7", + "rustls", "thiserror", "tokio", "tracing", @@ -3123,7 +2946,7 @@ dependencies = [ "rand", "ring", "rustc-hash 1.1.0", - "rustls 0.23.7", + "rustls", "slab", "thiserror", "tinyvec", @@ -3145,9 +2968,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.35" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3202,15 +3025,6 @@ dependencies = [ ] [[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] name = "rayon" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3232,9 +3046,9 @@ dependencies = [ [[package]] name = "redb" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0" +checksum = "58323dc32ea52a8ae105ff94bc0460c5d906307533ba3401aa63db3cbe491fe5" dependencies = [ "libc", ] @@ -3279,13 +3093,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.7", "regex-syntax 0.8.2", ] @@ -3300,9 +3114,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -3329,20 +3143,20 @@ checksum = "e898588f33fdd5b9420719948f9f2a32c922a246964576f71ba7f24f80610fbc" [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", "futures-core", "futures-util", - "h2 0.4.4", - "http 1.1.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", - "hyper-rustls 0.27.2", + "hyper", + "hyper-rustls", "hyper-util", "ipnet", "js-sys", @@ -3352,16 +3166,16 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.7", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.0", + "rustls", + "rustls-native-certs", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tokio-util", "tower-service", "url", @@ -3369,18 +3183,18 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg", + "windows-registry", ] [[package]] name = "reqwest-middleware" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39346a33ddfe6be00cbc17a34ce996818b97b230b87229f10114693becca1268" +checksum = "562ceb5a604d3f7c885a792d42c199fd8af239d0a51b2fa6a78aafa092452b04" dependencies = [ "anyhow", "async-trait", - "http 1.1.0", + "http", "reqwest", "serde", "thiserror", @@ -3389,14 +3203,14 @@ dependencies = [ [[package]] name = "reqwest-tracing" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e45dcad05dc210fdb0278d62a679eb768730af808f8cb552f810da89bdbe76d" +checksum = "bfdd9bfa64c72233d8dd99ab7883efcdefe9e16d46488ecb9228b71a2e2ceb45" dependencies = [ "anyhow", "async-trait", "getrandom", - "http 1.1.0", + "http", "matchit 0.8.4", "opentelemetry 0.22.0", "reqwest", @@ -3466,7 +3280,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.48", + "syn 2.0.76", "unicode-ident", ] @@ -3479,7 +3293,7 @@ dependencies = [ "quote", "rand", "rustc_version", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -3511,11 +3325,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.30" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -3524,32 +3338,6 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.2", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" version = "0.23.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" @@ -3558,31 +3346,19 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki", "subtle", "zeroize", ] [[package]] name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-native-certs" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.1.0", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", @@ -3590,15 +3366,6 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-pemfile" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b" @@ -3615,16 +3382,6 @@ checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" [[package]] name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustls-webpki" version = "0.102.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" @@ -3641,18 +3398,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] name = "rustyline" version = "10.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3712,16 +3457,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] name = "security-framework" version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3752,22 +3487,22 @@ checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -3804,9 +3539,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -3835,11 +3570,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -3853,14 +3588,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -3895,6 +3630,12 @@ dependencies = [ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "signal-hook-registry" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3945,9 +3686,9 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smol_str" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -3968,7 +3709,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "syn 1.0.109", @@ -4019,6 +3760,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] name = "structmeta" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4060,9 +3807,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.48" +version = "2.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525" dependencies = [ "proc-macro2", "quote", @@ -4080,6 +3827,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "tabwriter" @@ -4092,15 +3842,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4132,22 +3882,22 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -4171,9 +3921,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -4192,9 +3942,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -4227,30 +3977,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", + "windows-sys 0.52.0", ] [[package]] @@ -4259,19 +3998,19 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "914a439d123292125bc806649c396d23e1aac5da4052f0d97b23137b38782f46" dependencies = [ - "axum 0.7.5", + "axum", "clap", "document-features", "futures-core", "futures-util", - "hyper 1.4.1", + "hyper", "hyper-util", "nix 0.26.4", "pin-project", "socket2", "tokio", "tokio-util", - "tonic 0.12.1", + "tonic", "tower", "tower-service", "tracing", @@ -4279,13 +4018,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -4301,41 +4040,20 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.7", + "rustls", "rustls-pki-types", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -4359,9 +4077,9 @@ dependencies = [ [[package]] name = "tokio-test" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b3cbabd3ae862100094ae433e1def582cf86451b4e9bf83aa7ac1d8a7d719" +checksum = "2468baabc3311435b55dd935f702f42cd1b8abb7e754fb7dfb16bd36aa88f9f7" dependencies = [ "async-stream", "bytes", @@ -4372,9 +4090,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -4382,7 +4100,6 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -4399,14 +4116,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", - "toml_datetime 0.6.6", - "toml_edit 0.22.16", + "toml_datetime 0.6.8", + "toml_edit 0.22.20", ] [[package]] @@ -4420,9 +4137,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -4442,73 +4159,43 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap 2.1.0", "serde", "serde_spanned", - "toml_datetime 0.6.6", + "toml_datetime 0.6.8", "winnow", ] [[package]] name = "tonic" -version = "0.11.0" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +checksum = "c6f6ba989e4b2c58ae83d862d3a3e27690b6e3ae630d0deb59f3697f32aa88ad" dependencies = [ "async-stream", "async-trait", - "axum 0.6.20", - "base64 0.21.7", - "bytes", - "h2 0.3.26", - "http 0.2.11", - "http-body 0.4.6", - "hyper 0.14.28", - "hyper-timeout 0.4.1", - "percent-encoding", - "pin-project", - "prost 0.12.3", - "rustls-pemfile 2.1.0", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.25.0", - "tokio-stream", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" -dependencies = [ - "async-stream", - "async-trait", - "axum 0.7.5", + "axum", "base64 0.22.1", "bytes", - "h2 0.4.4", - "http 1.1.0", - "http-body 1.0.0", + "h2", + "http", + "http-body", "http-body-util", - "hyper 1.4.1", - "hyper-timeout 0.5.1", + "hyper", + "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", - "prost 0.13.1", - "rustls-native-certs 0.7.0", - "rustls-pemfile 2.1.0", + "prost", + "rustls-native-certs", + "rustls-pemfile", "socket2", "tokio", - "tokio-rustls 0.26.0", + "tokio-rustls", "tokio-stream", "tower", "tower-layer", @@ -4518,54 +4205,41 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build 0.12.3", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tonic-build" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568392c5a2bd0020723e3f387891176aabafe36fd9fcd074ad309dfa0c8eb964" +checksum = "fe4ee8877250136bd7e3d2331632810a4df4ea5e004656990d8d66d2f5ee8a67" dependencies = [ "prettyplease", "proc-macro2", - "prost-build 0.13.1", + "prost-build", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] name = "tonic-health" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e10e6a96ee08b6ce443487d4368442d328d0e746f3681f81127f7dc41b4955" +checksum = "ec0a34e6f706bae26b2b490e1da5c3f6a6ff87cae442bcbc7c881bab9631b5a7" dependencies = [ "async-stream", - "prost 0.13.1", + "prost", "tokio", "tokio-stream", - "tonic 0.12.1", + "tonic", ] [[package]] name = "tonic-reflection" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b742c83ad673e9ab5b4ce0981f7b9e8932be9d60e8682cbf9120494764dbc173" +checksum = "7b56b874eedb04f89907573b408eab1e87c1c1dce43aac6ad63742f57faa99ff" dependencies = [ - "prost 0.13.1", - "prost-types 0.13.1", + "prost", + "prost-types", "tokio", "tokio-stream", - "tonic 0.12.1", + "tonic", ] [[package]] @@ -4594,10 +4268,10 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "bytes", - "http 1.1.0", - "http-body 1.0.0", + "http", + "http-body", "http-body-util", "pin-project-lite", "tower-layer", @@ -4637,7 +4311,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -4739,9 +4413,9 @@ dependencies = [ [[package]] name = "tracing-tracy" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6024d04f84a69fd0d1dc1eee3a2b070bd246530a0582f9982ae487cb6c703614" +checksum = "c6a90519f16f55e5c62ffd5976349f10744435a919ecff83d918300575dfb69b" dependencies = [ "tracing-core", "tracing-subscriber", @@ -4775,21 +4449,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] +name = "trybuild" +version = "1.0.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "207aa50d36c4be8d8c6ea829478be44a372c6a77669937bb39c698e52f1491e8" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "termcolor", + "toml 0.8.19", +] + +[[package]] name = "tvix-build" version = "0.1.0" dependencies = [ "bytes", "clap", - "itertools 0.12.0", + "itertools 0.12.1", "mimalloc", - "prost 0.13.1", - "prost-build 0.13.1", + "prost", + "prost-build", "rstest", "thiserror", "tokio", "tokio-listener", - "tonic 0.12.1", - "tonic-build 0.12.1", + "tonic", + "tonic-build", "tonic-reflection", "tracing", "tvix-castore", @@ -4823,8 +4511,8 @@ dependencies = [ "parking_lot 0.12.3", "petgraph", "pin-project-lite", - "prost 0.13.1", - "prost-build 0.13.1", + "prost", + "prost-build", "redb", "rstest", "rstest_reuse", @@ -4842,8 +4530,8 @@ dependencies = [ "tokio-stream", "tokio-tar", "tokio-util", - "tonic 0.12.1", - "tonic-build 0.12.1", + "tonic", + "tonic-build", "tonic-reflection", "tower", "tracing", @@ -4901,12 +4589,12 @@ dependencies = [ "data-encoding", "dirs", "genawaiter", - "imbl", - "itertools 0.12.0", + "itertools 0.12.1", "lazy_static", "lexical-core", "md-5", "mimalloc", + "nohash-hasher", "os_str_bytes", "path-clean", "pretty_assertions", @@ -4926,6 +4614,7 @@ dependencies = [ "test-strategy", "toml 0.6.0", "tvix-eval-builtin-macros", + "vu128", ] [[package]] @@ -4968,6 +4657,7 @@ dependencies = [ "thiserror", "tokio", "tokio-tar", + "tokio-test", "tokio-util", "tracing", "tracing-indicatif", @@ -5013,8 +4703,8 @@ dependencies = [ "nix-compat", "parking_lot 0.12.3", "pin-project-lite", - "prost 0.13.1", - "prost-build 0.13.1", + "prost", + "prost-build", "redb", "reqwest", "reqwest-middleware", @@ -5033,9 +4723,9 @@ dependencies = [ "tokio-retry", "tokio-stream", "tokio-util", - "toml 0.8.15", - "tonic 0.12.1", - "tonic-build 0.12.1", + "toml 0.8.19", + "tonic", + "tonic-build", "tonic-health", "tonic-reflection", "tower", @@ -5052,8 +4742,8 @@ dependencies = [ name = "tvix-tracing" version = "0.1.0" dependencies = [ - "axum 0.7.5", - "http 1.1.0", + "axum", + "http", "indicatif", "lazy_static", "opentelemetry 0.24.0", @@ -5063,7 +4753,7 @@ dependencies = [ "reqwest-tracing", "thiserror", "tokio", - "tonic 0.12.1", + "tonic", "tracing", "tracing-indicatif", "tracing-opentelemetry 0.25.0", @@ -5104,7 +4794,7 @@ checksum = "ac73887f47b9312552aa90ef477927ff014d63d1920ca8037c6c1951eab64bb1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -5163,9 +4853,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -5317,19 +5007,16 @@ dependencies = [ ] [[package]] -name = "wait-timeout" -version = "0.2.0" +name = "vu128" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] +checksum = "b18da3bd753c6f4373511e5f025423986560dfe4a5e7d642cc9a0266847f9fdd" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -5371,7 +5058,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", "wasm-bindgen-shared", ] @@ -5405,7 +5092,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5450,31 +5137,6 @@ dependencies = [ ] [[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "which" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5512,7 +5174,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" dependencies = [ "windows-core 0.54.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5521,7 +5183,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5530,8 +5192,19 @@ version = "0.54.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" dependencies = [ - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", ] [[package]] @@ -5540,7 +5213,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -5558,7 +5250,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5578,18 +5279,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5600,9 +5301,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5612,9 +5313,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5624,15 +5325,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5642,9 +5343,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5654,9 +5355,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5666,9 +5367,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5678,30 +5379,20 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] [[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] name = "wu-manber" version = "0.1.0" source = "git+https://github.com/tvlfyi/wu-manber.git#0d5b22bea136659f7de60b102a7030e0daaa503d" @@ -5749,7 +5440,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn 2.0.76", ] [[package]] @@ -5760,27 +5451,27 @@ checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zstd" -version = "0.13.0" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.0.0" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix index 9df3c8af8ef5..5671624ceceb 100644 --- a/tvix/Cargo.nix +++ b/tvix/Cargo.nix @@ -55,6 +55,26 @@ rec { # File a bug if you depend on any for non-debug work! debug = internal.debugCrate { inherit packageId; }; }; + "nix-compat-derive" = rec { + packageId = "nix-compat-derive"; + build = internal.buildRustCrateWithFeatures { + packageId = "nix-compat-derive"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; + "nix-compat-derive-tests" = rec { + packageId = "nix-compat-derive-tests"; + build = internal.buildRustCrateWithFeatures { + packageId = "nix-compat-derive-tests"; + }; + + # Debug support which might change between releases. + # File a bug if you depend on any for non-debug work! + debug = internal.debugCrate { inherit packageId; }; + }; "tvix-build" = rec { packageId = "tvix-build"; build = internal.buildRustCrateWithFeatures { @@ -281,13 +301,14 @@ rec { "perf-literal" = [ "dep:memchr" ]; "std" = [ "memchr?/std" ]; }; - resolvedDefaultFeatures = [ "default" "perf-literal" "std" ]; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; }; "allocator-api2" = rec { crateName = "allocator-api2"; version = "0.2.18"; edition = "2018"; sha256 = "0kr6lfnxvnj164j1x38g97qjlhb7akppqzvgfs0697140ixbav2w"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -303,6 +324,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -340,9 +362,9 @@ rec { }; "anstream" = rec { crateName = "anstream"; - version = "0.6.11"; + version = "0.6.15"; edition = "2021"; - sha256 = "19dndamalavhjwp4i74k8hdijcixb7gsfa6ycwyc1r8xn6y1wbkf"; + sha256 = "09nm4qj34kiwgzczdvj14x7hgsb235g4sqsay3xsz7zqn4d5rqb4"; dependencies = [ { name = "anstyle"; @@ -368,6 +390,10 @@ rec { packageId = "colorchoice"; } { + name = "is_terminal_polyfill"; + packageId = "is_terminal_polyfill"; + } + { name = "utf8parse"; packageId = "utf8parse"; } @@ -381,9 +407,9 @@ rec { }; "anstyle" = rec { crateName = "anstyle"; - version = "1.0.4"; + version = "1.0.8"; edition = "2021"; - sha256 = "11yxw02b6parn29s757z96rgiqbn8qy0fk9a3p3bhczm85dhfybh"; + sha256 = "1cfmkza63xpn1kkz844mgjwm9miaiz4jkyczmwxzivcsypk1vv0v"; features = { "default" = [ "std" ]; }; @@ -391,9 +417,10 @@ rec { }; "anstyle-parse" = rec { crateName = "anstyle-parse"; - version = "0.2.3"; + version = "0.2.5"; edition = "2021"; - sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + sha256 = "1jy12rvgbldflnb2x7mcww9dcffw1mx22nyv6p3n7d62h0gdwizb"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -410,9 +437,10 @@ rec { }; "anstyle-query" = rec { crateName = "anstyle-query"; - version = "1.0.2"; + version = "1.1.1"; edition = "2021"; - sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + sha256 = "0aj22iy4pzk6mz745sfrm1ym14r0y892jhcrbs8nkj7nqx9gqdkd"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; @@ -425,9 +453,10 @@ rec { }; "anstyle-wincon" = rec { crateName = "anstyle-wincon"; - version = "3.0.2"; + version = "3.0.4"; edition = "2021"; - sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + sha256 = "1y2pkvsrdxbcwircahb4wimans2pzmwwxad7ikdhj5lpdqdlxxsv"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -444,9 +473,9 @@ rec { }; "anyhow" = rec { crateName = "anyhow"; - version = "1.0.79"; + version = "1.0.86"; edition = "2018"; - sha256 = "1ji5irqiwr8yprgqj8zvnli7zd7fz9kzaiddq44jnrl2l289h3h8"; + sha256 = "1nk301x8qhpdaks6a9zvcp7yakjqnczjmqndbg7vk4494d3d1ldk"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -461,6 +490,7 @@ rec { version = "1.6.0"; edition = "2018"; sha256 = "19n9j146bpxs9phyh48gmlh9jjsdijr9p9br04qms0g9ypfsvp5x"; + libName = "arc_swap"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" ]; @@ -497,6 +527,7 @@ rec { version = "2.2.0"; edition = "2021"; sha256 = "1hzhkbrlmgbrrwb1d5aba5f03p42s6z80g5p38s127c27nj470pj"; + libName = "async_channel"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -534,9 +565,10 @@ rec { }; "async-compression" = rec { crateName = "async-compression"; - version = "0.4.9"; + version = "0.4.12"; edition = "2018"; - sha256 = "14r6vbsbbkqjiqy0qwwywjakdi29jfyidhqp389l5r4gm7bsp7jf"; + sha256 = "1ap403q889b1gghca7vigvydsnf8vr94xz3d488p9i9b9vv39hgy"; + libName = "async_compression"; authors = [ "Wim Looman <wim@nemo157.com>" "Allen Bui <fairingrey@gmail.com>" @@ -626,6 +658,7 @@ rec { version = "2.3.2"; edition = "2021"; sha256 = "110847w0ycfhklm3i928avd28x7lf9amblr2wjngi8ngk7sv1k6w"; + libName = "async_io"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -690,6 +723,7 @@ rec { version = "2.8.0"; edition = "2018"; sha256 = "0asq5xdzgp3d5m82y5rg7a0k9q0g95jy6mgc7ivl334x7qlp4wi8"; + libName = "async_lock"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -706,6 +740,7 @@ rec { version = "3.3.0"; edition = "2021"; sha256 = "0yxflkfw46rad4lv86f59b5z555dlfmg1riz1n8830rgi0qb8d6h"; + libName = "async_lock"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -733,9 +768,10 @@ rec { }; "async-process" = rec { crateName = "async-process"; - version = "2.1.0"; + version = "2.2.4"; edition = "2021"; - sha256 = "1j0cfac9p3kq5dclfzlz6jv5l29kwflh9nvr3ivmdg8ih3v3q7j5"; + sha256 = "0x3305pq0fzaqmw7q4c93sgabq97zhkr32xig5dkhkcscn4pg858"; + libName = "async_process"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -743,6 +779,11 @@ rec { { name = "async-channel"; packageId = "async-channel"; + target = { target, features }: ("linux" == target."os" or null); + } + { + name = "async-channel"; + packageId = "async-channel"; target = { target, features }: (target."windows" or false); } { @@ -760,6 +801,11 @@ rec { target = { target, features }: (target."unix" or false); } { + name = "async-task"; + packageId = "async-task"; + target = { target, features }: ("linux" == target."os" or null); + } + { name = "blocking"; packageId = "blocking"; target = { target, features }: (target."windows" or false); @@ -780,12 +826,24 @@ rec { name = "rustix"; packageId = "rustix"; usesDefaultFeatures = false; + target = { target, features }: ((target."unix" or false) && (!("linux" == target."os" or null))); + features = [ "std" "fs" "process" ]; + } + { + name = "rustix"; + packageId = "rustix"; + usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); features = [ "std" "fs" ]; } { + name = "tracing"; + packageId = "tracing"; + usesDefaultFeatures = false; + } + { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; usesDefaultFeatures = false; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_System_Threading" ]; @@ -804,6 +862,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1i9466hiqghhmljjnn83a8vnxi8z013xga03f59c89d2cl7xjiwy"; + libName = "async_signal"; authors = [ "John Nunley <dev@notgull.net>" ]; @@ -874,6 +933,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -899,6 +959,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -913,7 +974,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "visit-mut" ]; } ]; @@ -924,6 +985,7 @@ rec { version = "4.7.0"; edition = "2018"; sha256 = "16975vx6aqy5yf16fs9xz5vx1zq8mwkzfmykvcilc1j7b6c6xczv"; + libName = "async_task"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -938,6 +1000,7 @@ rec { version = "0.4.0"; edition = "2021"; sha256 = "16zx4qcwzq94n13pp6xwa4589apm5y8j20jb7lk4yzn42fqlnzdk"; + libName = "async_tempfile"; authors = [ "Markus Mayer" ]; @@ -973,6 +1036,7 @@ rec { edition = "2021"; sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -987,7 +1051,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "visit-mut" ]; } ]; @@ -998,6 +1062,7 @@ rec { version = "1.1.2"; edition = "2018"; sha256 = "1h5av1lw56m0jf0fd3bchxq8a30xv0b4wv8s4zkp4s0i7mfvs18m"; + libName = "atomic_waker"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Contributors to futures-rs" @@ -1016,135 +1081,7 @@ rec { ]; }; - "axum 0.6.20" = rec { - crateName = "axum"; - version = "0.6.20"; - edition = "2021"; - sha256 = "1gynqkg3dcy1zd7il69h8a3zax86v6qq5zpawqyn87mr6979x0iv"; - dependencies = [ - { - name = "async-trait"; - packageId = "async-trait"; - } - { - name = "axum-core"; - packageId = "axum-core 0.3.4"; - } - { - name = "bitflags"; - packageId = "bitflags 1.3.2"; - } - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "stream" ]; - } - { - name = "itoa"; - packageId = "itoa"; - } - { - name = "matchit"; - packageId = "matchit 0.7.3"; - } - { - name = "memchr"; - packageId = "memchr"; - } - { - name = "mime"; - packageId = "mime"; - } - { - name = "percent-encoding"; - packageId = "percent-encoding"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "serde"; - packageId = "serde"; - } - { - name = "sync_wrapper"; - packageId = "sync_wrapper 0.1.2"; - } - { - name = "tower"; - packageId = "tower"; - usesDefaultFeatures = false; - features = [ "util" ]; - } - { - name = "tower-layer"; - packageId = "tower-layer"; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - ]; - buildDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - ]; - devDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - { - name = "serde"; - packageId = "serde"; - features = [ "derive" ]; - } - { - name = "tower"; - packageId = "tower"; - rename = "tower"; - features = [ "util" "timeout" "limit" "load-shed" "steer" "filter" ]; - } - ]; - features = { - "__private_docs" = [ "tower/full" "dep:tower-http" ]; - "default" = [ "form" "http1" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" ]; - "form" = [ "dep:serde_urlencoded" ]; - "headers" = [ "dep:headers" ]; - "http1" = [ "hyper/http1" ]; - "http2" = [ "hyper/http2" ]; - "json" = [ "dep:serde_json" "dep:serde_path_to_error" ]; - "macros" = [ "dep:axum-macros" ]; - "multipart" = [ "dep:multer" ]; - "query" = [ "dep:serde_urlencoded" ]; - "tokio" = [ "dep:tokio" "hyper/server" "hyper/tcp" "hyper/runtime" "tower/make" ]; - "tower-log" = [ "tower/log" ]; - "tracing" = [ "dep:tracing" "axum-core/tracing" ]; - "ws" = [ "tokio" "dep:tokio-tungstenite" "dep:sha1" "dep:base64" ]; - }; - }; - "axum 0.7.5" = rec { + "axum" = rec { crateName = "axum"; version = "0.7.5"; edition = "2021"; @@ -1156,7 +1093,7 @@ rec { } { name = "axum-core"; - packageId = "axum-core 0.4.3"; + packageId = "axum-core"; } { name = "bytes"; @@ -1170,11 +1107,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -1182,7 +1119,7 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; optional = true; } { @@ -1321,71 +1258,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "form" "http1" "http2" "json" "matched-path" "original-uri" "query" "tokio" "tower-log" "tracing" ]; }; - "axum-core 0.3.4" = rec { - crateName = "axum-core"; - version = "0.3.4"; - edition = "2021"; - sha256 = "0b1d9nkqb8znaba4qqzxzc968qwj4ybn4vgpyz9lz4a7l9vsb7vm"; - dependencies = [ - { - name = "async-trait"; - packageId = "async-trait"; - } - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "mime"; - packageId = "mime"; - } - { - name = "tower-layer"; - packageId = "tower-layer"; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - ]; - buildDependencies = [ - { - name = "rustversion"; - packageId = "rustversion"; - } - ]; - devDependencies = [ - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - ]; - features = { - "__private_docs" = [ "dep:tower-http" ]; - "tracing" = [ "dep:tracing" ]; - }; - }; - "axum-core 0.4.3" = rec { + "axum-core" = rec { crateName = "axum-core"; version = "0.4.3"; edition = "2021"; sha256 = "1qx28wg4j6qdcdrisqwyaavlzc0zvbsrcwa99zf9456lfbyn6p51"; + libName = "axum_core"; dependencies = [ { name = "async-trait"; @@ -1403,11 +1281,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -1534,7 +1412,7 @@ rec { "default" = [ "std" ]; "std" = [ "alloc" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "std" ]; + resolvedDefaultFeatures = [ "alloc" "std" ]; }; "base64 0.22.1" = rec { crateName = "base64"; @@ -1567,7 +1445,12 @@ rec { crateName = "bigtable_rs"; version = "0.2.10"; edition = "2021"; - sha256 = "0wzcx254qlzy64306mg3ynp1izvn0wdii2gyn6raz0harl5bmk0j"; + workspace_member = null; + src = pkgs.fetchgit { + url = "https://github.com/liufuyang/bigtable_rs"; + rev = "1818355a5373a5bc2c84287e3a4e3807154ac8ef"; + sha256 = "0mn6iw1z7gdxbarsqiwscbdr25nplwlvzs0rs51vgnnjfsnbgl6q"; + }; authors = [ "Fuyang Liu <liufuyang@users.noreply.github.com>" ]; @@ -1578,7 +1461,12 @@ rec { } { name = "http"; - packageId = "http 0.2.11"; + packageId = "http"; + } + { + name = "hyper-util"; + packageId = "hyper-util"; + features = [ "tokio" ]; } { name = "log"; @@ -1586,11 +1474,11 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-types"; - packageId = "prost-types 0.12.3"; + packageId = "prost-types"; } { name = "prost-wkt"; @@ -1621,7 +1509,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.11.0"; + packageId = "tonic"; features = [ "tls" "transport" ]; } { @@ -1632,57 +1520,20 @@ rec { buildDependencies = [ { name = "prost-build"; - packageId = "prost-build 0.12.3"; + packageId = "prost-build"; } { - name = "prost-wkt-build"; - packageId = "prost-wkt-build"; + name = "prost-wkt-types"; + packageId = "prost-wkt-types"; } { name = "tonic-build"; - packageId = "tonic-build 0.11.0"; + packageId = "tonic-build"; features = [ "cleanup-markdown" ]; } ]; }; - "bit-set" = rec { - crateName = "bit-set"; - version = "0.5.3"; - edition = "2015"; - sha256 = "1wcm9vxi00ma4rcxkl3pzzjli6ihrpn9cfdi0c5b4cvga2mxs007"; - authors = [ - "Alexis Beingessner <a.beingessner@gmail.com>" - ]; - dependencies = [ - { - name = "bit-vec"; - packageId = "bit-vec"; - usesDefaultFeatures = false; - } - ]; - features = { - "default" = [ "std" ]; - "std" = [ "bit-vec/std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; - "bit-vec" = rec { - crateName = "bit-vec"; - version = "0.6.3"; - edition = "2015"; - sha256 = "1ywqjnv60cdh1slhz67psnp422md6jdliji6alq0gmly2xm9p7rl"; - authors = [ - "Alexis Beingessner <a.beingessner@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - "serde_no_std" = [ "serde/alloc" ]; - "serde_std" = [ "std" "serde/std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "bitflags 1.3.2" = rec { crateName = "bitflags"; version = "1.3.2"; @@ -1698,11 +1549,11 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "bitflags 2.4.2" = rec { + "bitflags 2.6.0" = rec { crateName = "bitflags"; - version = "2.4.2"; + version = "2.6.0"; edition = "2021"; - sha256 = "1pqd142hyqlzr7p9djxq2ff0jx07a2sb2xp9lhw69cbf80s0jmzd"; + sha256 = "1pkidwzn3hnxlsl8zizh0bncgbjnw7c41cx7bby26ncbzmiznj5h"; authors = [ "The Rust Project Developers" ]; @@ -1716,24 +1567,11 @@ rec { }; resolvedDefaultFeatures = [ "std" ]; }; - "bitmaps" = rec { - crateName = "bitmaps"; - version = "3.2.0"; - edition = "2021"; - sha256 = "00ql08pm4l9hizkldyy54v0pk96g7zg8x6i72c2vkcq0iawl4dkh"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - ]; - features = { - "default" = [ "std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "blake3" = rec { crateName = "blake3"; - version = "1.5.0"; + version = "1.5.4"; edition = "2021"; - sha256 = "11ysh12zcqq6xkjxh5cbrmnwzalprm3z552i5ff7wm5za9hz0c82"; + sha256 = "1xy6gp8yfcpvzwrhbx5iksxxwf6hsix403klizgr1s6qgwj3686q"; authors = [ "Jack O'Connor <oconnor663@gmail.com>" "Samuel Neves" @@ -1763,8 +1601,8 @@ rec { features = [ "mac" ]; } { - name = "rayon"; - packageId = "rayon"; + name = "rayon-core"; + packageId = "rayon-core"; optional = true; } ]; @@ -1776,20 +1614,20 @@ rec { ]; features = { "default" = [ "std" ]; - "digest" = [ "dep:digest" ]; "mmap" = [ "std" "dep:memmap2" ]; - "rayon" = [ "dep:rayon" "std" ]; + "rayon" = [ "dep:rayon-core" "std" ]; "serde" = [ "dep:serde" ]; - "traits-preview" = [ "digest" ]; + "traits-preview" = [ "dep:digest" ]; "zeroize" = [ "dep:zeroize" "arrayvec/zeroize" ]; }; - resolvedDefaultFeatures = [ "default" "digest" "rayon" "std" "traits-preview" ]; + resolvedDefaultFeatures = [ "default" "rayon" "std" "traits-preview" ]; }; "block-buffer" = rec { crateName = "block-buffer"; version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -1858,9 +1696,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.9.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "1p6hzf3wqwwynv6w4pn17jg21amfafph9kb5sfvf1idlli8h13y4"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -1872,7 +1710,7 @@ rec { } { name = "regex-automata"; - packageId = "regex-automata 0.4.3"; + packageId = "regex-automata 0.4.7"; optional = true; usesDefaultFeatures = false; features = [ "dfa-search" ]; @@ -1921,9 +1759,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0l5sf69avjxcw41cznyzxsnymwmkpmk08q0sm7fgicvvn0ysa643"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -2023,10 +1861,9 @@ rec { }; "cc" = rec { crateName = "cc"; - version = "1.0.83"; + version = "1.1.15"; edition = "2018"; - crateBin = [ ]; - sha256 = "1l643zidlb5iy1dskc5ggqs4wqa29a02f44piczqc8zcnsq4y5zi"; + sha256 = "1rn62w58ba1ylqlp3saj4n0vh1h40ii1r83xr06p80r9m9ss5djp"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2035,25 +1872,31 @@ rec { name = "jobserver"; packageId = "jobserver"; optional = true; + usesDefaultFeatures = false; } { name = "libc"; packageId = "libc"; + optional = true; usesDefaultFeatures = false; target = { target, features }: (target."unix" or false); } + { + name = "shlex"; + packageId = "shlex"; + } ]; features = { - "jobserver" = [ "dep:jobserver" ]; - "parallel" = [ "jobserver" ]; + "parallel" = [ "dep:libc" "dep:jobserver" ]; }; - resolvedDefaultFeatures = [ "jobserver" "parallel" ]; + resolvedDefaultFeatures = [ "parallel" ]; }; "cfg-if" = rec { crateName = "cfg-if"; version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2107,7 +1950,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; optional = true; target = { target, features }: (target."windows" or false); } @@ -2173,6 +2016,7 @@ rec { version = "0.2.1"; edition = "2021"; sha256 = "0mi6ci27lpz3azksxrvgzl9jc4a3dfr20pjx7y2nkcrjalbikyfd"; + libName = "ciborium_io"; authors = [ "Nathaniel McCallum <npmccallum@profian.com>" ]; @@ -2186,6 +2030,7 @@ rec { version = "0.2.1"; edition = "2021"; sha256 = "0az2vabamfk75m74ylgf6nzqgqgma5yf25bc1ripfg09ri7a5yny"; + libName = "ciborium_ll"; authors = [ "Nathaniel McCallum <npmccallum@profian.com>" ]; @@ -2205,10 +2050,10 @@ rec { }; "clap" = rec { crateName = "clap"; - version = "4.4.18"; + version = "4.5.16"; edition = "2021"; crateBin = [ ]; - sha256 = "0p46h346y8nval6gwzh27if3icbi9dwl95fg5ir36ihrqip8smqy"; + sha256 = "068hjwbrndn4iz4fsc6d52q4ymg1kfsymjnqbxzdil23zbzijrzd"; dependencies = [ { name = "clap_builder"; @@ -2236,6 +2081,7 @@ rec { "suggestions" = [ "clap_builder/suggestions" ]; "unicode" = [ "clap_builder/unicode" ]; "unstable-doc" = [ "clap_builder/unstable-doc" "derive" ]; + "unstable-ext" = [ "clap_builder/unstable-ext" ]; "unstable-styles" = [ "clap_builder/unstable-styles" ]; "unstable-v5" = [ "clap_builder/unstable-v5" "clap_derive?/unstable-v5" "deprecated" ]; "usage" = [ "clap_builder/usage" ]; @@ -2245,9 +2091,9 @@ rec { }; "clap_builder" = rec { crateName = "clap_builder"; - version = "4.4.18"; + version = "4.5.15"; edition = "2021"; - sha256 = "1iyif47075caa4x1p3ygk18b07lb4xl4k48w4c061i2hxi0dzx2d"; + sha256 = "1dmas5z20yqmlmfhykr38pn1hkcnr4jzxjw4cs2f6lkn2wmyqsi1"; dependencies = [ { name = "anstream"; @@ -2264,7 +2110,7 @@ rec { } { name = "strsim"; - packageId = "strsim"; + packageId = "strsim 0.11.1"; optional = true; } ]; @@ -2275,7 +2121,7 @@ rec { "std" = [ "anstyle/std" ]; "suggestions" = [ "dep:strsim" "error-context" ]; "unicode" = [ "dep:unicode-width" "dep:unicase" ]; - "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" ]; + "unstable-doc" = [ "cargo" "wrap_help" "env" "unicode" "string" "unstable-ext" ]; "unstable-styles" = [ "color" ]; "unstable-v5" = [ "deprecated" ]; "wrap_help" = [ "help" "dep:terminal_size" ]; @@ -2284,14 +2130,14 @@ rec { }; "clap_derive" = rec { crateName = "clap_derive"; - version = "4.4.7"; + version = "4.5.13"; edition = "2021"; - sha256 = "0hk4hcxl56qwqsf4hmf7c0gr19r9fbxk0ah2bgkr36pmmaph966g"; + sha256 = "1860xq3rbgwsqwcj9rd14cky9iiywwx86j7fvvngdjixbyfka7ah"; procMacro = true; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.5.0"; } { name = "proc-macro2"; @@ -2303,7 +2149,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } ]; @@ -2315,9 +2161,9 @@ rec { }; "clap_lex" = rec { crateName = "clap_lex"; - version = "0.6.0"; + version = "0.7.2"; edition = "2021"; - sha256 = "1l8bragdvim7mva9flvd159dskn2bdkpl0jqrr41wnjfn8pcfbvh"; + sha256 = "15zcrc2fa6ycdzaihxghf48180bnvzsivhf0fmah24bnnaf76qhl"; }; "clipboard-win" = rec { @@ -2325,6 +2171,7 @@ rec { version = "4.5.0"; edition = "2018"; sha256 = "0qh3rypkf1lazniq4nr04hxsck0d55rigb5sjvpvgnap4dyc54bi"; + libName = "clipboard_win"; authors = [ "Douman <douman@gmx.se>" ]; @@ -2366,6 +2213,7 @@ rec { version = "0.1.2"; edition = "2015"; sha256 = "08l1b84bn8r8a72rbvyi2v8a5i0j0kk0a5gr7fb6lmjvw05pf86c"; + libName = "codemap_diagnostic"; authors = [ "Kevin Mehall <km@kevinmehall.net>" "The Rust Project Developers" @@ -2384,9 +2232,9 @@ rec { }; "colorchoice" = rec { crateName = "colorchoice"; - version = "1.0.0"; + version = "1.0.2"; edition = "2021"; - sha256 = "1ix7w85kwvyybwi2jdkl3yva2r2bvdcc3ka2grjfzfgrapqimgxc"; + sha256 = "1h18ph538y8yjmbpaf8li98l0ifms2xmh3rax9666c5qfjfi3zfk"; }; "concurrent-queue" = rec { @@ -2394,6 +2242,7 @@ rec { version = "2.4.0"; edition = "2018"; sha256 = "0qvk23ynj311adb4z7v89wk3bs65blps4n24q8rgl23vjk6lhq6i"; + libName = "concurrent_queue"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Taiki Endo <te316e89@gmail.com>" @@ -2459,6 +2308,7 @@ rec { version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -2481,6 +2331,7 @@ rec { version = "0.9.4"; edition = "2018"; sha256 = "13zvbbj07yk3b61b8fhwfzhy35535a583irf23vlcg59j7h9bqci"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -2512,6 +2363,7 @@ rec { version = "0.8.6"; edition = "2018"; sha256 = "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -2525,6 +2377,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "11bswmgr81s3jagdci1pr6qh9vnz9zsbbf2dqpi260daa2mhgmff"; + libName = "count_write"; authors = [ "SOFe <sofe2038@gmail.com>" ]; @@ -2720,6 +2573,7 @@ rec { version = "0.5.0"; edition = "2018"; sha256 = "1c866xkjqqhzg4cjvg01f8w6xc1j3j7s58rdksl52skq89iq4l3b"; + libName = "criterion_plot"; authors = [ "Jorge Aparicio <japaricious@gmail.com>" "Brook Heisler <brookheisler@gmail.com>" @@ -2741,6 +2595,7 @@ rec { version = "0.5.11"; edition = "2021"; sha256 = "16v48qdflpw3hgdik70bhsj7hympna79q7ci47rw0mlgnxsw2v8p"; + libName = "crossbeam_channel"; dependencies = [ { name = "crossbeam-utils"; @@ -2759,6 +2614,7 @@ rec { version = "0.8.5"; edition = "2021"; sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; dependencies = [ { name = "crossbeam-epoch"; @@ -2782,6 +2638,7 @@ rec { version = "0.9.18"; edition = "2021"; sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; dependencies = [ { name = "crossbeam-utils"; @@ -2803,6 +2660,7 @@ rec { version = "0.8.19"; edition = "2021"; sha256 = "0iakrb1b8fjqrag7wphl94d10irhbh2fw1g444xslsywqyn3p3i4"; + libName = "crossbeam_utils"; features = { "default" = [ "std" ]; "loom" = [ "dep:loom" ]; @@ -2814,6 +2672,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -2839,6 +2698,7 @@ rec { version = "4.1.1"; edition = "2021"; sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -2911,6 +2771,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -2922,7 +2783,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } ]; @@ -2980,12 +2841,12 @@ rec { } { name = "strsim"; - packageId = "strsim"; + packageId = "strsim 0.10.0"; optional = true; } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "extra-traits" ]; } ]; @@ -3015,7 +2876,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; } ]; @@ -3025,6 +2886,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -3173,6 +3035,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -3193,6 +3056,7 @@ rec { version = "0.3.7"; edition = "2015"; sha256 = "19md1cnkazham8a6kh22v12d8hh3raqahfk6yb043vrjr68is78v"; + libName = "dirs_sys"; authors = [ "Simon Ochsenreither <simon@ochsenreither.de>" ]; @@ -3222,6 +3086,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -3273,6 +3138,7 @@ rec { edition = "2018"; sha256 = "15cvgxqngxslgllz15m8aban6wqfgsi6nlhr0g25yfsnd6nq4lpg"; procMacro = true; + libName = "document_features"; libPath = "lib.rs"; authors = [ "Slint Developers <info@slint-ui.com>" @@ -3321,9 +3187,10 @@ rec { }; "ed25519-dalek" = rec { crateName = "ed25519-dalek"; - version = "2.1.0"; + version = "2.1.1"; edition = "2021"; - sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -3408,7 +3275,7 @@ rec { "default" = [ "use_std" ]; "serde" = [ "dep:serde" ]; }; - resolvedDefaultFeatures = [ "default" "use_std" ]; + resolvedDefaultFeatures = [ "use_std" ]; }; "encode_unicode" = rec { crateName = "encode_unicode"; @@ -3430,6 +3297,7 @@ rec { version = "0.1.2"; edition = "2015"; sha256 = "0bbh88zaig1jfqrm7w3gx0pz81kw2jakk3055vbgapw3dmk08ky3"; + libName = "endian_type"; authors = [ "Lolirofle <lolipopple@hotmail.com>" ]; @@ -3441,6 +3309,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -3456,7 +3325,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; } ]; @@ -3540,6 +3409,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "08baxlf8qz01lgjsdbfhs193r9y1nlc566s5xvzyf4dzwy8qkwb4"; + libName = "error_code"; authors = [ "Douman <douman@gmx.se>" ]; @@ -3561,6 +3431,7 @@ rec { version = "2.5.3"; edition = "2018"; sha256 = "1q4w3pndc518crld6zsqvvpy9lkzwahp2zgza9kbzmmqh9gif1h2"; + libName = "event_listener"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -3571,6 +3442,7 @@ rec { version = "4.0.3"; edition = "2021"; sha256 = "0vk4smw1vf871vi76af1zn7w69jg3zmpjddpby2qq91bkg21bck7"; + libName = "event_listener"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -3606,6 +3478,7 @@ rec { version = "5.2.0"; edition = "2021"; sha256 = "14fcnjgpfl22645nhc3hzkdq3a1v0srqacc3kfassg7sjj8vhprb"; + libName = "event_listener"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" ]; @@ -3641,6 +3514,7 @@ rec { version = "0.4.0"; edition = "2018"; sha256 = "1lwprdjqp2ibbxhgm9khw7s7y7k4xiqj5i5yprqiks6mnrq4v3lm"; + libName = "event_listener_strategy"; authors = [ "John Nunley <dev@notgull.net>" ]; @@ -3666,6 +3540,7 @@ rec { version = "0.5.0"; edition = "2021"; sha256 = "148jflvjrq0zrr3dx3srv88jksj1klm4amy3b9fifjdpm75azvgy"; + libName = "event_listener_strategy"; authors = [ "John Nunley <dev@notgull.net>" ]; @@ -3691,6 +3566,7 @@ rec { version = "1.5.0"; edition = "2018"; sha256 = "1q55nrkgzg345905aqbsdrwlq4sk0gjn4z5bdph1an1kc6jy02wy"; + libName = "expect_test"; authors = [ "rust-analyzer developers" ]; @@ -3768,6 +3644,7 @@ rec { version = "3.0.13"; edition = "2018"; sha256 = "1df1jdncda67g65hrnmd2zsl7q5hdn8cm84chdalxndsx7akw0zg"; + libName = "fd_lock"; authors = [ "Yoshua Wuyts <yoshuawuyts@gmail.com>" ]; @@ -3796,6 +3673,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -3958,6 +3836,7 @@ rec { version = "0.11.0"; edition = "2018"; sha256 = "0jyldvp0kvjk21j5vqga42lkksaf7zg8jkj3l6h2dv20kyl66nif"; + libName = "fuse_backend_rs"; authors = [ "Liu Bo <bo.liu@linux.alibaba.com>" "Liu Jiang <gerry@linux.alibaba.com>" @@ -3998,7 +3877,7 @@ rec { } { name = "mio"; - packageId = "mio"; + packageId = "mio 0.8.11"; features = [ "os-poll" "os-ext" ]; } { @@ -4126,6 +4005,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -4153,6 +4033,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -4165,6 +4046,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -4195,6 +4077,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -4205,6 +4088,7 @@ rec { version = "2.3.0"; edition = "2021"; sha256 = "19gk4my8zhfym6gwnpdjiyv2hw8cc098skkbkhryjdaf0yspwljj"; + libName = "futures_lite"; authors = [ "Stjepan Glavina <stjepang@gmail.com>" "Contributors to futures-rs" @@ -4253,6 +4137,7 @@ rec { edition = "2018"; sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -4264,7 +4149,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } ]; @@ -4275,6 +4160,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -4286,6 +4172,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -4297,6 +4184,7 @@ rec { version = "3.0.2"; edition = "2018"; sha256 = "0b5v7lk9838ix6jdcrainsyrh7xrf24pwm61dp13907qkn806jz6"; + libName = "futures_timer"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4311,6 +4199,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -4410,9 +4299,9 @@ rec { }; "gcp_auth" = rec { crateName = "gcp_auth"; - version = "0.10.0"; + version = "0.12.2"; edition = "2021"; - sha256 = "1m7lsh2gc7n9p0gs9k2qbxsrvchw1vz6dyz9a2ma322vd3m72b6y"; + sha256 = "0gb9bp9nkc810kfycm4vxndpccbhx68lcirq0y06lafykpkpjv2k"; dependencies = [ { name = "async-trait"; @@ -4420,7 +4309,11 @@ rec { } { name = "base64"; - packageId = "base64 0.21.7"; + packageId = "base64 0.22.1"; + } + { + name = "bytes"; + packageId = "bytes"; } { name = "chrono"; @@ -4432,27 +4325,37 @@ rec { packageId = "home"; } { + name = "http"; + packageId = "http"; + } + { + name = "http-body-util"; + packageId = "http-body-util"; + } + { name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" "runtime" "http2" ]; + packageId = "hyper"; + usesDefaultFeatures = false; + features = [ "client" "http1" "http2" ]; } { name = "hyper-rustls"; - packageId = "hyper-rustls 0.24.2"; + packageId = "hyper-rustls"; usesDefaultFeatures = false; - features = [ "tokio-runtime" "http1" "http2" ]; + features = [ "http1" "http2" ]; } { - name = "ring"; - packageId = "ring"; + name = "hyper-util"; + packageId = "hyper-util"; + features = [ "client-legacy" ]; } { - name = "rustls"; - packageId = "rustls 0.21.12"; + name = "ring"; + packageId = "ring"; } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 1.0.4"; + packageId = "rustls-pemfile"; } { name = "serde"; @@ -4484,10 +4387,6 @@ rec { name = "url"; packageId = "url"; } - { - name = "which"; - packageId = "which 5.0.0"; - } ]; devDependencies = [ { @@ -4497,7 +4396,7 @@ rec { } ]; features = { - "default" = [ "hyper-rustls/rustls-native-certs" ]; + "default" = [ "hyper-rustls/rustls-native-certs" "hyper-rustls/ring" ]; "webpki-roots" = [ "hyper-rustls/webpki-roots" ]; }; resolvedDefaultFeatures = [ "default" ]; @@ -4530,6 +4429,7 @@ rec { version = "0.99.1"; edition = "2018"; sha256 = "1g6zmr88fk48f1ksz9ik1i2mwjsiam9s4p9aybhvs2zwzphxychb"; + libName = "genawaiter_macro"; authors = [ "Devin R <devin.ragotzy@gmail.com>" ]; @@ -4680,79 +4580,7 @@ rec { ]; }; - "h2 0.3.26" = rec { - crateName = "h2"; - version = "0.3.26"; - edition = "2018"; - sha256 = "1s7msnfv7xprzs6xzfj5sg6p8bjcdpcqcmjjbkd345cyi1x55zl1"; - authors = [ - "Carl Lerche <me@carllerche.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; - } - { - name = "futures-sink"; - packageId = "futures-sink"; - usesDefaultFeatures = false; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "indexmap"; - packageId = "indexmap 2.1.0"; - features = [ "std" ]; - } - { - name = "slab"; - packageId = "slab"; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "io-util" ]; - } - { - name = "tokio-util"; - packageId = "tokio-util"; - features = [ "codec" "io" ]; - } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - features = [ "std" ]; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "rt-multi-thread" "macros" "sync" "net" ]; - } - ]; - features = { }; - }; - "h2 0.4.4" = rec { + "h2" = rec { crateName = "h2"; version = "0.4.4"; edition = "2021"; @@ -4787,7 +4615,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "indexmap"; @@ -4902,7 +4730,7 @@ rec { }; resolvedDefaultFeatures = [ "ahash" "allocator-api2" "default" "inline-more" "raw" ]; }; - "heck" = rec { + "heck 0.4.1" = rec { crateName = "heck"; version = "0.4.1"; edition = "2018"; @@ -4916,11 +4744,19 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "heck 0.5.0" = rec { + crateName = "heck"; + version = "0.5.0"; + edition = "2021"; + sha256 = "1sjmpsdl8czyh9ywl3qcsfsq9a307dg4ni2vnlwgnzzqhc4y0113"; + + }; "hermit-abi" = rec { crateName = "hermit-abi"; - version = "0.3.4"; + version = "0.3.9"; edition = "2021"; - sha256 = "07v5vbwb9kx0yxgdpx15h38ynpzhaqx5ncriryipypi5707hwgax"; + sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -4952,6 +4788,7 @@ rec { version = "0.4.1"; edition = "2021"; sha256 = "0iny5inkixsdr41pm2vkqh3fl66752z5j5c0cdxw16yl9ryjdqkg"; + libName = "hex_literal"; authors = [ "RustCrypto Developers" ]; @@ -4975,33 +4812,7 @@ rec { ]; }; - "http 0.2.11" = rec { - crateName = "http"; - version = "0.2.11"; - edition = "2018"; - sha256 = "1fwz3mhh86h5kfnr5767jlx9agpdggclq7xsqx930fflzakb2iw9"; - authors = [ - "Alex Crichton <alex@alexcrichton.com>" - "Carl Lerche <me@carllerche.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "itoa"; - packageId = "itoa"; - } - ]; - - }; - "http 1.1.0" = rec { + "http" = rec { crateName = "http"; version = "1.1.0"; edition = "2018"; @@ -5030,37 +4841,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "http-body 0.4.6" = rec { - crateName = "http-body"; - version = "0.4.6"; - edition = "2018"; - sha256 = "1lmyjfk6bqk6k9gkn1dxq770sb78pqbqshga241hr5p995bb5skw"; - authors = [ - "Carl Lerche <me@carllerche.com>" - "Lucio Franco <luciofranco14@gmail.com>" - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - ]; - - }; - "http-body 1.0.0" = rec { + "http-body" = rec { crateName = "http-body"; version = "1.0.0"; edition = "2018"; sha256 = "0hyn8n3iadrbwq8y0p1rl1275s4nm49bllw5wji29g4aa3dqbb0w"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -5073,7 +4859,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } ]; @@ -5083,6 +4869,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "07agldas2qgcfc05ckiarlmf9vzragbda823nqhrqrc6mjrghx84"; + libName = "http_body_util"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -5099,11 +4886,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "pin-project-lite"; @@ -5145,114 +4932,7 @@ rec { ]; }; - "hyper 0.14.28" = rec { - crateName = "hyper"; - version = "0.14.28"; - edition = "2018"; - sha256 = "107gkvqx4h9bl17d602zkm2dgpfq86l2dr36yzfsi8l3xcsy35mz"; - authors = [ - "Sean McArthur <sean@seanmonstar.com>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "futures-channel"; - packageId = "futures-channel"; - } - { - name = "futures-core"; - packageId = "futures-core"; - usesDefaultFeatures = false; - } - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "h2"; - packageId = "h2 0.3.26"; - optional = true; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "httparse"; - packageId = "httparse"; - } - { - name = "httpdate"; - packageId = "httpdate"; - } - { - name = "itoa"; - packageId = "itoa"; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "socket2"; - packageId = "socket2"; - optional = true; - features = [ "all" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "sync" ]; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - { - name = "tracing"; - packageId = "tracing"; - usesDefaultFeatures = false; - features = [ "std" ]; - } - { - name = "want"; - packageId = "want"; - } - ]; - devDependencies = [ - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - features = [ "alloc" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "fs" "macros" "io-std" "io-util" "rt" "rt-multi-thread" "sync" "time" "test-util" ]; - } - ]; - features = { - "ffi" = [ "libc" ]; - "full" = [ "client" "http1" "http2" "server" "stream" "runtime" ]; - "h2" = [ "dep:h2" ]; - "http2" = [ "h2" ]; - "libc" = [ "dep:libc" ]; - "runtime" = [ "tcp" "tokio/rt" "tokio/time" ]; - "socket2" = [ "dep:socket2" ]; - "tcp" = [ "socket2" "tokio/net" "tokio/rt" "tokio/time" ]; - }; - resolvedDefaultFeatures = [ "client" "default" "full" "h2" "http1" "http2" "runtime" "server" "socket2" "stream" "tcp" ]; - }; - "hyper 1.4.1" = rec { + "hyper" = rec { crateName = "hyper"; version = "1.4.1"; edition = "2021"; @@ -5278,16 +4958,16 @@ rec { } { name = "h2"; - packageId = "h2 0.4.4"; + packageId = "h2"; optional = true; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "httparse"; @@ -5355,86 +5035,12 @@ rec { }; resolvedDefaultFeatures = [ "client" "default" "http1" "http2" "server" ]; }; - "hyper-rustls 0.24.2" = rec { - crateName = "hyper-rustls"; - version = "0.24.2"; - edition = "2021"; - sha256 = "1475j4a2nczz4aajzzsq3hpwg1zacmzbqg393a14j80ff8izsgpc"; - dependencies = [ - { - name = "futures-util"; - packageId = "futures-util"; - usesDefaultFeatures = false; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "hyper"; - packageId = "hyper 0.14.28"; - usesDefaultFeatures = false; - features = [ "client" ]; - } - { - name = "rustls"; - packageId = "rustls 0.21.12"; - usesDefaultFeatures = false; - } - { - name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.6.3"; - optional = true; - } - { - name = "tokio"; - packageId = "tokio"; - } - { - name = "tokio-rustls"; - packageId = "tokio-rustls 0.24.1"; - usesDefaultFeatures = false; - } - ]; - devDependencies = [ - { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "full" ]; - } - { - name = "rustls"; - packageId = "rustls 0.21.12"; - usesDefaultFeatures = false; - features = [ "tls12" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "io-std" "macros" "net" "rt-multi-thread" ]; - } - ]; - features = { - "acceptor" = [ "hyper/server" "tokio-runtime" ]; - "default" = [ "native-tokio" "http1" "tls12" "logging" "acceptor" ]; - "http1" = [ "hyper/http1" ]; - "http2" = [ "hyper/http2" ]; - "log" = [ "dep:log" ]; - "logging" = [ "log" "tokio-rustls/logging" "rustls/logging" ]; - "native-tokio" = [ "tokio-runtime" "rustls-native-certs" ]; - "rustls-native-certs" = [ "dep:rustls-native-certs" ]; - "tls12" = [ "tokio-rustls/tls12" "rustls/tls12" ]; - "tokio-runtime" = [ "hyper/runtime" ]; - "webpki-roots" = [ "dep:webpki-roots" ]; - "webpki-tokio" = [ "tokio-runtime" "webpki-roots" ]; - }; - resolvedDefaultFeatures = [ "http1" "http2" "rustls-native-certs" "tokio-runtime" ]; - }; - "hyper-rustls 0.27.2" = rec { + "hyper-rustls" = rec { crateName = "hyper-rustls"; version = "0.27.2"; edition = "2021"; sha256 = "0ma1wyfnqnkz7zyr7wpply3xfvlijd0rqqhb6ajs28c9jhnbxr2y"; + libName = "hyper_rustls"; dependencies = [ { name = "futures-util"; @@ -5443,11 +5049,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; usesDefaultFeatures = false; } { @@ -5458,12 +5064,12 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; usesDefaultFeatures = false; } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.7.0"; + packageId = "rustls-native-certs"; optional = true; } { @@ -5477,7 +5083,7 @@ rec { } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.26.0"; + packageId = "tokio-rustls"; usesDefaultFeatures = false; } { @@ -5494,7 +5100,7 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; usesDefaultFeatures = false; features = [ "tls12" ]; } @@ -5522,59 +5128,19 @@ rec { }; resolvedDefaultFeatures = [ "http1" "http2" "native-tokio" "ring" "rustls-native-certs" "tls12" ]; }; - "hyper-timeout 0.4.1" = rec { - crateName = "hyper-timeout"; - version = "0.4.1"; - edition = "2018"; - sha256 = "1c8k3g8k2yh1gxvsx9p7amkimgxhl9kafwpj7jyf8ywc5r45ifdv"; - authors = [ - "Herman J. Radtke III <herman@hermanradtke.com>" - ]; - dependencies = [ - { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" ]; - } - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "tokio"; - packageId = "tokio"; - } - { - name = "tokio-io-timeout"; - packageId = "tokio-io-timeout"; - } - ]; - devDependencies = [ - { - name = "hyper"; - packageId = "hyper 0.14.28"; - features = [ "client" "http1" "tcp" ]; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "io-std" "io-util" "macros" ]; - } - ]; - - }; - "hyper-timeout 0.5.1" = rec { + "hyper-timeout" = rec { crateName = "hyper-timeout"; version = "0.5.1"; edition = "2018"; sha256 = "14rpyv9zz0ncadn9qgmnjz0hiqk3nav7hglkk1a6yfy8wmhsj0rj"; + libName = "hyper_timeout"; authors = [ "Herman J. Radtke III <herman@hermanradtke.com>" ]; dependencies = [ { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; } { name = "hyper-util"; @@ -5597,7 +5163,7 @@ rec { devDependencies = [ { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; features = [ "http1" ]; } { @@ -5610,9 +5176,9 @@ rec { }; "hyper-util" = rec { crateName = "hyper-util"; - version = "0.1.6"; + version = "0.1.7"; edition = "2021"; - sha256 = "0mm9biwckhwqz23s5dp02410aw7sw2ibg167jzwv8kzf957jzf9s"; + sha256 = "1fg9h591skksq5zxnffyisj7487jhdcgj6c7bvlkckn535bhbryd"; libName = "hyper_util"; authors = [ "Sean McArthur <sean@seanmonstar.com>" @@ -5634,15 +5200,15 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; } { name = "pin-project-lite"; @@ -5687,7 +5253,7 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; features = [ "full" ]; } { @@ -5715,6 +5281,7 @@ rec { version = "0.1.60"; edition = "2018"; sha256 = "0hdid5xz3jznm04lysjm3vi93h3c523w0hcc3xba47jl3ddbpzz7"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -5760,6 +5327,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -5808,95 +5376,6 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "imbl" = rec { - crateName = "imbl"; - version = "3.0.0"; - edition = "2018"; - sha256 = "1sw1vw8qysyr9cxyxfi3fal9ykf46zw337w4n533mwrnrpcfhfxw"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - } - { - name = "imbl-sized-chunks"; - packageId = "imbl-sized-chunks"; - } - { - name = "proptest"; - packageId = "proptest"; - optional = true; - } - { - name = "rand_core"; - packageId = "rand_core"; - } - { - name = "rand_xoshiro"; - packageId = "rand_xoshiro"; - } - { - name = "serde"; - packageId = "serde"; - optional = true; - } - ]; - buildDependencies = [ - { - name = "version_check"; - packageId = "version_check"; - } - ]; - devDependencies = [ - { - name = "proptest"; - packageId = "proptest"; - } - { - name = "serde"; - packageId = "serde"; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "proptest" = [ "dep:proptest" ]; - "quickcheck" = [ "dep:quickcheck" ]; - "rayon" = [ "dep:rayon" ]; - "refpool" = [ "dep:refpool" ]; - "serde" = [ "dep:serde" ]; - "triomphe" = [ "dep:triomphe" ]; - }; - resolvedDefaultFeatures = [ "proptest" "serde" ]; - }; - "imbl-sized-chunks" = rec { - crateName = "imbl-sized-chunks"; - version = "0.1.2"; - edition = "2021"; - sha256 = "0qzdw55na2w6fd44p7y9rh05nxa98gzpaigmwg57sy7db3xhch0l"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - usesDefaultFeatures = false; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "array-ops" = [ "dep:array-ops" ]; - "default" = [ "std" ]; - "refpool" = [ "dep:refpool" ]; - "ringbuffer" = [ "array-ops" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "indexmap 1.9.3" = rec { crateName = "indexmap"; version = "1.9.3"; @@ -6070,6 +5549,7 @@ rec { version = "0.4.10"; edition = "2018"; sha256 = "0m9la3f7cs77y85nkbcjsxkb7k861fc6bdhahyfidgh7gljh1b8b"; + libName = "is_terminal"; authors = [ "softprops <d.tangren@gmail.com>" "Dan Gohman <dev@sunfishcode.online>" @@ -6103,6 +5583,14 @@ rec { ]; }; + "is_terminal_polyfill" = rec { + crateName = "is_terminal_polyfill"; + version = "1.70.1"; + edition = "2021"; + sha256 = "1kwfgglh91z33kl0w5i338mfpa3zs0hidq5j4ny4rmjwrikchhvr"; + features = { }; + resolvedDefaultFeatures = [ "default" ]; + }; "itertools 0.10.5" = rec { crateName = "itertools"; version = "0.10.5"; @@ -6124,11 +5612,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_alloc" "use_std" ]; }; - "itertools 0.11.0" = rec { + "itertools 0.12.1" = rec { crateName = "itertools"; - version = "0.11.0"; + version = "0.12.1"; edition = "2018"; - sha256 = "0mzyqcc59azx9g5cg6fs8k529gvh4463smmka6jvzs3cd2jp7hdi"; + sha256 = "0s95jbb3ndj1lvfxyq5wanc0fm0r6hg6q4ngb92qlfdxvci10ads"; authors = [ "bluss" ]; @@ -6143,13 +5631,13 @@ rec { "default" = [ "use_std" ]; "use_std" = [ "use_alloc" "either/use_std" ]; }; - resolvedDefaultFeatures = [ "use_alloc" ]; + resolvedDefaultFeatures = [ "default" "use_alloc" "use_std" ]; }; - "itertools 0.12.0" = rec { + "itertools 0.13.0" = rec { crateName = "itertools"; - version = "0.12.0"; + version = "0.13.0"; edition = "2018"; - sha256 = "1c07gzdlc6a1c8p8jrvvw3gs52bss3y58cs2s21d9i978l36pnr5"; + sha256 = "11hiy3qzl643zcigknclh446qb9zlg4dpdzfkjaa9q9fqpgyfgj1"; authors = [ "bluss" ]; @@ -6180,9 +5668,9 @@ rec { }; "jobserver" = rec { crateName = "jobserver"; - version = "0.1.27"; - edition = "2018"; - sha256 = "0z9w6vfqwbr6hfk9yaw7kydlh6f7k39xdlszxlh39in4acwzcdwc"; + version = "0.1.32"; + edition = "2021"; + sha256 = "1l2k50qmj84x9mn39ivjz76alqmx72jhm12rw33zx9xnpv5xpla8"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -6200,6 +5688,7 @@ rec { version = "0.3.67"; edition = "2018"; sha256 = "1lar78p13w781b4zf44a0sk26i461fczbdrhpan6kjav4gqkc7cs"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -6213,9 +5702,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -6229,6 +5718,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ihf0x3vrk25fq3bv9q35m0xax0wmvwkh0j0pjm2yk4ddvh5vpic"; + libName = "lexical_core"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6291,6 +5781,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0py0gp8hlzcrlvjqmqlpl2v1as65iiqxq2xsabxvhc01pmg3lfv8"; + libName = "lexical_parse_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6331,6 +5822,7 @@ rec { version = "0.8.6"; edition = "2018"; sha256 = "1sayji3mpvb2xsjq56qcq3whfz8px9a6fxk5v7v15hyhbr4982bd"; + libName = "lexical_parse_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6362,6 +5854,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "1z73qkv7yxhsbc4aiginn1dqmsj8jarkrdlyxc88g2gz2vzvjmaj"; + libName = "lexical_util"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6388,6 +5881,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0qk825l0csvnksh9sywb51996cjc2bylq6rxjaiha7sqqjhvmjmc"; + libName = "lexical_write_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6428,6 +5922,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ii4hmvqrg6pd4j9y1pkhkp0nw2wpivjzmljh6v6ca22yk8z7dp1"; + libName = "lexical_write_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6456,9 +5951,9 @@ rec { }; "libc" = rec { crateName = "libc"; - version = "0.2.152"; + version = "0.2.158"; edition = "2015"; - sha256 = "1rsnma7hnw22w7jh9yqg43slddvfbnfzrvm3s7s4kinbj1jvzqqk"; + sha256 = "0fb4qldw1jrxljrwz6bsjn8lv4rqizlqmab41q3j98q332xw9bfq"; authors = [ "The Rust Project Developers" ]; @@ -6490,6 +5985,7 @@ rec { edition = "2018"; links = "mimalloc"; sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; authors = [ "Octavian Oncescu <octavonce@gmail.com>" ]; @@ -6521,7 +6017,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "libc"; @@ -6540,9 +6036,10 @@ rec { }; "linux-raw-sys" = rec { crateName = "linux-raw-sys"; - version = "0.4.13"; + version = "0.4.14"; edition = "2021"; - sha256 = "172k2c6422gsc914ig8rh99mb9yc7siw6ikc3d9xw1k7vx0s3k81"; + sha256 = "12gsjgbhhjwywpqcrizv80vrp7p7grsz5laqq773i33wphjsxcvq"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -6661,9 +6158,9 @@ rec { }; "lru" = rec { crateName = "lru"; - version = "0.12.3"; + version = "0.12.4"; edition = "2015"; - sha256 = "1p5hryc967wdh56q9wzb2x9gdqy3yd0sqmnb2fcf7z28wrsjw9nk"; + sha256 = "017rzh4kyl3j79sj0qc35wallblsqbnkzxpn6i3xkrv02y4kkvip"; authors = [ "Jerome Froelich <jeromefroelic@hotmail.com>" ]; @@ -6687,6 +6184,7 @@ rec { edition = "2018"; links = "lzma"; sha256 = "09sxp20waxyglgn3cjz8qjkspb3ryz2fwx4rigkwvrk46ymh9njz"; + libName = "lzma_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -6724,7 +6222,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "libc"; @@ -6748,6 +6246,7 @@ rec { edition = "2015"; links = "magic"; sha256 = "1g5k9d9igxv4h23nbhp8bqa5gdpkd3ahgm0rh5i0s54mi3h6my7g"; + libName = "magic_sys"; authors = [ "robo9k <robo9k@symlink.io>" ]; @@ -6952,6 +6451,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -6987,7 +6487,7 @@ rec { }; resolvedDefaultFeatures = [ "with-alloc" ]; }; - "mio" = rec { + "mio 0.8.11" = rec { crateName = "mio"; version = "0.8.11"; edition = "2018"; @@ -7030,7 +6530,53 @@ rec { "log" = [ "dep:log" ]; "os-ext" = [ "os-poll" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_Security" ]; }; - resolvedDefaultFeatures = [ "default" "log" "net" "os-ext" "os-poll" ]; + resolvedDefaultFeatures = [ "default" "log" "os-ext" "os-poll" ]; + }; + "mio 1.0.2" = rec { + crateName = "mio"; + version = "1.0.2"; + edition = "2021"; + sha256 = "1v1cnnn44awxbcfm4zlavwgkvbyg7gp5zzjm8mqf1apkrwflvq40"; + authors = [ + "Carl Lerche <me@carllerche.com>" + "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "hermit-abi"; + packageId = "hermit-abi"; + rename = "libc"; + target = { target, features }: ("hermit" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "libc"; + packageId = "libc"; + target = { target, features }: (target."unix" or false); + } + { + name = "wasi"; + packageId = "wasi"; + target = { target, features }: ("wasi" == target."os" or null); + } + { + name = "windows-sys"; + packageId = "windows-sys 0.52.0"; + target = { target, features }: (target."windows" or false); + features = [ "Wdk_Foundation" "Wdk_Storage_FileSystem" "Wdk_System_IO" "Win32_Foundation" "Win32_Networking_WinSock" "Win32_Storage_FileSystem" "Win32_System_IO" "Win32_System_WindowsProgramming" ]; + } + ]; + features = { + "default" = [ "log" ]; + "log" = [ "dep:log" ]; + "os-ext" = [ "os-poll" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_Security" ]; + }; + resolvedDefaultFeatures = [ "net" "os-ext" "os-poll" ]; }; "multimap" = rec { crateName = "multimap"; @@ -7058,10 +6604,11 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./nar-bridge; }; + libName = "nar_bridge"; dependencies = [ { name = "axum"; - packageId = "axum 0.7.5"; + packageId = "axum"; features = [ "http2" ]; } { @@ -7083,7 +6630,7 @@ rec { } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; } { name = "lru"; @@ -7104,7 +6651,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "serde"; @@ -7131,7 +6678,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; features = [ "tls" "tls-roots" ]; } { @@ -7172,11 +6719,11 @@ rec { buildDependencies = [ { name = "prost-build"; - packageId = "prost-build 0.13.1"; + packageId = "prost-build"; } { name = "tonic-build"; - packageId = "tonic-build 0.12.1"; + packageId = "tonic-build"; } ]; devDependencies = [ @@ -7358,7 +6905,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "cfg-if"; @@ -7400,10 +6947,11 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "bstr"; @@ -7411,6 +6959,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -7435,6 +6988,11 @@ rec { packageId = "mimalloc"; } { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + optional = true; + } + { name = "nom"; packageId = "nom"; } @@ -7470,6 +7028,10 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { @@ -7480,8 +7042,6 @@ rec { { name = "futures"; packageId = "futures"; - usesDefaultFeatures = false; - features = [ "executor" ]; } { name = "hex-literal"; @@ -7508,6 +7068,10 @@ rec { packageId = "serde_json"; } { + name = "smol_str"; + packageId = "smol_str"; + } + { name = "tokio-test"; packageId = "tokio-test"; } @@ -7518,12 +7082,127 @@ rec { ]; features = { "async" = [ "tokio" ]; - "default" = [ "async" "wire" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" "nix-compat-derive" ]; + "nix-compat-derive" = [ "dep:nix-compat-derive" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "async" "default" "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "nix-compat-derive" "pin-project-lite" "test" "tokio" "wire" ]; + }; + "nix-compat-derive" = rec { + crateName = "nix-compat-derive"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat-derive; }; + procMacro = true; + libName = "nix_compat_derive"; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + features = [ "proc-macro" ]; + } + { + name = "quote"; + packageId = "quote"; + features = [ "proc-macro" ]; + } + { + name = "syn"; + packageId = "syn 2.0.76"; + features = [ "full" "extra-traits" ]; + } + ]; + devDependencies = [ + { + name = "hex-literal"; + packageId = "hex-literal"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + usesDefaultFeatures = false; + features = [ "async" "wire" "test" ]; + } + { + name = "pretty_assertions"; + packageId = "pretty_assertions"; + } + { + name = "rstest"; + packageId = "rstest"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-util" "macros" ]; + } + { + name = "tokio-test"; + packageId = "tokio-test"; + } + ]; + + }; + "nix-compat-derive-tests" = rec { + crateName = "nix-compat-derive-tests"; + version = "0.1.0"; + edition = "2021"; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./nix-compat-derive-tests; }; + devDependencies = [ + { + name = "hex-literal"; + packageId = "hex-literal"; + } + { + name = "nix-compat"; + packageId = "nix-compat"; + features = [ "test" "wire" ]; + } + { + name = "nix-compat-derive"; + packageId = "nix-compat-derive"; + } + { + name = "pretty_assertions"; + packageId = "pretty_assertions"; + } + { + name = "rstest"; + packageId = "rstest"; + } + { + name = "tokio"; + packageId = "tokio"; + features = [ "io-util" "macros" ]; + } + { + name = "tokio-test"; + packageId = "tokio-test"; + } + { + name = "trybuild"; + packageId = "trybuild"; + } + ]; + features = { }; + resolvedDefaultFeatures = [ "compile-tests" ]; + }; + "nohash-hasher" = rec { + crateName = "nohash-hasher"; + version = "0.2.0"; + edition = "2018"; + sha256 = "0lf4p6k01w4wm7zn4grnihzj8s7zd5qczjmzng7wviwxawih5x9b"; + libName = "nohash_hasher"; + authors = [ + "Parity Technologies <admin@parity.io>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; }; "nom" = rec { crateName = "nom"; @@ -7575,6 +7254,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -7603,6 +7283,7 @@ rec { version = "0.1.0"; edition = "2021"; sha256 = "1ndiyg82q73783jq18isi71a7mjh56wxrk52rlvyx0mi5z9ibmai"; + libName = "num_conv"; authors = [ "Jacob Pratt <jacob@jhpratt.dev>" ]; @@ -7610,9 +7291,10 @@ rec { }; "num-traits" = rec { crateName = "num-traits"; - version = "0.2.18"; - edition = "2018"; - sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + version = "0.2.19"; + edition = "2021"; + sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -7704,9 +7386,9 @@ rec { }; "object_store" = rec { crateName = "object_store"; - version = "0.10.1"; + version = "0.10.2"; edition = "2021"; - sha256 = "1mkag13fnzcgn52smi9h7ssf53as04w9373sz83ikfhkq8rgvszv"; + sha256 = "1wz3m20hqs3v93dyxcqy7qpsbd4rqp6050hy49wcw5f740l4bnp6"; dependencies = [ { name = "async-trait"; @@ -7739,13 +7421,13 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; optional = true; usesDefaultFeatures = false; } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.13.0"; } { name = "md-5"; @@ -7790,7 +7472,7 @@ rec { } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; @@ -7833,7 +7515,7 @@ rec { devDependencies = [ { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; features = [ "server" ]; } { @@ -7895,6 +7577,7 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -7995,6 +7678,7 @@ rec { version = "0.13.0"; edition = "2021"; sha256 = "1avqmyh42apakbkhjij3c9hl0brnq5v37zk4kpxkhdgf8kgfjcdd"; + libName = "opentelemetry_http"; dependencies = [ { name = "async-trait"; @@ -8006,7 +7690,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; usesDefaultFeatures = false; features = [ "std" ]; } @@ -8028,6 +7712,7 @@ rec { version = "0.17.0"; edition = "2021"; sha256 = "09z70ygp6lfcplnwx7cgf3p3fyq2arkvhxhj8avnz4gv5xh5m4kb"; + libName = "opentelemetry_otlp"; dependencies = [ { name = "async-trait"; @@ -8039,7 +7724,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; @@ -8061,7 +7746,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; optional = true; } { @@ -8078,7 +7763,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; optional = true; usesDefaultFeatures = false; } @@ -8125,6 +7810,7 @@ rec { version = "0.7.0"; edition = "2021"; sha256 = "1nahv1dflvwdgi4c4p7ikd59x0yyivf85w02398q9jgrpwh9zvih"; + libName = "opentelemetry_proto"; dependencies = [ { name = "opentelemetry"; @@ -8138,12 +7824,12 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; optional = true; } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; optional = true; usesDefaultFeatures = false; features = [ "codegen" "prost" ]; @@ -8372,6 +8058,7 @@ rec { version = "4.2.0"; edition = "2021"; sha256 = "0kjqcvvbcsibbx3hnj7ag06bd9gv2zfi5ja6rgyh2kbxbh3zfvd7"; + libName = "ordered_float"; authors = [ "Jonathan Reem <jonathan.reem@gmail.com>" "Matt Brubeck <mbrubeck@limpet.net>" @@ -8600,6 +8287,7 @@ rec { version = "0.1.0"; edition = "2015"; sha256 = "1pcgqxw0mgg3ha5hi5xkjhyjf488bw5rw1g3qlr9awbq4szh3fpc"; + libName = "path_clean"; authors = [ "Dan Reeves <hey@danreev.es>" ]; @@ -8610,6 +8298,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -8621,9 +8310,9 @@ rec { }; "petgraph" = rec { crateName = "petgraph"; - version = "0.6.4"; + version = "0.6.5"; edition = "2018"; - sha256 = "1ac6wfq5f5pzcv0nvzzfgjbwg2kwslpnzsw5wcmxlscfcb9azlz1"; + sha256 = "1ns7mbxidnn2pqahbbjccxkrqkrll2i5rbxx43ns6rh6fn3cridl"; authors = [ "bluss" "mitchmindtree" @@ -8640,9 +8329,10 @@ rec { } ]; features = { - "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" ]; + "all" = [ "unstable" "quickcheck" "matrix_graph" "stable_graph" "graphmap" "rayon" ]; "default" = [ "graphmap" "stable_graph" "matrix_graph" ]; "quickcheck" = [ "dep:quickcheck" ]; + "rayon" = [ "dep:rayon" "indexmap/rayon" ]; "serde" = [ "dep:serde" ]; "serde-1" = [ "serde" "serde_derive" ]; "serde_derive" = [ "dep:serde_derive" ]; @@ -8655,6 +8345,7 @@ rec { version = "1.1.3"; edition = "2021"; sha256 = "08k4cpy8q3j93qqgnrbzkcgpn7g0a88l4a9nm33kyghpdhffv97x"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -8669,6 +8360,7 @@ rec { edition = "2021"; sha256 = "01a4l3vb84brv9v7wl71chzxra2kynm6yvcjca66xv3ij6fgsna3"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -8680,7 +8372,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "visit-mut" ]; } ]; @@ -8688,9 +8380,10 @@ rec { }; "pin-project-lite" = rec { crateName = "pin-project-lite"; - version = "0.2.13"; + version = "0.2.14"; edition = "2018"; - sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -8698,6 +8391,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -8777,6 +8471,7 @@ rec { version = "0.3.29"; edition = "2015"; sha256 = "1jy6158v1316khkpmq2sjj1vgbnbnw51wffx7p0k0l9h9vlys019"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -8862,6 +8557,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "02cn98gsj2i1bwrfsymifmyas1wn2gibdm9mk8w82x9s9n5n4xly"; + libName = "plotters_backend"; authors = [ "Hao Hou <haohou302@gmail.com>" ]; @@ -8872,6 +8568,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "1axbw82frs5di4drbyzihr5j35wpy2a75hp3f49p186cjfcd7xiq"; + libName = "plotters_svg"; authors = [ "Hao Hou <haohou302@gmail.com>" ]; @@ -8936,6 +8633,7 @@ rec { version = "1.6.0"; edition = "2018"; sha256 = "1h77x9qx7pns0d66vdrmdbmwpi7586h7ysnkdnhrn5mwi2cyyw3i"; + libName = "portable_atomic"; features = { "critical-section" = [ "dep:critical-section" ]; "default" = [ "fallback" ]; @@ -8962,6 +8660,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; @@ -9012,7 +8711,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; usesDefaultFeatures = false; features = [ "full" ]; } @@ -9025,7 +8724,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; usesDefaultFeatures = false; features = [ "parsing" ]; } @@ -9036,9 +8735,10 @@ rec { }; "proc-macro2" = rec { crateName = "proc-macro2"; - version = "1.0.76"; + version = "1.0.86"; edition = "2021"; - sha256 = "136cp0fgl6rg5ljm3b1xpc0bn0lyvagzzmxvbxgk5hxml36mdz4m"; + sha256 = "0xrv22p8lqlfdf1w0pj4si8n2ws4aw0kilmziwf0vpv5ys6rwway"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -9056,26 +8756,16 @@ rec { }; "proptest" = rec { crateName = "proptest"; - version = "1.4.0"; + version = "1.5.0"; edition = "2018"; - sha256 = "1gzmw40pgmwzb7x6jsyr88z5w151snv5rp1g0dlcp1iw3h9pdd1i"; + sha256 = "13gm7mphs95cw4gbgk5qiczkmr68dvcwhp58gmiz33dq2ccm3hml"; authors = [ "Jason Lingle" ]; dependencies = [ { - name = "bit-set"; - packageId = "bit-set"; - optional = true; - } - { - name = "bit-vec"; - packageId = "bit-vec"; - optional = true; - } - { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "lazy_static"; @@ -9109,12 +8799,6 @@ rec { optional = true; } { - name = "rusty-fork"; - packageId = "rusty-fork"; - optional = true; - usesDefaultFeatures = false; - } - { name = "tempfile"; packageId = "tempfile"; optional = true; @@ -9125,12 +8809,14 @@ rec { } ]; features = { + "attr-macro" = [ "proptest-macro" ]; "bit-set" = [ "dep:bit-set" "dep:bit-vec" ]; "default" = [ "std" "fork" "timeout" "bit-set" ]; "default-code-coverage" = [ "std" "fork" "timeout" "bit-set" ]; "fork" = [ "std" "rusty-fork" "tempfile" ]; "hardware-rng" = [ "x86" ]; "lazy_static" = [ "dep:lazy_static" ]; + "proptest-macro" = [ "dep:proptest-macro" ]; "regex-syntax" = [ "dep:regex-syntax" ]; "rusty-fork" = [ "dep:rusty-fork" ]; "std" = [ "rand/std" "lazy_static" "regex-syntax" "num-traits/std" ]; @@ -9138,37 +8824,9 @@ rec { "timeout" = [ "fork" "rusty-fork/timeout" ]; "x86" = [ "dep:x86" ]; }; - resolvedDefaultFeatures = [ "alloc" "bit-set" "default" "fork" "lazy_static" "regex-syntax" "rusty-fork" "std" "tempfile" "timeout" ]; - }; - "prost 0.12.3" = rec { - crateName = "prost"; - version = "0.12.3"; - edition = "2021"; - sha256 = "0jmrhlb4jkiylz72xb14vlkfbmlq0jwv7j20ini9harhvaf2hv0l"; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - usesDefaultFeatures = false; - } - { - name = "prost-derive"; - packageId = "prost-derive 0.12.3"; - optional = true; - } - ]; - features = { - "default" = [ "prost-derive" "std" ]; - "prost-derive" = [ "dep:prost-derive" ]; - }; - resolvedDefaultFeatures = [ "default" "prost-derive" "std" ]; + resolvedDefaultFeatures = [ "alloc" "lazy_static" "regex-syntax" "std" "tempfile" ]; }; - "prost 0.13.1" = rec { + "prost" = rec { crateName = "prost"; version = "0.13.1"; edition = "2021"; @@ -9187,7 +8845,7 @@ rec { } { name = "prost-derive"; - packageId = "prost-derive 0.13.1"; + packageId = "prost-derive"; optional = true; } ]; @@ -9198,14 +8856,16 @@ rec { }; resolvedDefaultFeatures = [ "default" "derive" "prost-derive" "std" ]; }; - "prost-build 0.12.3" = rec { + "prost-build" = rec { crateName = "prost-build"; - version = "0.12.3"; + version = "0.13.1"; edition = "2021"; - sha256 = "1lp2l1l65l163yggk9nw5mjb2fqwzz12693af5phn1v0abih4pn5"; + sha256 = "1hbp7cam99q56qf2wp8inwfh59adkzgf676hi07hgpbi1xc85cav"; + libName = "prost_build"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" + "Casper Meijn <casper@meijn.net>" "Tokio Contributors <team@tokio.rs>" ]; dependencies = [ @@ -9216,11 +8876,11 @@ rec { } { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; } { name = "itertools"; - packageId = "itertools 0.11.0"; + packageId = "itertools 0.10.5"; usesDefaultFeatures = false; features = [ "use_alloc" ]; } @@ -9249,12 +8909,12 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; usesDefaultFeatures = false; } { name = "prost-types"; - packageId = "prost-types 0.12.3"; + packageId = "prost-types"; usesDefaultFeatures = false; } { @@ -9276,99 +8936,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; - optional = true; - features = [ "full" ]; - } - { - name = "tempfile"; - packageId = "tempfile"; - } - { - name = "which"; - packageId = "which 4.4.2"; - } - ]; - features = { - "cleanup-markdown" = [ "pulldown-cmark" "pulldown-cmark-to-cmark" ]; - "default" = [ "format" ]; - "format" = [ "prettyplease" "syn" ]; - "prettyplease" = [ "dep:prettyplease" ]; - "pulldown-cmark" = [ "dep:pulldown-cmark" ]; - "pulldown-cmark-to-cmark" = [ "dep:pulldown-cmark-to-cmark" ]; - "syn" = [ "dep:syn" ]; - }; - resolvedDefaultFeatures = [ "cleanup-markdown" "default" "format" "prettyplease" "pulldown-cmark" "pulldown-cmark-to-cmark" "syn" ]; - }; - "prost-build 0.13.1" = rec { - crateName = "prost-build"; - version = "0.13.1"; - edition = "2021"; - sha256 = "1hbp7cam99q56qf2wp8inwfh59adkzgf676hi07hgpbi1xc85cav"; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com>" - "Casper Meijn <casper@meijn.net>" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "bytes"; - packageId = "bytes"; - usesDefaultFeatures = false; - } - { - name = "heck"; - packageId = "heck"; - } - { - name = "itertools"; - packageId = "itertools 0.12.0"; - usesDefaultFeatures = false; - features = [ "use_alloc" ]; - } - { - name = "log"; - packageId = "log"; - } - { - name = "multimap"; - packageId = "multimap"; - usesDefaultFeatures = false; - } - { - name = "once_cell"; - packageId = "once_cell"; - } - { - name = "petgraph"; - packageId = "petgraph"; - usesDefaultFeatures = false; - } - { - name = "prettyplease"; - packageId = "prettyplease"; - optional = true; - } - { - name = "prost"; - packageId = "prost 0.13.1"; - usesDefaultFeatures = false; - } - { - name = "prost-types"; - packageId = "prost-types 0.13.1"; - usesDefaultFeatures = false; - } - { - name = "regex"; - packageId = "regex"; - usesDefaultFeatures = false; - features = [ "std" "unicode-bool" ]; - } - { - name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; optional = true; features = [ "full" ]; } @@ -9382,52 +8950,15 @@ rec { "default" = [ "format" ]; "format" = [ "dep:prettyplease" "dep:syn" ]; }; - resolvedDefaultFeatures = [ "default" "format" ]; - }; - "prost-derive 0.12.3" = rec { - crateName = "prost-derive"; - version = "0.12.3"; - edition = "2021"; - sha256 = "03l4yf6pdjvc4sgbvln2srq1avzm1ai86zni4hhqxvqxvnhwkdpg"; - procMacro = true; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com>" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "anyhow"; - packageId = "anyhow"; - } - { - name = "itertools"; - packageId = "itertools 0.11.0"; - usesDefaultFeatures = false; - features = [ "use_alloc" ]; - } - { - name = "proc-macro2"; - packageId = "proc-macro2"; - } - { - name = "quote"; - packageId = "quote"; - } - { - name = "syn"; - packageId = "syn 2.0.48"; - features = [ "extra-traits" ]; - } - ]; - + resolvedDefaultFeatures = [ "cleanup-markdown" "default" "format" ]; }; - "prost-derive 0.13.1" = rec { + "prost-derive" = rec { crateName = "prost-derive"; version = "0.13.1"; edition = "2021"; sha256 = "1jng0kwkwiih777f77kn6ja7hdvi7sxbg11nndwagsy4mnqckghq"; procMacro = true; + libName = "prost_derive"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -9441,7 +8972,7 @@ rec { } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.10.5"; } { name = "proc-macro2"; @@ -9453,41 +8984,18 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "extra-traits" ]; } ]; }; - "prost-types 0.12.3" = rec { - crateName = "prost-types"; - version = "0.12.3"; - edition = "2021"; - sha256 = "03j73llzljdxv9cdxp4m3vb9j3gh4y24rkbx48k3rx6wkvsrhf0r"; - authors = [ - "Dan Burkert <dan@danburkert.com>" - "Lucio Franco <luciofranco14@gmail.com" - "Tokio Contributors <team@tokio.rs>" - ]; - dependencies = [ - { - name = "prost"; - packageId = "prost 0.12.3"; - usesDefaultFeatures = false; - features = [ "prost-derive" ]; - } - ]; - features = { - "default" = [ "std" ]; - "std" = [ "prost/std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; - "prost-types 0.13.1" = rec { + "prost-types" = rec { crateName = "prost-types"; version = "0.13.1"; edition = "2021"; sha256 = "1hjww9k35c4fqjd75ziyjvyzl8kv9aqnw841ll64p7gl0n5idrff"; + libName = "prost_types"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -9497,7 +9005,7 @@ rec { dependencies = [ { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; usesDefaultFeatures = false; features = [ "prost-derive" ]; } @@ -9510,9 +9018,10 @@ rec { }; "prost-wkt" = rec { crateName = "prost-wkt"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "0h3c0jyfpg7f3s9a3mx6xcif28j3ir5c5qmps88bknpiy31zk3jd"; + sha256 = "16c2mbaq2hff51kwr204fncnmi0qx2zz4ff3pb1086qqxqmlxn58"; + libName = "prost_wkt"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; @@ -9529,7 +9038,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "serde"; @@ -9552,28 +9061,29 @@ rec { }; "prost-wkt-build" = rec { crateName = "prost-wkt-build"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "0883g26vrhx07kv0dq85559pj95zxs10lx042pp4za2clplwlcav"; + sha256 = "054v5qqvdv29g5s1kr26zv0yvzc8gmnlx9k2dw6026g7rdd9srla"; + libName = "prost_wkt_build"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-build"; - packageId = "prost-build 0.12.3"; + packageId = "prost-build"; } { name = "prost-types"; - packageId = "prost-types 0.12.3"; + packageId = "prost-types"; } { name = "quote"; @@ -9584,9 +9094,10 @@ rec { }; "prost-wkt-types" = rec { crateName = "prost-wkt-types"; - version = "0.5.0"; + version = "0.6.0"; edition = "2021"; - sha256 = "1vipmgvqqzr3hn9z5v85mx9zznzjwyfpjy8xzg2v94a0f2lf8ns3"; + sha256 = "0r2gxf5b604b00v1fwif1rn5nm5xk4vb3ri29dhm9rl2kf70dvq1"; + libName = "prost_wkt_types"; authors = [ "fdeantoni <fdeantoni@gmail.com>" ]; @@ -9599,7 +9110,7 @@ rec { } { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-wkt"; @@ -9621,15 +9132,15 @@ rec { buildDependencies = [ { name = "prost"; - packageId = "prost 0.12.3"; + packageId = "prost"; } { name = "prost-build"; - packageId = "prost-build 0.12.3"; + packageId = "prost-build"; } { name = "prost-types"; - packageId = "prost-types 0.12.3"; + packageId = "prost-types"; } { name = "prost-wkt-build"; @@ -9655,6 +9166,7 @@ rec { edition = "2021"; crateBin = [ ]; sha256 = "0av876a31qvqhy7gzdg134zn4s10smlyi744mz9vrllkf906n82p"; + libName = "pulldown_cmark"; authors = [ "Raph Levien <raph.levien@gmail.com>" "Marcus Klaas de Vries <mail@marcusklaas.nl>" @@ -9662,7 +9174,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "memchr"; @@ -9684,6 +9196,7 @@ rec { version = "10.0.4"; edition = "2018"; sha256 = "0gc366cmd5jxal9m95l17rvqsm4dn62lywc8v5gwq8vcjvhyd501"; + libName = "pulldown_cmark_to_cmark"; authors = [ "Sebastian Thiel <byronimo@gmail.com>" "Dylan Owen <dyltotheo@gmail.com>" @@ -9699,22 +9212,12 @@ rec { ]; }; - "quick-error" = rec { - crateName = "quick-error"; - version = "1.2.3"; - edition = "2015"; - sha256 = "1q6za3v78hsspisc197bg3g7rpc989qycy8ypr8ap8igv10ikl51"; - authors = [ - "Paul Colomiets <paul@colomiets.name>" - "Colin Kiegel <kiegel@gmx.de>" - ]; - - }; "quick-xml" = rec { crateName = "quick-xml"; - version = "0.31.0"; + version = "0.36.1"; edition = "2021"; - sha256 = "0cravqanylzh5cq2v6hzlfqgxcid5nrp2snnb3pf4m0and2a610h"; + sha256 = "1g0p8h4hxz2ymiyd71mn862nrj7s0g1wwiyahhdabpzxiqp5x84n"; + libName = "quick_xml"; dependencies = [ { name = "memchr"; @@ -9771,7 +9274,7 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; optional = true; usesDefaultFeatures = false; features = [ "ring" "std" ]; @@ -9818,6 +9321,7 @@ rec { version = "0.11.3"; edition = "2021"; sha256 = "1zhfcj6fffdgkqdhxzlr18hqmpwqshwbx9280h8bi78h7b01gxfx"; + libName = "quinn_proto"; dependencies = [ { name = "bytes"; @@ -9838,7 +9342,7 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; optional = true; usesDefaultFeatures = false; features = [ "ring" "std" ]; @@ -9876,6 +9380,7 @@ rec { version = "0.5.2"; edition = "2021"; sha256 = "0ilcrwrah36nqxh329p31ghj3rxm4sw5w4iy2kxwf3w68nf655lh"; + libName = "quinn_udp"; dependencies = [ { name = "libc"; @@ -9908,9 +9413,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.35"; + version = "1.0.37"; edition = "2018"; - sha256 = "1vv8r2ncaz4pqdr78x7f138ka595sp2ncr1sa2plm4zxbsmwj7i9"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -10067,25 +9572,6 @@ rec { "serde1" = [ "serde" ]; }; }; - "rand_xoshiro" = rec { - crateName = "rand_xoshiro"; - version = "0.6.0"; - edition = "2018"; - sha256 = "1ajsic84rzwz5qr0mzlay8vi17swqi684bqvwqyiim3flfrcv5vg"; - authors = [ - "The Rand Project Developers" - ]; - dependencies = [ - { - name = "rand_core"; - packageId = "rand_core"; - } - ]; - features = { - "serde" = [ "dep:serde" ]; - "serde1" = [ "serde" ]; - }; - }; "rayon" = rec { crateName = "rayon"; version = "1.8.1"; @@ -10116,6 +9602,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -10136,12 +9623,12 @@ rec { }; "redb" = rec { crateName = "redb"; - version = "2.1.1"; + version = "2.1.2"; edition = "2021"; - sha256 = "1h68d2gqq4vpwiyfpyq9ag0swxavnf9npcd0cqipv77brp9j1pd6"; + sha256 = "1r8z96z3rnv3m80k9fikflq0dnf5c02br57z0phqlam55v1kscjq"; type = [ "cdylib" "rlib" ]; authors = [ - "Christopher Berner <christopherberner@gmail.com>" + "Christopher Berner <me@cberner.com>" ]; dependencies = [ { @@ -10158,11 +9645,8 @@ rec { } ]; features = { - "log" = [ "dep:log" ]; - "logging" = [ "log" ]; - "pyo3" = [ "dep:pyo3" ]; - "pyo3-build-config" = [ "dep:pyo3-build-config" ]; - "python" = [ "pyo3" "pyo3-build-config" ]; + "logging" = [ "dep:log" ]; + "python" = [ "dep:pyo3" "dep:pyo3-build-config" ]; }; }; "redox_syscall 0.2.16" = rec { @@ -10257,9 +9741,9 @@ rec { }; "regex" = rec { crateName = "regex"; - version = "1.10.2"; + version = "1.10.6"; edition = "2021"; - sha256 = "0hxkd814n4irind8im5c9am221ri6bprx49nc7yxv02ykhd9a2rq"; + sha256 = "06cnlxwzyqfbw1za1i7ks89ns4i2kr0lpg5ykx56b8v7dd6df6a2"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -10269,15 +9753,17 @@ rec { name = "aho-corasick"; packageId = "aho-corasick"; optional = true; + usesDefaultFeatures = false; } { name = "memchr"; packageId = "memchr"; optional = true; + usesDefaultFeatures = false; } { name = "regex-automata"; - packageId = "regex-automata 0.4.3"; + packageId = "regex-automata 0.4.7"; usesDefaultFeatures = false; features = [ "alloc" "syntax" "meta" "nfa-pikevm" ]; } @@ -10316,6 +9802,7 @@ rec { version = "0.1.10"; edition = "2015"; sha256 = "0ci1hvbzhrfby5fdpf4ganhf7kla58acad9i1ff1p34dzdrhs8vc"; + libName = "regex_automata"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -10335,11 +9822,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "regex-syntax" "std" ]; }; - "regex-automata 0.4.3" = rec { + "regex-automata 0.4.7" = rec { crateName = "regex-automata"; - version = "0.4.3"; + version = "0.4.7"; edition = "2021"; - sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + sha256 = "1pwjdi4jckpbaivpl6x4v5g4crb37zr2wac93wlfsbzgqn6gbjiq"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -10400,6 +9888,7 @@ rec { version = "0.6.29"; edition = "2018"; sha256 = "1qgj49vm6y3zn1hi09x91jvgkl2b1fiaq402skj83280ggfwcqpi"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" ]; @@ -10414,6 +9903,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -10430,6 +9920,7 @@ rec { version = "1.9.2"; edition = "2021"; sha256 = "1g0gc604zwm73gvpcicn8si25j9j5agqz50r0x1bkmgx6f7mi678"; + libName = "relative_path"; authors = [ "John-John Tedro <udoprog@tedro.se>" ]; @@ -10440,9 +9931,9 @@ rec { }; "reqwest" = rec { crateName = "reqwest"; - version = "0.12.5"; + version = "0.12.7"; edition = "2021"; - sha256 = "0dva5mx1cli19adc9igc81ix4si7yiri24ayxdw8652pgnid5mn7"; + sha256 = "0qsymmmgam6whjcymnlpf5kvk3ylc4bs92lygz63hp7g95b9bx7q"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -10467,17 +9958,17 @@ rec { } { name = "h2"; - packageId = "h2 0.4.4"; + packageId = "h2"; optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; target = { target, features }: (!("wasm32" == target."arch" or null)); } { @@ -10487,13 +9978,13 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; target = { target, features }: (!("wasm32" == target."arch" or null)); features = [ "http1" "client" ]; } { name = "hyper-rustls"; - packageId = "hyper-rustls 0.27.2"; + packageId = "hyper-rustls"; optional = true; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); @@ -10550,7 +10041,7 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; optional = true; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); @@ -10558,13 +10049,13 @@ rec { } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.7.0"; + packageId = "rustls-native-certs"; optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; optional = true; target = { target, features }: (!("wasm32" == target."arch" or null)); } @@ -10596,6 +10087,7 @@ rec { { name = "sync_wrapper"; packageId = "sync_wrapper 1.0.1"; + features = [ "futures" ]; } { name = "tokio"; @@ -10606,7 +10098,7 @@ rec { } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.26.0"; + packageId = "tokio-rustls"; optional = true; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); @@ -10651,8 +10143,8 @@ rec { features = [ "AbortController" "AbortSignal" "Headers" "Request" "RequestInit" "RequestMode" "Response" "Window" "FormData" "Blob" "BlobPropertyBag" "ServiceWorkerGlobalScope" "RequestCredentials" "File" "ReadableStream" ]; } { - name = "winreg"; - packageId = "winreg"; + name = "windows-registry"; + packageId = "windows-registry"; target = { target, features }: (target."windows" or false); } ]; @@ -10666,7 +10158,7 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); features = [ "http1" "http2" "client" "server" ]; @@ -10679,7 +10171,7 @@ rec { } { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; usesDefaultFeatures = false; target = { target, features }: (!("wasm32" == target."arch" or null)); features = [ "ring" ]; @@ -10740,9 +10232,10 @@ rec { }; "reqwest-middleware" = rec { crateName = "reqwest-middleware"; - version = "0.3.2"; + version = "0.3.3"; edition = "2018"; - sha256 = "0s0jrbn3ns8l07qjjwmq62r9g2w1jvllr8qpph6f0szyvlrnld1r"; + sha256 = "011b8n9a1bwalyk2y6x5s0wz52pxk70l4bbrba47qgsdc1dfnb2n"; + libName = "reqwest_middleware"; authors = [ "Rodrigo Gryzinski <rodrigo.gryzinski@truelayer.com>" ]; @@ -10757,7 +10250,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "reqwest"; @@ -10777,6 +10270,13 @@ rec { packageId = "tower-service"; } ]; + devDependencies = [ + { + name = "reqwest"; + packageId = "reqwest"; + features = [ "rustls-tls" ]; + } + ]; features = { "charset" = [ "reqwest/charset" ]; "http2" = [ "reqwest/http2" ]; @@ -10787,9 +10287,9 @@ rec { }; "reqwest-tracing" = rec { crateName = "reqwest-tracing"; - version = "0.5.2"; + version = "0.5.3"; edition = "2018"; - sha256 = "0vg7vfdsh3c15xawpy08z0576s5pkrkjmmkq0bdhy8fw0nnxqiaf"; + sha256 = "0igb5hp1mdr8jb5qwj26dphykvydxy1piawrvpc368n7ckx9ppdz"; libName = "reqwest_tracing"; authors = [ "Rodrigo Gryzinski <rodrigo.gryzinski@truelayer.com>" @@ -10811,7 +10311,7 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "matchit"; @@ -10859,10 +10359,13 @@ rec { "opentelemetry_0_22_pkg" = [ "dep:opentelemetry_0_22_pkg" ]; "opentelemetry_0_23" = [ "opentelemetry_0_23_pkg" "tracing-opentelemetry_0_24_pkg" ]; "opentelemetry_0_23_pkg" = [ "dep:opentelemetry_0_23_pkg" ]; + "opentelemetry_0_24" = [ "opentelemetry_0_24_pkg" "tracing-opentelemetry_0_25_pkg" ]; + "opentelemetry_0_24_pkg" = [ "dep:opentelemetry_0_24_pkg" ]; "tracing-opentelemetry_0_21_pkg" = [ "dep:tracing-opentelemetry_0_21_pkg" ]; "tracing-opentelemetry_0_22_pkg" = [ "dep:tracing-opentelemetry_0_22_pkg" ]; "tracing-opentelemetry_0_23_pkg" = [ "dep:tracing-opentelemetry_0_23_pkg" ]; "tracing-opentelemetry_0_24_pkg" = [ "dep:tracing-opentelemetry_0_24_pkg" ]; + "tracing-opentelemetry_0_25_pkg" = [ "dep:tracing-opentelemetry_0_25_pkg" ]; }; resolvedDefaultFeatures = [ "opentelemetry_0_22" "opentelemetry_0_22_pkg" "tracing-opentelemetry_0_23_pkg" ]; }; @@ -11052,7 +10555,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "parsing" "extra-traits" "visit" "visit-mut" ]; } { @@ -11091,7 +10594,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" "extra-traits" ]; } ]; @@ -11108,6 +10611,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -11122,6 +10626,7 @@ rec { version = "1.1.0"; edition = "2015"; sha256 = "1qkc5khrmv5pqi5l5ca9p5nl5hs742cagrndhbrlk3dhlrx3zm08"; + libName = "rustc_hash"; authors = [ "The Rust Project Developers" ]; @@ -11135,6 +10640,7 @@ rec { version = "2.0.0"; edition = "2021"; sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q"; + libName = "rustc_hash"; authors = [ "The Rust Project Developers" ]; @@ -11163,9 +10669,9 @@ rec { }; "rustix" = rec { crateName = "rustix"; - version = "0.38.30"; + version = "0.38.35"; edition = "2021"; - sha256 = "1jkb6bzrj2w9ffy35aw4q04mqk1yxqw35fz80x0c4cxgi9c988rj"; + sha256 = "0vy38cpprg64i6kfwz0w5hj2lqgliyimnx6vmplninir499m0pd8"; authors = [ "Dan Gohman <dev@sunfishcode.online>" "Jakub Konka <kubkon@jakubkonka.com>" @@ -11173,7 +10679,7 @@ rec { dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; usesDefaultFeatures = false; } { @@ -11204,14 +10710,12 @@ rec { optional = true; usesDefaultFeatures = false; target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); - features = [ "extra_traits" ]; } { name = "libc"; packageId = "libc"; usesDefaultFeatures = false; target = { target, features }: ((!(target."windows" or false)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); - features = [ "extra_traits" ]; } { name = "linux-raw-sys"; @@ -11248,10 +10752,13 @@ rec { ]; features = { "all-apis" = [ "event" "fs" "io_uring" "mm" "mount" "net" "param" "pipe" "process" "procfs" "pty" "rand" "runtime" "shm" "stdio" "system" "termios" "thread" "time" ]; + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; "default" = [ "std" "use-libc-auxv" ]; "io_uring" = [ "event" "fs" "net" "linux-raw-sys/io_uring" ]; "itoa" = [ "dep:itoa" ]; "libc" = [ "dep:libc" ]; + "libc-extra-traits" = [ "libc?/extra_traits" ]; "libc_errno" = [ "dep:libc_errno" ]; "linux_latest" = [ "linux_4_11" ]; "net" = [ "linux-raw-sys/net" "linux-raw-sys/netlink" "linux-raw-sys/if_ether" "linux-raw-sys/xdp" ]; @@ -11261,113 +10768,17 @@ rec { "procfs" = [ "once_cell" "itoa" "fs" ]; "pty" = [ "itoa" "fs" ]; "runtime" = [ "linux-raw-sys/prctl" ]; - "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-dep-of-std" = [ "core" "rustc-std-workspace-alloc" "compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "rustc-std-workspace-alloc" = [ "dep:rustc-std-workspace-alloc" ]; "shm" = [ "fs" ]; - "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" ]; + "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" "libc-extra-traits" ]; "system" = [ "linux-raw-sys/system" ]; "thread" = [ "linux-raw-sys/prctl" ]; - "use-libc" = [ "libc_errno" "libc" ]; + "use-libc" = [ "libc_errno" "libc" "libc-extra-traits" ]; }; - resolvedDefaultFeatures = [ "alloc" "default" "event" "fs" "net" "pipe" "process" "std" "termios" "time" "use-libc-auxv" ]; + resolvedDefaultFeatures = [ "alloc" "default" "event" "fs" "libc-extra-traits" "net" "pipe" "process" "std" "termios" "time" "use-libc-auxv" ]; }; - "rustls 0.21.12" = rec { - crateName = "rustls"; - version = "0.21.12"; - edition = "2021"; - sha256 = "0gjdg2a9r81sdwkyw3n5yfbkrr6p9gyk3xr2kcsr3cs83x6s2miz"; - dependencies = [ - { - name = "log"; - packageId = "log"; - optional = true; - } - { - name = "ring"; - packageId = "ring"; - } - { - name = "rustls-webpki"; - packageId = "rustls-webpki 0.101.7"; - rename = "webpki"; - features = [ "alloc" "std" ]; - } - { - name = "sct"; - packageId = "sct"; - } - ]; - devDependencies = [ - { - name = "log"; - packageId = "log"; - } - ]; - features = { - "default" = [ "logging" "tls12" ]; - "log" = [ "dep:log" ]; - "logging" = [ "log" ]; - "read_buf" = [ "rustversion" ]; - "rustversion" = [ "dep:rustversion" ]; - }; - resolvedDefaultFeatures = [ "default" "log" "logging" "tls12" ]; - }; - "rustls 0.22.4" = rec { - crateName = "rustls"; - version = "0.22.4"; - edition = "2021"; - sha256 = "0cl4q6w0x1cl5ldjsgbbiiqhkz6qg5vxl5dkn9wwsyxc44vzfkmz"; - dependencies = [ - { - name = "log"; - packageId = "log"; - optional = true; - } - { - name = "ring"; - packageId = "ring"; - optional = true; - } - { - name = "rustls-pki-types"; - packageId = "rustls-pki-types"; - rename = "pki-types"; - features = [ "std" ]; - } - { - name = "rustls-webpki"; - packageId = "rustls-webpki 0.102.2"; - rename = "webpki"; - usesDefaultFeatures = false; - features = [ "std" ]; - } - { - name = "subtle"; - packageId = "subtle"; - usesDefaultFeatures = false; - } - { - name = "zeroize"; - packageId = "zeroize"; - } - ]; - devDependencies = [ - { - name = "log"; - packageId = "log"; - } - ]; - features = { - "aws_lc_rs" = [ "dep:aws-lc-rs" "webpki/aws_lc_rs" ]; - "default" = [ "logging" "ring" "tls12" ]; - "log" = [ "dep:log" ]; - "logging" = [ "log" ]; - "read_buf" = [ "rustversion" ]; - "ring" = [ "dep:ring" "webpki/ring" ]; - "rustversion" = [ "dep:rustversion" ]; - }; - resolvedDefaultFeatures = [ "log" "logging" "ring" "tls12" ]; - }; - "rustls 0.23.7" = rec { + "rustls" = rec { crateName = "rustls"; version = "0.23.7"; edition = "2021"; @@ -11397,7 +10808,7 @@ rec { } { name = "rustls-webpki"; - packageId = "rustls-webpki 0.102.2"; + packageId = "rustls-webpki"; rename = "webpki"; usesDefaultFeatures = false; features = [ "alloc" ]; @@ -11433,39 +10844,12 @@ rec { }; resolvedDefaultFeatures = [ "log" "logging" "ring" "std" "tls12" ]; }; - "rustls-native-certs 0.6.3" = rec { - crateName = "rustls-native-certs"; - version = "0.6.3"; - edition = "2021"; - sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; - dependencies = [ - { - name = "openssl-probe"; - packageId = "openssl-probe"; - target = { target, features }: ((target."unix" or false) && (!("macos" == target."os" or null))); - } - { - name = "rustls-pemfile"; - packageId = "rustls-pemfile 1.0.4"; - } - { - name = "schannel"; - packageId = "schannel"; - target = { target, features }: (target."windows" or false); - } - { - name = "security-framework"; - packageId = "security-framework"; - target = { target, features }: ("macos" == target."os" or null); - } - ]; - - }; - "rustls-native-certs 0.7.0" = rec { + "rustls-native-certs" = rec { crateName = "rustls-native-certs"; version = "0.7.0"; edition = "2021"; sha256 = "14ip15dcr6fmjzi12lla9cpln7mmkdid4a7wsp344v4kz9gbh7wg"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -11474,7 +10858,7 @@ rec { } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; } { name = "rustls-pki-types"; @@ -11494,24 +10878,12 @@ rec { ]; }; - "rustls-pemfile 1.0.4" = rec { - crateName = "rustls-pemfile"; - version = "1.0.4"; - edition = "2018"; - sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; - dependencies = [ - { - name = "base64"; - packageId = "base64 0.21.7"; - } - ]; - - }; - "rustls-pemfile 2.1.0" = rec { + "rustls-pemfile" = rec { crateName = "rustls-pemfile"; version = "2.1.0"; edition = "2018"; sha256 = "02y7qn9d93ri4hrm72yw4zqlbxch6ma045nyazmdrppw6jvkncrw"; + libName = "rustls_pemfile"; dependencies = [ { name = "base64"; @@ -11536,37 +10908,14 @@ rec { version = "1.3.1"; edition = "2021"; sha256 = "1a0g7453h07701vyxjj05gv903a0shi43mf7hl3cdd08hsr6gpjy"; + libName = "rustls_pki_types"; features = { "default" = [ "alloc" ]; "std" = [ "alloc" ]; }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "rustls-webpki 0.101.7" = rec { - crateName = "rustls-webpki"; - version = "0.101.7"; - edition = "2021"; - sha256 = "0rapfhpkqp75552i8r0y7f4vq7csb4k7gjjans0df73sxv8paqlb"; - libName = "webpki"; - dependencies = [ - { - name = "ring"; - packageId = "ring"; - usesDefaultFeatures = false; - } - { - name = "untrusted"; - packageId = "untrusted"; - } - ]; - features = { - "alloc" = [ "ring/alloc" ]; - "default" = [ "std" ]; - "std" = [ "alloc" ]; - }; - resolvedDefaultFeatures = [ "alloc" "default" "std" ]; - }; - "rustls-webpki 0.102.2" = rec { + "rustls-webpki" = rec { crateName = "rustls-webpki"; version = "0.102.2"; edition = "2021"; @@ -11611,40 +10960,6 @@ rec { ]; }; - "rusty-fork" = rec { - crateName = "rusty-fork"; - version = "0.3.0"; - edition = "2018"; - sha256 = "0kxwq5c480gg6q0j3bg4zzyfh2kwmc3v2ba94jw8ncjc8mpcqgfb"; - authors = [ - "Jason Lingle" - ]; - dependencies = [ - { - name = "fnv"; - packageId = "fnv"; - } - { - name = "quick-error"; - packageId = "quick-error"; - } - { - name = "tempfile"; - packageId = "tempfile"; - } - { - name = "wait-timeout"; - packageId = "wait-timeout"; - optional = true; - } - ]; - features = { - "default" = [ "timeout" ]; - "timeout" = [ "wait-timeout" ]; - "wait-timeout" = [ "dep:wait-timeout" ]; - }; - resolvedDefaultFeatures = [ "timeout" "wait-timeout" ]; - }; "rustyline" = rec { crateName = "rustyline"; version = "10.1.1"; @@ -11756,6 +11071,7 @@ rec { version = "1.0.6"; edition = "2018"; sha256 = "00h5j1w87dmhnvbv9l8bic3y7xxsnjmssvifw2ayvgx9mb1ivz4k"; + libName = "same_file"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -11798,6 +11114,7 @@ rec { version = "1.0.1"; edition = "2015"; sha256 = "15524h04mafihcvfpgxd8f4bgc3k95aclz8grjkg9a0rxcvn9kz1"; + libName = "scoped_tls"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -11816,31 +11133,12 @@ rec { }; resolvedDefaultFeatures = [ "default" "use_std" ]; }; - "sct" = rec { - crateName = "sct"; - version = "0.7.1"; - edition = "2021"; - sha256 = "056lmi2xkzdg1dbai6ha3n57s18cbip4pnmpdhyljli3m99n216s"; - authors = [ - "Joseph Birr-Pixton <jpixton@gmail.com>" - ]; - dependencies = [ - { - name = "ring"; - packageId = "ring"; - } - { - name = "untrusted"; - packageId = "untrusted"; - } - ]; - - }; "security-framework" = rec { crateName = "security-framework"; version = "2.9.2"; edition = "2021"; sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -11887,6 +11185,7 @@ rec { version = "2.9.1"; edition = "2021"; sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -11928,9 +11227,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.204"; + version = "1.0.209"; edition = "2018"; - sha256 = "04kwpwqz559xlhxkggmm8rjxqgywy5swam3kscwsicnbw1cgaxmw"; + sha256 = "029yqqbb3c8v3gc720fhxn49dhgvb88zbyprdg5621riwzzy1z4r"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -11962,9 +11261,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.204"; + version = "1.0.209"; edition = "2015"; - sha256 = "08p25262mbmhsr2cg0508d5b1wvljj956rvpg0v3qgg6gc8pxkg0"; + sha256 = "0w114ksg1ymnmqdisd0g1j3g8jgz6pam45xg6yb47dfpkybip0x5"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -11985,7 +11284,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; usesDefaultFeatures = false; features = [ "clone-impls" "derive" "parsing" "printing" "proc-macro" ]; } @@ -12093,9 +11392,9 @@ rec { }; "serde_spanned" = rec { crateName = "serde_spanned"; - version = "0.6.6"; + version = "0.6.7"; edition = "2021"; - sha256 = "1839b6m5p9ijjmcwamiya2r612ks2vg6w2pp95yg76lr3zh79rkr"; + sha256 = "0v9h2nlg8r7n7dkbgj1aw59g35kl869l652wc6zi2f4zawqinnzb"; dependencies = [ { name = "serde"; @@ -12170,9 +11469,9 @@ rec { }; "serde_with" = rec { crateName = "serde_with"; - version = "3.7.0"; + version = "3.9.0"; edition = "2021"; - sha256 = "16jn72cij27fxjafcsma1z5p587xkk8wqhp2yv98zy5vc7iv107f"; + sha256 = "0mxqyh2qzq5xi8pnv9647337pz107yjv3ck7x9b229s892lwzkk9"; authors = [ "Jonas Bushart" "Marcin Kaźmierczak" @@ -12180,7 +11479,7 @@ rec { dependencies = [ { name = "base64"; - packageId = "base64 0.21.7"; + packageId = "base64 0.22.1"; optional = true; usesDefaultFeatures = false; } @@ -12277,9 +11576,9 @@ rec { }; "serde_with_macros" = rec { crateName = "serde_with_macros"; - version = "3.7.0"; + version = "3.9.0"; edition = "2021"; - sha256 = "0mbnika5bw1mvgnl50rs7wfzj7dwxzgwqxnq6656694j38bdqqb5"; + sha256 = "0l1kfkzj46can1rwfspmnan8shqr0prlmbaig9hp9wpl3scy9zm8"; procMacro = true; authors = [ "Jonas Bushart" @@ -12299,7 +11598,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "extra-traits" "full" "parsing" ]; } ]; @@ -12389,6 +11688,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -12402,11 +11702,30 @@ rec { "loom" = [ "dep:loom" ]; }; }; + "shlex" = rec { + crateName = "shlex"; + version = "1.3.0"; + edition = "2015"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; + authors = [ + "comex <comexk@gmail.com>" + "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "signal-hook-registry" = rec { crateName = "signal-hook-registry"; version = "1.4.1"; edition = "2015"; sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -12544,9 +11863,9 @@ rec { }; "smol_str" = rec { crateName = "smol_str"; - version = "0.2.1"; + version = "0.2.2"; edition = "2018"; - sha256 = "0jca0hyrwnv428q5gxhn2s8jsvrrkyrb0fyla9x37056mmimb176"; + sha256 = "1bfylqf2vnqaglw58930vpxm2rfzji5gjp15a2c0kh8aj6v8ylyx"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -12616,13 +11935,14 @@ rec { edition = "2018"; sha256 = "1gzy9rzggs090zf7hfvgp4lm1glrmg9qzh796686jnq7bxk7j04r"; procMacro = true; + libName = "snafu_derive"; authors = [ "Jake Goulding <jake.goulding@gmail.com>" ]; dependencies = [ { name = "heck"; - packageId = "heck"; + packageId = "heck 0.4.1"; } { name = "proc-macro2"; @@ -12738,6 +12058,7 @@ rec { version = "1.0.6"; edition = "2018"; sha256 = "1l7q4nha7wpsr0970bfqm773vhmpwr9l6rr8r4gwgrh46wvdh24y"; + libName = "str_buf"; authors = [ "Douman <douman@gmx.se>" ]; @@ -12745,7 +12066,7 @@ rec { "serde" = [ "dep:serde" ]; }; }; - "strsim" = rec { + "strsim 0.10.0" = rec { crateName = "strsim"; version = "0.10.0"; edition = "2015"; @@ -12755,6 +12076,17 @@ rec { ]; }; + "strsim 0.11.1" = rec { + crateName = "strsim"; + version = "0.11.1"; + edition = "2015"; + sha256 = "0kzvqlw8hxqb7y598w1s0hxlnmi84sg5vsipp3yg5na5d1rvba3x"; + authors = [ + "Danny Guo <danny@dannyguo.com>" + "maxbachmann <oss@maxbachmann.de>" + ]; + + }; "structmeta" = rec { crateName = "structmeta"; version = "0.1.6"; @@ -12796,6 +12128,7 @@ rec { edition = "2021"; sha256 = "14vxik2m3dm7bwx016qfz062fwznkbq02fyq8vby545m0pj0nhi4"; procMacro = true; + libName = "structmeta_derive"; authors = [ "frozenlib" ]; @@ -12869,11 +12202,11 @@ rec { }; resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; }; - "syn 2.0.48" = rec { + "syn 2.0.76" = rec { crateName = "syn"; - version = "2.0.48"; + version = "2.0.76"; edition = "2021"; - sha256 = "0gqgfygmrxmp8q32lia9p294kdd501ybn6kn2h4gqza0irik2d8g"; + sha256 = "09fmdkmqqkkfkg53qnldl10ppwqkqlw22ixhg4rgrkp02hd0i3jp"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -12896,12 +12229,11 @@ rec { ]; features = { "default" = [ "derive" "parsing" "printing" "clone-impls" "proc-macro" ]; - "printing" = [ "quote" ]; - "proc-macro" = [ "proc-macro2/proc-macro" "quote/proc-macro" ]; - "quote" = [ "dep:quote" ]; + "printing" = [ "dep:quote" ]; + "proc-macro" = [ "proc-macro2/proc-macro" "quote?/proc-macro" ]; "test" = [ "syn-test-suite/all-features" ]; }; - resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "quote" "visit" "visit-mut" ]; + resolvedDefaultFeatures = [ "clone-impls" "default" "derive" "extra-traits" "full" "parsing" "printing" "proc-macro" "visit" "visit-mut" ]; }; "sync_wrapper 0.1.2" = rec { crateName = "sync_wrapper"; @@ -12924,10 +12256,19 @@ rec { authors = [ "Actyx AG <developer@actyx.io>" ]; + dependencies = [ + { + name = "futures-core"; + packageId = "futures-core"; + optional = true; + usesDefaultFeatures = false; + } + ]; features = { "futures" = [ "futures-core" ]; "futures-core" = [ "dep:futures-core" ]; }; + resolvedDefaultFeatures = [ "futures" "futures-core" ]; }; "tabwriter" = rec { crateName = "tabwriter"; @@ -12948,9 +12289,9 @@ rec { }; "tempfile" = rec { crateName = "tempfile"; - version = "3.9.0"; - edition = "2018"; - sha256 = "1ypkl7rvv57n16q28psxpb61rnyhmfaif12ascdnsyljm90l3kh1"; + version = "3.12.0"; + edition = "2021"; + sha256 = "0r3sm3323crr50ranvask8z4qb3x5zfqxs1mrzab1swlqz8cvjq4"; authors = [ "Steven Allen <steven@stebalien.com>" "The Rust Project Developers" @@ -12967,9 +12308,10 @@ rec { packageId = "fastrand"; } { - name = "redox_syscall"; - packageId = "redox_syscall 0.4.1"; - target = { target, features }: ("redox" == target."os" or null); + name = "once_cell"; + packageId = "once_cell"; + usesDefaultFeatures = false; + features = [ "std" ]; } { name = "rustix"; @@ -12979,7 +12321,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.52.0"; + packageId = "windows-sys 0.59.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; } @@ -13009,6 +12351,7 @@ rec { edition = "2021"; sha256 = "105lxqs0vnqff5821sgns8q1scvrwfx1yw6iz7i7nr862j6l1mk2"; procMacro = true; + libName = "test_strategy"; authors = [ "frozenlib" ]; @@ -13038,6 +12381,7 @@ rec { version = "1.1.1"; edition = "2018"; sha256 = "0cwjbkl7w3xc8mnkhg1nwij6p5y2qkcfldgss8ddnawvhf3s32pi"; + libName = "text_size"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" "Christopher Durham (CAD97) <cad97@cad97.com>" @@ -13048,9 +12392,9 @@ rec { }; "thiserror" = rec { crateName = "thiserror"; - version = "1.0.56"; + version = "1.0.63"; edition = "2021"; - sha256 = "1b9hnzngjan4d89zjs16i01bcpcnvdwklyh73lj16xk28p37hhym"; + sha256 = "092p83mf4p1vkjb2j6h6z96dan4raq2simhirjv12slbndq26d60"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -13064,10 +12408,11 @@ rec { }; "thiserror-impl" = rec { crateName = "thiserror-impl"; - version = "1.0.56"; + version = "1.0.63"; edition = "2021"; - sha256 = "0w9ldp8fa574ilz4dn7y7scpcq66vdjy59qal8qdpwsh7faal3zs"; + sha256 = "0qd21l2jjrkvnpr5da3l3b58v4wmrkn6aa0h1z5dg6kb8rc8nmd4"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -13082,7 +12427,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; } ]; @@ -13127,9 +12472,9 @@ rec { }; "time" = rec { crateName = "time"; - version = "0.3.34"; + version = "0.3.36"; edition = "2021"; - sha256 = "0jc7wgprzqjhzd0nqkbmdlnjwyddnswmjw86ni2vq55v45jqn968"; + sha256 = "11g8hdpahgrf1wwl2rpsg5nxq3aj7ri6xr672v4qcij6cgjqizax"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -13210,6 +12555,7 @@ rec { version = "0.1.2"; edition = "2021"; sha256 = "1wx3qizcihw6z151hywfzzyd1y5dl804ydyxci6qm07vbakpr4pg"; + libName = "time_core"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -13218,10 +12564,11 @@ rec { }; "time-macros" = rec { crateName = "time-macros"; - version = "0.2.17"; + version = "0.2.18"; edition = "2021"; - sha256 = "0x3pahhk2751c6kqqq9dk6lz0gydbnxr44q01wpjlrz687ps78vv"; + sha256 = "1kqwxvfh2jkpg38fy673d6danh1bhcmmbsmffww3mphgail2l99z"; procMacro = true; + libName = "time_macros"; authors = [ "Jacob Pratt <open-source@jhpratt.dev>" "Time contributors" @@ -13298,9 +12645,9 @@ rec { }; "tokio" = rec { crateName = "tokio"; - version = "1.35.1"; + version = "1.39.3"; edition = "2021"; - sha256 = "01613rkziqp812a288ga65aqygs254wgajdi57v8brivjkx4x6y8"; + sha256 = "1xgzhj7bxqqpjaabjkgsx8hi0f600bzj4iyp9f0a9gr3k6dwkawv"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13323,16 +12670,11 @@ rec { } { name = "mio"; - packageId = "mio"; + packageId = "mio 1.0.2"; optional = true; usesDefaultFeatures = false; } { - name = "num_cpus"; - packageId = "num_cpus"; - optional = true; - } - { name = "pin-project-lite"; packageId = "pin-project-lite"; } @@ -13356,7 +12698,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; optional = true; target = { target, features }: (target."windows" or false); } @@ -13374,7 +12716,7 @@ rec { } { name = "windows-sys"; - packageId = "windows-sys 0.48.0"; + packageId = "windows-sys 0.52.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Foundation" "Win32_Security_Authorization" ]; } @@ -13387,10 +12729,9 @@ rec { "macros" = [ "tokio-macros" ]; "mio" = [ "dep:mio" ]; "net" = [ "libc" "mio/os-poll" "mio/os-ext" "mio/net" "socket2" "windows-sys/Win32_Foundation" "windows-sys/Win32_Security" "windows-sys/Win32_Storage_FileSystem" "windows-sys/Win32_System_Pipes" "windows-sys/Win32_System_SystemServices" ]; - "num_cpus" = [ "dep:num_cpus" ]; "parking_lot" = [ "dep:parking_lot" ]; "process" = [ "bytes" "libc" "mio/os-poll" "mio/os-ext" "mio/net" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Threading" "windows-sys/Win32_System_WindowsProgramming" ]; - "rt-multi-thread" = [ "num_cpus" "rt" ]; + "rt-multi-thread" = [ "rt" ]; "signal" = [ "libc" "mio/os-poll" "mio/net" "mio/os-ext" "signal-hook-registry" "windows-sys/Win32_Foundation" "windows-sys/Win32_System_Console" ]; "signal-hook-registry" = [ "dep:signal-hook-registry" ]; "socket2" = [ "dep:socket2" ]; @@ -13399,35 +12740,7 @@ rec { "tracing" = [ "dep:tracing" ]; "windows-sys" = [ "dep:windows-sys" ]; }; - resolvedDefaultFeatures = [ "bytes" "default" "fs" "io-std" "io-util" "libc" "macros" "mio" "net" "num_cpus" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; - }; - "tokio-io-timeout" = rec { - crateName = "tokio-io-timeout"; - version = "1.2.0"; - edition = "2018"; - sha256 = "1gx84f92q1491vj4pkn81j8pz1s3pgwnbrsdhfsa2556mli41drh"; - authors = [ - "Steven Fackler <sfackler@gmail.com>" - ]; - dependencies = [ - { - name = "pin-project-lite"; - packageId = "pin-project-lite"; - } - { - name = "tokio"; - packageId = "tokio"; - features = [ "time" ]; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; - } - ]; - + resolvedDefaultFeatures = [ "bytes" "default" "fs" "io-std" "io-util" "libc" "macros" "mio" "net" "rt" "rt-multi-thread" "signal" "signal-hook-registry" "socket2" "sync" "test-util" "time" "tokio-macros" "windows-sys" ]; }; "tokio-listener" = rec { crateName = "tokio-listener"; @@ -13438,7 +12751,7 @@ rec { dependencies = [ { name = "axum"; - packageId = "axum 0.7.5"; + packageId = "axum"; rename = "axum07"; optional = true; } @@ -13464,7 +12777,7 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; rename = "hyper1"; optional = true; features = [ "server" ]; @@ -13506,7 +12819,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; rename = "tonic_012"; optional = true; } @@ -13562,10 +12875,11 @@ rec { }; "tokio-macros" = rec { crateName = "tokio-macros"; - version = "2.2.0"; + version = "2.4.0"; edition = "2021"; - sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; + sha256 = "0lnpg14h1v3fh2jvnc8cz7cjf0m7z1xgkwfpcyy632g829imjgb9"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13580,7 +12894,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } ]; @@ -13591,6 +12905,7 @@ rec { version = "0.3.0"; edition = "2018"; sha256 = "0kr1hnm5dmb9gfkby88yg2xj8g6x4i4gipva0c8ca3xyxhvfnmvz"; + libName = "tokio_retry"; authors = [ "Sam Rijs <srijs@airpost.net>" ]; @@ -13618,82 +12933,16 @@ rec { ]; }; - "tokio-rustls 0.24.1" = rec { - crateName = "tokio-rustls"; - version = "0.24.1"; - edition = "2018"; - sha256 = "10bhibg57mqir7xjhb2xmf24xgfpx6fzpyw720a4ih8a737jg0y2"; - dependencies = [ - { - name = "rustls"; - packageId = "rustls 0.21.12"; - usesDefaultFeatures = false; - } - { - name = "tokio"; - packageId = "tokio"; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; - } - ]; - features = { - "dangerous_configuration" = [ "rustls/dangerous_configuration" ]; - "default" = [ "logging" "tls12" ]; - "logging" = [ "rustls/logging" ]; - "secret_extraction" = [ "rustls/secret_extraction" ]; - "tls12" = [ "rustls/tls12" ]; - }; - }; - "tokio-rustls 0.25.0" = rec { - crateName = "tokio-rustls"; - version = "0.25.0"; - edition = "2021"; - sha256 = "03w6d5aqqf084rmcmrsyq5grhydl53blaiqcl0i2yfnv187hqpkp"; - dependencies = [ - { - name = "rustls"; - packageId = "rustls 0.22.4"; - usesDefaultFeatures = false; - } - { - name = "rustls-pki-types"; - packageId = "rustls-pki-types"; - rename = "pki-types"; - } - { - name = "tokio"; - packageId = "tokio"; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "full" ]; - } - ]; - features = { - "default" = [ "logging" "tls12" "ring" ]; - "logging" = [ "rustls/logging" ]; - "ring" = [ "rustls/ring" ]; - "tls12" = [ "rustls/tls12" ]; - }; - resolvedDefaultFeatures = [ "default" "logging" "ring" "tls12" ]; - }; - "tokio-rustls 0.26.0" = rec { + "tokio-rustls" = rec { crateName = "tokio-rustls"; version = "0.26.0"; edition = "2021"; sha256 = "1m00czrmk8x7pdjnz10a3da3i1d0sdf9j9vfp5dnk5ss1q6w8yqc"; + libName = "tokio_rustls"; dependencies = [ { name = "rustls"; - packageId = "rustls 0.23.7"; + packageId = "rustls"; usesDefaultFeatures = false; features = [ "std" ]; } @@ -13727,9 +12976,10 @@ rec { }; "tokio-stream" = rec { crateName = "tokio-stream"; - version = "0.1.14"; + version = "0.1.15"; edition = "2021"; - sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + sha256 = "1brpbsqyg8yfmfc4y0j9zxvc8xsxjc31d48kb0g6jvpc1fgchyi6"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13773,6 +13023,7 @@ rec { version = "0.3.1"; edition = "2018"; sha256 = "0xffvap4g7hlswk5daklk3jaqha6s6wxw72c24kmqgna23018mwx"; + libName = "tokio_tar"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "dignifiedquire <me@dignifiequire.com>" @@ -13829,9 +13080,10 @@ rec { }; "tokio-test" = rec { crateName = "tokio-test"; - version = "0.4.3"; + version = "0.4.4"; edition = "2021"; - sha256 = "06fplzcc2ymahfzykd2ickw2qn7g3lz47bll00865s1spnx3r6z8"; + sha256 = "1xzri2m3dg8nzdyznm77nymvil9cyh1gfdfrbnska51iqfmvls14"; + libName = "tokio_test"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13869,9 +13121,10 @@ rec { }; "tokio-util" = rec { crateName = "tokio-util"; - version = "0.7.10"; + version = "0.7.11"; edition = "2021"; - sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + sha256 = "1qcz30db6m8lxkl61b3nic4bim1symi636nhbb3rmi3i6xxv9xlw"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -13902,13 +13155,6 @@ rec { packageId = "tokio"; features = [ "sync" ]; } - { - name = "tracing"; - packageId = "tracing"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } ]; devDependencies = [ { @@ -13919,7 +13165,6 @@ rec { ]; features = { "__docs_rs" = [ "futures-util" ]; - "codec" = [ "tracing" ]; "compat" = [ "futures-io" ]; "full" = [ "codec" "compat" "io-util" "time" "net" "rt" ]; "futures-io" = [ "dep:futures-io" ]; @@ -13932,7 +13177,7 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "compat" "default" "futures-io" "io" "io-util" "net" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "compat" "default" "futures-io" "io" "io-util" "net" ]; }; "toml 0.6.0" = rec { crateName = "toml"; @@ -13980,11 +13225,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "display" "parse" ]; }; - "toml 0.8.15" = rec { + "toml 0.8.19" = rec { crateName = "toml"; - version = "0.8.15"; + version = "0.8.19"; edition = "2021"; - sha256 = "0a2wk4xjdqw59w0jjia3b7p3yinv7wlv68xfq338hwvmpyqalb5c"; + sha256 = "0knjd3mkxyb87qcs2dark3qkpadidap3frqfj5nqvhpxwfc1zvd1"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -14000,12 +13245,12 @@ rec { } { name = "toml_datetime"; - packageId = "toml_datetime 0.6.6"; + packageId = "toml_datetime 0.6.8"; features = [ "serde" ]; } { name = "toml_edit"; - packageId = "toml_edit 0.22.16"; + packageId = "toml_edit 0.22.20"; optional = true; usesDefaultFeatures = false; features = [ "serde" ]; @@ -14047,11 +13292,11 @@ rec { }; resolvedDefaultFeatures = [ "serde" ]; }; - "toml_datetime 0.6.6" = rec { + "toml_datetime 0.6.8" = rec { crateName = "toml_datetime"; - version = "0.6.6"; + version = "0.6.8"; edition = "2021"; - sha256 = "1grcrr3gh7id3cy3j700kczwwfbn04p5ncrrj369prjaj9bgvbab"; + sha256 = "0hgv7v9g35d7y9r2afic58jvlwnf73vgd1mz2k8gihlgrf73bmqd"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -14108,11 +13353,11 @@ rec { }; resolvedDefaultFeatures = [ "default" "serde" ]; }; - "toml_edit 0.22.16" = rec { + "toml_edit 0.22.20" = rec { crateName = "toml_edit"; - version = "0.22.16"; + version = "0.22.20"; edition = "2021"; - sha256 = "1207pygznx57j9hrkmmfiq8mxjkba5c7g1yfjk4ij8hmir8kv3r7"; + sha256 = "07ffw4626k6abicjxb2idh12f1p5fn965zk660zhqsyj5b048g2q"; authors = [ "Andronik Ordian <write@reusable.software>" "Ed Page <eopage@gmail.com>" @@ -14136,7 +13381,7 @@ rec { } { name = "toml_datetime"; - packageId = "toml_datetime 0.6.6"; + packageId = "toml_datetime 0.6.8"; } { name = "winnow"; @@ -14152,11 +13397,11 @@ rec { }; resolvedDefaultFeatures = [ "display" "parse" "serde" ]; }; - "tonic 0.11.0" = rec { + "tonic" = rec { crateName = "tonic"; - version = "0.11.0"; + version = "0.12.2"; edition = "2021"; - sha256 = "04qsr527i256i3dk9dp1g2jr42q7yl91y5h06rvd9ycy9rxfpi3n"; + sha256 = "1bc8m8r7ysgkb7mhs3b3mvivd43nwaix6qnqhfp5hb2bkscbmxn6"; authors = [ "Lucio Franco <luciofranco14@gmail.com>" ]; @@ -14173,148 +13418,7 @@ rec { } { name = "axum"; - packageId = "axum 0.6.20"; - optional = true; - usesDefaultFeatures = false; - } - { - name = "base64"; - packageId = "base64 0.21.7"; - } - { - name = "bytes"; - packageId = "bytes"; - } - { - name = "h2"; - packageId = "h2 0.3.26"; - optional = true; - } - { - name = "http"; - packageId = "http 0.2.11"; - } - { - name = "http-body"; - packageId = "http-body 0.4.6"; - } - { - name = "hyper"; - packageId = "hyper 0.14.28"; - optional = true; - features = [ "full" ]; - } - { - name = "hyper-timeout"; - packageId = "hyper-timeout 0.4.1"; - optional = true; - } - { - name = "percent-encoding"; - packageId = "percent-encoding"; - } - { - name = "pin-project"; - packageId = "pin-project"; - } - { - name = "prost"; - packageId = "prost 0.12.3"; - optional = true; - usesDefaultFeatures = false; - features = [ "std" ]; - } - { - name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; - optional = true; - } - { - name = "rustls-pki-types"; - packageId = "rustls-pki-types"; - optional = true; - } - { - name = "tokio"; - packageId = "tokio"; - } - { - name = "tokio-rustls"; - packageId = "tokio-rustls 0.25.0"; - optional = true; - } - { - name = "tokio-stream"; - packageId = "tokio-stream"; - } - { - name = "tower"; - packageId = "tower"; - optional = true; - usesDefaultFeatures = false; - features = [ "balance" "buffer" "discover" "limit" "load" "make" "timeout" "util" ]; - } - { - name = "tower-layer"; - packageId = "tower-layer"; - } - { - name = "tower-service"; - packageId = "tower-service"; - } - { - name = "tracing"; - packageId = "tracing"; - } - ]; - devDependencies = [ - { - name = "tokio"; - packageId = "tokio"; - features = [ "rt" "macros" ]; - } - { - name = "tower"; - packageId = "tower"; - features = [ "full" ]; - } - ]; - features = { - "codegen" = [ "dep:async-trait" ]; - "default" = [ "transport" "codegen" "prost" ]; - "gzip" = [ "dep:flate2" ]; - "prost" = [ "dep:prost" ]; - "tls" = [ "dep:rustls-pki-types" "dep:rustls-pemfile" "transport" "dep:tokio-rustls" "tokio/rt" "tokio/macros" ]; - "tls-roots" = [ "tls-roots-common" "dep:rustls-native-certs" ]; - "tls-roots-common" = [ "tls" ]; - "tls-webpki-roots" = [ "tls-roots-common" "dep:webpki-roots" ]; - "transport" = [ "dep:async-stream" "dep:axum" "channel" "dep:h2" "dep:hyper" "tokio/net" "tokio/time" "dep:tower" "dep:hyper-timeout" ]; - "zstd" = [ "dep:zstd" ]; - }; - resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "tls" "transport" ]; - }; - "tonic 0.12.1" = rec { - crateName = "tonic"; - version = "0.12.1"; - edition = "2021"; - sha256 = "00bl9i4fal2s90g1p877053dkpbxvgsqj5c24y6mka5bj559yr9q"; - authors = [ - "Lucio Franco <luciofranco14@gmail.com>" - ]; - dependencies = [ - { - name = "async-stream"; - packageId = "async-stream"; - optional = true; - } - { - name = "async-trait"; - packageId = "async-trait"; - optional = true; - } - { - name = "axum"; - packageId = "axum 0.7.5"; + packageId = "axum"; optional = true; usesDefaultFeatures = false; } @@ -14328,16 +13432,16 @@ rec { } { name = "h2"; - packageId = "h2 0.4.4"; + packageId = "h2"; optional = true; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -14345,13 +13449,13 @@ rec { } { name = "hyper"; - packageId = "hyper 1.4.1"; + packageId = "hyper"; optional = true; features = [ "http1" "http2" ]; } { name = "hyper-timeout"; - packageId = "hyper-timeout 0.5.1"; + packageId = "hyper-timeout"; optional = true; } { @@ -14370,19 +13474,19 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; optional = true; usesDefaultFeatures = false; features = [ "std" ]; } { name = "rustls-native-certs"; - packageId = "rustls-native-certs 0.7.0"; + packageId = "rustls-native-certs"; optional = true; } { name = "rustls-pemfile"; - packageId = "rustls-pemfile 2.1.0"; + packageId = "rustls-pemfile"; optional = true; } { @@ -14399,7 +13503,7 @@ rec { } { name = "tokio-rustls"; - packageId = "tokio-rustls 0.26.0"; + packageId = "tokio-rustls"; optional = true; usesDefaultFeatures = false; features = [ "logging" "tls12" "ring" ]; @@ -14449,18 +13553,20 @@ rec { "router" = [ "dep:axum" "dep:tower" "tower?/util" ]; "server" = [ "router" "dep:async-stream" "dep:h2" "dep:hyper" "hyper?/server" "dep:hyper-util" "hyper-util?/service" "hyper-util?/server-auto" "dep:socket2" "dep:tokio" "tokio?/macros" "tokio?/net" "tokio?/time" "tokio-stream/net" "dep:tower" "tower?/util" "tower?/limit" ]; "tls" = [ "dep:rustls-pemfile" "dep:tokio-rustls" "dep:tokio" "tokio?/rt" "tokio?/macros" ]; - "tls-roots" = [ "tls" "channel" "dep:rustls-native-certs" ]; + "tls-native-roots" = [ "tls" "channel" "dep:rustls-native-certs" ]; + "tls-roots" = [ "tls-native-roots" ]; "tls-webpki-roots" = [ "tls" "channel" "dep:webpki-roots" ]; "transport" = [ "server" "channel" ]; "zstd" = [ "dep:zstd" ]; }; - resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "router" "server" "tls" "tls-roots" "transport" ]; + resolvedDefaultFeatures = [ "channel" "codegen" "default" "prost" "router" "server" "tls" "tls-native-roots" "tls-roots" "transport" ]; }; - "tonic-build 0.11.0" = rec { + "tonic-build" = rec { crateName = "tonic-build"; - version = "0.11.0"; + version = "0.12.2"; edition = "2021"; - sha256 = "1hm99ckaw0pzq8h22bdjy6gpbg06kpvs0f73nj60f456f3fzckmy"; + sha256 = "0rwaxvsx4rld1ncmcih0bvmg8k8ah4r1ccyjwgbnn4shfa3yhkpy"; + libName = "tonic_build"; authors = [ "Lucio Franco <luciofranco14@gmail.com>" ]; @@ -14475,7 +13581,7 @@ rec { } { name = "prost-build"; - packageId = "prost-build 0.12.3"; + packageId = "prost-build"; optional = true; } { @@ -14484,7 +13590,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; } ]; features = { @@ -14495,50 +13601,12 @@ rec { }; resolvedDefaultFeatures = [ "cleanup-markdown" "default" "prost" "prost-build" "transport" ]; }; - "tonic-build 0.12.1" = rec { - crateName = "tonic-build"; - version = "0.12.1"; - edition = "2021"; - sha256 = "0r5riq6gm79hmmsd1z6rdziszava2y8phf1z7rr2005xlb2r50sn"; - authors = [ - "Lucio Franco <luciofranco14@gmail.com>" - ]; - dependencies = [ - { - name = "prettyplease"; - packageId = "prettyplease"; - } - { - name = "proc-macro2"; - packageId = "proc-macro2"; - } - { - name = "prost-build"; - packageId = "prost-build 0.13.1"; - optional = true; - } - { - name = "quote"; - packageId = "quote"; - } - { - name = "syn"; - packageId = "syn 2.0.48"; - } - ]; - features = { - "cleanup-markdown" = [ "prost" "prost-build/cleanup-markdown" ]; - "default" = [ "transport" "prost" ]; - "prost" = [ "prost-build" ]; - "prost-build" = [ "dep:prost-build" ]; - }; - resolvedDefaultFeatures = [ "default" "prost" "prost-build" "transport" ]; - }; "tonic-health" = rec { crateName = "tonic-health"; - version = "0.12.1"; + version = "0.12.2"; edition = "2021"; - sha256 = "0ma93g27szqjh4gniws6wz82ils2hhvd91rl8k7bc27fjrm0xqg1"; + sha256 = "19xm66ban6w8gjybqhp4ra3zz9pnqfjis3j95dmy5fh6yzk382pc"; + libName = "tonic_health"; authors = [ "James Nugent <james@jen20.com>" ]; @@ -14549,7 +13617,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "tokio"; @@ -14562,7 +13630,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; usesDefaultFeatures = false; features = [ "codegen" "prost" ]; } @@ -14584,9 +13652,10 @@ rec { }; "tonic-reflection" = rec { crateName = "tonic-reflection"; - version = "0.12.1"; + version = "0.12.2"; edition = "2021"; - sha256 = "0wy1vdj4fj90j6zjqs78c2fvwcl9krxiz6709idspsbksqxchhmp"; + sha256 = "1zwrm9zzahipsrmaqfp4vk0w31qymf740fsp0yczh16vxrsbhmkv"; + libName = "tonic_reflection"; authors = [ "James Nugent <james@jen20.com>" "Samani G. Gikandi <samani@gojulas.com>" @@ -14594,11 +13663,11 @@ rec { dependencies = [ { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "prost-types"; - packageId = "prost-types 0.13.1"; + packageId = "prost-types"; optional = true; } { @@ -14615,7 +13684,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; usesDefaultFeatures = false; features = [ "codegen" "prost" ]; } @@ -14623,7 +13692,7 @@ rec { devDependencies = [ { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; usesDefaultFeatures = false; features = [ "transport" ]; } @@ -14754,20 +13823,21 @@ rec { "tracing" = [ "dep:tracing" ]; "util" = [ "__common" "futures-util" "pin-project" ]; }; - resolvedDefaultFeatures = [ "__common" "balance" "buffer" "default" "discover" "futures-core" "futures-util" "indexmap" "limit" "load" "log" "make" "pin-project" "pin-project-lite" "rand" "ready-cache" "slab" "timeout" "tokio" "tokio-util" "tracing" "util" ]; + resolvedDefaultFeatures = [ "__common" "balance" "buffer" "default" "discover" "futures-core" "futures-util" "indexmap" "limit" "load" "log" "make" "pin-project" "pin-project-lite" "rand" "ready-cache" "slab" "tokio" "tokio-util" "tracing" "util" ]; }; "tower-http" = rec { crateName = "tower-http"; version = "0.5.2"; edition = "2018"; sha256 = "1xakj3x0anp55gjqibiwvzma5iz0w9pcjsr7qk97sx4qm4sd970y"; + libName = "tower_http"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; dependencies = [ { name = "bitflags"; - packageId = "bitflags 2.4.2"; + packageId = "bitflags 2.6.0"; } { name = "bytes"; @@ -14775,11 +13845,11 @@ rec { } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; } { name = "http-body"; - packageId = "http-body 1.0.0"; + packageId = "http-body"; } { name = "http-body-util"; @@ -14854,6 +13924,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -14864,6 +13935,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -14922,6 +13994,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -14938,7 +14011,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; usesDefaultFeatures = false; features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; } @@ -14950,6 +14023,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -14980,6 +14054,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1wimg0iwa2ldq7xv98lvivvf3q9ykfminig8r1bs0ig22np9bl4p"; + libName = "tracing_futures"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "Tokio Contributors <team@tokio.rs>" @@ -15043,6 +14118,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -15074,6 +14150,7 @@ rec { version = "0.23.0"; edition = "2018"; sha256 = "1112kmckw0qwyckhbwarb230n4ldmfgzixr9jagbfjmy3fx19gm9"; + libName = "tracing_opentelemetry"; authors = [ "Julian Tescher <julian@tescher.me>" "Tokio Contributors <team@tokio.rs>" @@ -15174,6 +14251,7 @@ rec { version = "0.25.0"; edition = "2021"; sha256 = "0fzzhpcxngnxra56cxmslr5y6k0f1b4ghqv9vz41p4kxvba4wy59"; + libName = "tracing_opentelemetry"; dependencies = [ { name = "js-sys"; @@ -15272,6 +14350,7 @@ rec { version = "0.3.18"; edition = "2018"; sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -15382,9 +14461,10 @@ rec { }; "tracing-tracy" = rec { crateName = "tracing-tracy"; - version = "0.11.0"; + version = "0.11.2"; edition = "2021"; - sha256 = "051nf1ncp1z45acgk0h5199ldlhb0wmkmvhyvk8x17x6hi7x0930"; + sha256 = "16xnvxshac0qv61zzv0rm4sl8x0hkws7cngx5z3fambgy4chbaf6"; + libName = "tracing_tracy"; authors = [ "Simonas Kazlauskas <tracing-tracy@kazlauskas.me>" ]; @@ -15415,6 +14495,7 @@ rec { "context-switch-tracing" = [ "client/context-switch-tracing" ]; "default" = [ "enable" "system-tracing" "context-switch-tracing" "sampling" "code-transfer" "broadcast" "callstack-inlines" ]; "delayed-init" = [ "client/delayed-init" ]; + "demangle" = [ "client/demangle" ]; "enable" = [ "client/enable" ]; "fibers" = [ "client/fibers" ]; "flush-on-exit" = [ "client/flush-on-exit" ]; @@ -15425,6 +14506,7 @@ rec { "sampling" = [ "client/sampling" ]; "system-tracing" = [ "client/system-tracing" ]; "timer-fallback" = [ "client/timer-fallback" ]; + "verify" = [ "client/verify" ]; }; resolvedDefaultFeatures = [ "broadcast" "callstack-inlines" "code-transfer" "context-switch-tracing" "default" "enable" "flush-on-exit" "sampling" "system-tracing" ]; }; @@ -15433,6 +14515,7 @@ rec { version = "0.17.0"; edition = "2021"; sha256 = "07bla4iigg17fl4zil2dwizslhw8mv8vrsfkhr7ri27zchd97ysr"; + libName = "tracy_client"; authors = [ "Simonas Kazlauskas <tracy-client@kazlauskas.me>" ]; @@ -15478,6 +14561,7 @@ rec { version = "0.22.2"; edition = "2021"; sha256 = "10h8msq85b7rhfg2vg22g2iizbk4c6fcq0jiadad37gs1mhls44x"; + libName = "tracy_client_sys"; authors = [ "Simonas Kazlauskas <tracy-client-sys@kazlauskas.me>" ]; @@ -15499,11 +14583,51 @@ rec { version = "0.2.5"; edition = "2015"; sha256 = "0jqijrrvm1pyq34zn1jmy2vihd4jcrjlvsh4alkjahhssjnsn8g4"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; }; + "trybuild" = rec { + crateName = "trybuild"; + version = "1.0.99"; + edition = "2021"; + sha256 = "1s4i2hpyb66676xkg6b6fxm2qdsawj5lfad8ds68vgn46q6sayi0"; + authors = [ + "David Tolnay <dtolnay@gmail.com>" + ]; + dependencies = [ + { + name = "glob"; + packageId = "glob"; + } + { + name = "serde"; + packageId = "serde"; + } + { + name = "serde_derive"; + packageId = "serde_derive"; + } + { + name = "serde_json"; + packageId = "serde_json"; + } + { + name = "termcolor"; + packageId = "termcolor"; + } + { + name = "toml"; + packageId = "toml 0.8.19"; + } + ]; + features = { + "diff" = [ "dissimilar" ]; + "dissimilar" = [ "dep:dissimilar" ]; + }; + }; "tvix-build" = rec { crateName = "tvix-build"; version = "0.1.0"; @@ -15516,6 +14640,7 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./build; }; + libName = "tvix_build"; dependencies = [ { name = "bytes"; @@ -15528,7 +14653,7 @@ rec { } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; } { name = "mimalloc"; @@ -15536,7 +14661,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "thiserror"; @@ -15553,7 +14678,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; features = [ "tls" "tls-roots" ]; } { @@ -15581,11 +14706,11 @@ rec { buildDependencies = [ { name = "prost-build"; - packageId = "prost-build 0.13.1"; + packageId = "prost-build"; } { name = "tonic-build"; - packageId = "tonic-build 0.12.1"; + packageId = "tonic-build"; } ]; devDependencies = [ @@ -15604,6 +14729,7 @@ rec { version = "0.1.0"; edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ./castore; }; + libName = "tvix_castore"; dependencies = [ { name = "async-compression"; @@ -15694,7 +14820,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "redb"; @@ -15751,7 +14877,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; } { name = "tonic-reflection"; @@ -15821,11 +14947,11 @@ rec { buildDependencies = [ { name = "prost-build"; - packageId = "prost-build 0.13.1"; + packageId = "prost-build"; } { name = "tonic-build"; - packageId = "tonic-build 0.12.1"; + packageId = "tonic-build"; } ]; devDependencies = [ @@ -15884,6 +15010,7 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./cli; }; + libName = "tvix_cli"; dependencies = [ { name = "bytes"; @@ -16021,13 +15148,8 @@ rec { usesDefaultFeatures = false; } { - name = "imbl"; - packageId = "imbl"; - features = [ "serde" ]; - } - { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; } { name = "lazy_static"; @@ -16043,6 +15165,10 @@ rec { packageId = "md-5"; } { + name = "nohash-hasher"; + packageId = "nohash-hasher"; + } + { name = "os_str_bytes"; packageId = "os_str_bytes"; features = [ "conversions" ]; @@ -16113,6 +15239,10 @@ rec { packageId = "tvix-eval-builtin-macros"; rename = "builtin-macros"; } + { + name = "vu128"; + packageId = "vu128"; + } ]; devDependencies = [ { @@ -16121,7 +15251,7 @@ rec { } { name = "itertools"; - packageId = "itertools 0.12.0"; + packageId = "itertools 0.12.1"; } { name = "mimalloc"; @@ -16141,7 +15271,7 @@ rec { } ]; features = { - "arbitrary" = [ "proptest" "test-strategy" "imbl/proptest" ]; + "arbitrary" = [ "proptest" "test-strategy" ]; "default" = [ "impure" "arbitrary" "nix_tests" ]; "proptest" = [ "dep:proptest" ]; "test-strategy" = [ "dep:test-strategy" ]; @@ -16154,6 +15284,7 @@ rec { edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ./eval/builtin-macros; }; procMacro = true; + libName = "tvix_eval_builtin_macros"; authors = [ "Griffin Smith <root@gws.fyi>" ]; @@ -16185,6 +15316,7 @@ rec { version = "0.1.0"; edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ./glue; }; + libName = "tvix_glue"; dependencies = [ { name = "async-compression"; @@ -16202,7 +15334,6 @@ rec { { name = "clap"; packageId = "clap"; - usesDefaultFeatures = false; } { name = "data-encoding"; @@ -16345,6 +15476,10 @@ rec { name = "tempfile"; packageId = "tempfile"; } + { + name = "tokio-test"; + packageId = "tokio-test"; + } ]; features = { "default" = [ "nix_tests" ]; @@ -16356,6 +15491,7 @@ rec { version = "0.1.0"; edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ./serde; }; + libName = "tvix_serde"; dependencies = [ { name = "bstr"; @@ -16386,6 +15522,7 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./store; }; + libName = "tvix_store"; dependencies = [ { name = "anyhow"; @@ -16466,7 +15603,7 @@ rec { } { name = "prost"; - packageId = "prost 0.13.1"; + packageId = "prost"; } { name = "redb"; @@ -16533,12 +15670,12 @@ rec { } { name = "toml"; - packageId = "toml 0.8.15"; + packageId = "toml 0.8.19"; optional = true; } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; features = [ "tls" "tls-roots" ]; } { @@ -16589,11 +15726,11 @@ rec { buildDependencies = [ { name = "prost-build"; - packageId = "prost-build 0.13.1"; + packageId = "prost-build"; } { name = "tonic-build"; - packageId = "tonic-build 0.12.1"; + packageId = "tonic-build"; } ]; devDependencies = [ @@ -16636,15 +15773,16 @@ rec { version = "0.1.0"; edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ./tracing; }; + libName = "tvix_tracing"; dependencies = [ { name = "axum"; - packageId = "axum 0.7.5"; + packageId = "axum"; optional = true; } { name = "http"; - packageId = "http 1.1.0"; + packageId = "http"; optional = true; } { @@ -16693,7 +15831,7 @@ rec { } { name = "tonic"; - packageId = "tonic 0.12.1"; + packageId = "tonic"; optional = true; } { @@ -16800,6 +15938,7 @@ rec { edition = "2021"; sha256 = "1cabnvm526bcgh1sh34js5ils0gz4xwlgvwhm992acdr8xzqhwxc"; procMacro = true; + libName = "typetag_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -16814,7 +15953,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } ]; @@ -16867,6 +16006,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -16877,6 +16017,7 @@ rec { version = "0.1.22"; edition = "2018"; sha256 = "08d95g7b1irc578b2iyhzv4xhsa4pfvwsqxcl9lbcpabzkq16msw"; + libName = "unicode_normalization"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -16898,6 +16039,7 @@ rec { version = "1.10.1"; edition = "2018"; sha256 = "0dky2hm5k51xy11hc3nk85p533rvghd462b6i0c532b7hl4j9mhx"; + libName = "unicode_segmentation"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -16909,6 +16051,7 @@ rec { version = "0.1.11"; edition = "2015"; sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -16933,9 +16076,9 @@ rec { }; "url" = rec { crateName = "url"; - version = "2.5.0"; + version = "2.5.2"; edition = "2018"; - sha256 = "0cs65961miawncdg2z20171w0vqrmraswv2ihdpd8lxp7cp31rii"; + sha256 = "0v2dx50mx7xzl9454cl5qmpjnhkbahmn59gd3apyipbgyyylsy12"; authors = [ "The rust-url developers" ]; @@ -17102,6 +16245,7 @@ rec { version = "0.8.0"; edition = "2018"; sha256 = "00s33wy8cj2i8b4hlxn7wd8zm1fpaa5kjhzv77b3khsavf8pn8wz"; + libName = "vhost_user_backend"; authors = [ "The Cloud Hypervisor Authors" ]; @@ -17156,6 +16300,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "0sxxhhmz1r4s4q5pd2lykswcv9qk05fmpwc5xlb8aj45h8bi5x9z"; + libName = "virtio_bindings"; authors = [ "Sergio Lopez <slp@redhat.com>" ]; @@ -17166,6 +16311,7 @@ rec { version = "0.2.2"; edition = "2021"; sha256 = "11mfm9brqgwpfg0izsgc4n7xkqwxk5ad03ivslq0r88j50dwp2w7"; + libName = "virtio_bindings"; authors = [ "Sergio Lopez <slp@redhat.com>" ]; @@ -17176,6 +16322,7 @@ rec { version = "0.7.1"; edition = "2021"; sha256 = "1gbppbapj7c0vyca88vl34cx4sp2cy9yg0v6bvyd5h11rhmixa1v"; + libName = "virtio_queue"; authors = [ "The Chromium OS Authors" ]; @@ -17211,6 +16358,7 @@ rec { version = "0.10.0"; edition = "2021"; sha256 = "0z423a8i4s3addq4yjad4ar5l6qwarjwdn94lismbd0mcqv712k8"; + libName = "vm_memory"; authors = [ "Liu Jiang <gerry@linux.alibaba.com>" ]; @@ -17242,6 +16390,7 @@ rec { version = "0.11.2"; edition = "2021"; sha256 = "0a9azxk6wsahwkggshbdga4jdryzfw6j5r21f11gf50j4f2b1ds8"; + libName = "vmm_sys_util"; authors = [ "Intel Virtualization Team <vmm-maintainers@intel.com>" ]; @@ -17353,29 +16502,22 @@ rec { ]; }; - "wait-timeout" = rec { - crateName = "wait-timeout"; - version = "0.2.0"; - edition = "2015"; - crateBin = [ ]; - sha256 = "1xpkk0j5l9pfmjfh1pi0i89invlavfrd9av5xp0zhxgb29dhy84z"; + "vu128" = rec { + crateName = "vu128"; + version = "1.1.0"; + edition = "2018"; + sha256 = "1pczgy26c0lsri1ddrx5wkgn0rcq4da04pqya5rl6vrwfnys73di"; + libPath = "vu128/vu128.rs"; authors = [ - "Alex Crichton <alex@alexcrichton.com>" - ]; - dependencies = [ - { - name = "libc"; - packageId = "libc"; - target = { target, features }: (target."unix" or false); - } + "John Millikin <john@john-millikin.com>" ]; }; "walkdir" = rec { crateName = "walkdir"; - version = "2.4.0"; + version = "2.5.0"; edition = "2018"; - sha256 = "1vjl9fmfc4v8k9ald23qrpcbyb8dl1ynyq8d516cm537r1yqa7fp"; + sha256 = "0jsy7a710qv8gld5957ybrnc07gavppp963gs32xk4ag8130jy99"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -17430,6 +16572,7 @@ rec { version = "0.2.90"; edition = "2018"; sha256 = "01jlal3mynqwvqx4acrdnr9bvsdczaz2sy8lmmzmqh81lab348mi"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -17461,6 +16604,7 @@ rec { version = "0.2.90"; edition = "2018"; sha256 = "1kcxml9762zjdrn0h0n0qxfg1n7z1f577jcc5yimi3a0cddr7p7w"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -17487,7 +16631,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "full" ]; } { @@ -17505,6 +16649,7 @@ rec { version = "0.4.40"; edition = "2018"; sha256 = "0qf4bzlinyg0s4b38fhzdi1cqdd7rgrywqdjr3ngmgc6xcm07qmx"; + libName = "wasm_bindgen_futures"; authors = [ "The wasm-bindgen Developers" ]; @@ -17539,6 +16684,7 @@ rec { edition = "2018"; sha256 = "16d980bql7y5krfqlmcr8mk1q4mrm0rmb0a99j92im5jc62j6k1y"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -17563,6 +16709,7 @@ rec { version = "0.2.90"; edition = "2018"; sha256 = "19r5bsyjw0fvim7dsj8pbwrq8v0ggh845lhfasgavhbdh2vapqds"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -17577,7 +16724,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; features = [ "visit" "full" ]; } { @@ -17601,6 +16748,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "0av0m0shdg1jxhf66ymjbq03m0qb7ypm297glndm7mri3hxl34ad"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -17611,6 +16759,7 @@ rec { version = "0.4.0"; edition = "2021"; sha256 = "0ad17c59xb8fffsnbrqbyqz93hb66nzxhizpii31icb31g4w8pdn"; + libName = "wasm_streams"; type = [ "cdylib" "rlib" ]; authors = [ "Mattias Buelens <mattias@buelens.com>" @@ -17653,6 +16802,7 @@ rec { version = "0.3.67"; edition = "2018"; sha256 = "1vfjjj3i49gy8bh8znnqhak1hx7xj9c2a3jzc0wpmgp0nqrj7kaq"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -18122,6 +17272,7 @@ rec { version = "1.1.0"; edition = "2021"; sha256 = "1fx05yqx83dhx628wb70fyy10yjfq1jpl20qfqhdkymi13rq0ras"; + libName = "web_time"; dependencies = [ { name = "js-sys"; @@ -18139,80 +17290,6 @@ rec { "serde" = [ "dep:serde" ]; }; }; - "which 4.4.2" = rec { - crateName = "which"; - version = "4.4.2"; - edition = "2021"; - sha256 = "1ixzmx3svsv5hbdvd8vdhd3qwvf6ns8jdpif1wmwsy10k90j9fl7"; - authors = [ - "Harry Fei <tiziyuanfang@gmail.com>" - ]; - dependencies = [ - { - name = "either"; - packageId = "either"; - } - { - name = "home"; - packageId = "home"; - target = { target, features }: ((target."windows" or false) || (target."unix" or false) || ("redox" == target."os" or null)); - } - { - name = "once_cell"; - packageId = "once_cell"; - target = { target, features }: (target."windows" or false); - } - { - name = "rustix"; - packageId = "rustix"; - usesDefaultFeatures = false; - features = [ "fs" "std" ]; - } - ]; - features = { - "regex" = [ "dep:regex" ]; - }; - }; - "which 5.0.0" = rec { - crateName = "which"; - version = "5.0.0"; - edition = "2021"; - sha256 = "053fpbczryyn8lcbpkvwl8v2rzld0pr30r5lh1cxv87kjs2ymwwv"; - authors = [ - "Harry Fei <tiziyuanfang@gmail.com>" - ]; - dependencies = [ - { - name = "either"; - packageId = "either"; - } - { - name = "home"; - packageId = "home"; - target = { target, features }: ((target."windows" or false) || (target."unix" or false) || ("redox" == target."os" or null)); - } - { - name = "once_cell"; - packageId = "once_cell"; - target = { target, features }: (target."windows" or false); - } - { - name = "rustix"; - packageId = "rustix"; - usesDefaultFeatures = false; - features = [ "fs" "std" ]; - } - { - name = "windows-sys"; - packageId = "windows-sys 0.48.0"; - target = { target, features }: (target."windows" or false); - features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; - } - ]; - features = { - "regex" = [ "dep:regex" ]; - }; - }; "winapi" = rec { crateName = "winapi"; version = "0.3.9"; @@ -18243,6 +17320,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -18253,6 +17331,7 @@ rec { version = "0.1.6"; edition = "2021"; sha256 = "15i5lm39wd44004i9d5qspry2cynkrpvwzghr6s2c3dsk28nz7pj"; + libName = "winapi_util"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -18271,6 +17350,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -18291,7 +17371,7 @@ rec { } { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; } ]; features = { @@ -18991,13 +18071,14 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; } ]; features = { }; @@ -19008,23 +18089,49 @@ rec { version = "0.54.0"; edition = "2021"; sha256 = "0r8x2sgl4qq1h23ldf4z7cj213k0bz7479m8a156h79mi6f1nrhj"; + libName = "windows_core"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-result"; - packageId = "windows-result"; + packageId = "windows-result 0.1.2"; } { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; } ]; features = { }; resolvedDefaultFeatures = [ "default" ]; }; - "windows-result" = rec { + "windows-registry" = rec { + crateName = "windows-registry"; + version = "0.2.0"; + edition = "2021"; + sha256 = "1c04923fq0rbvl3z0h67xr6rh2fgwkizhclhqv0j79i0nwdh0074"; + libName = "windows_registry"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-result"; + packageId = "windows-result 0.2.0"; + } + { + name = "windows-strings"; + packageId = "windows-strings"; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + + }; + "windows-result 0.1.2" = rec { crateName = "windows-result"; version = "0.1.2"; edition = "2021"; @@ -19036,7 +18143,52 @@ rec { dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "windows-result 0.2.0" = rec { + crateName = "windows-result"; + version = "0.2.0"; + edition = "2021"; + sha256 = "03mf2z1xcy2slhhsm15z24p76qxgm2m74xdjp8bihyag47c4640x"; + libName = "windows_result"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; + "windows-strings" = rec { + crateName = "windows-strings"; + version = "0.1.0"; + edition = "2021"; + sha256 = "042dxvi3133f7dyi2pgcvknwkikk47k8bddwxbq5s0l6qhjv3nac"; + libName = "windows_strings"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-result"; + packageId = "windows-result 0.2.0"; + usesDefaultFeatures = false; + } + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; } ]; features = { @@ -19049,6 +18201,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -19335,20 +18488,21 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_Registry" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_Time" "Win32_System_WindowsProgramming" "default" ]; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Console" "Win32_System_IO" "Win32_System_Pipes" "Win32_System_Threading" "Win32_System_WindowsProgramming" "default" ]; }; "windows-sys 0.52.0" = rec { crateName = "windows-sys"; version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows-targets"; - packageId = "windows-targets 0.52.5"; + packageId = "windows-targets 0.52.6"; } ]; features = { @@ -19582,13 +18736,273 @@ rec { "Win32_Web" = [ "Win32" ]; "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; }; - resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; + resolvedDefaultFeatures = [ "Wdk" "Wdk_Foundation" "Wdk_Storage" "Wdk_Storage_FileSystem" "Wdk_System" "Wdk_System_IO" "Win32" "Win32_Foundation" "Win32_NetworkManagement" "Win32_NetworkManagement_IpHelper" "Win32_Networking" "Win32_Networking_WinSock" "Win32_Security" "Win32_Security_Authentication" "Win32_Security_Authentication_Identity" "Win32_Security_Credentials" "Win32_Security_Cryptography" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Com" "Win32_System_Console" "Win32_System_Diagnostics" "Win32_System_Diagnostics_Debug" "Win32_System_IO" "Win32_System_LibraryLoader" "Win32_System_Memory" "Win32_System_Pipes" "Win32_System_SystemServices" "Win32_System_Threading" "Win32_System_WindowsProgramming" "Win32_UI" "Win32_UI_Input" "Win32_UI_Input_KeyboardAndMouse" "Win32_UI_Shell" "default" ]; + }; + "windows-sys 0.59.0" = rec { + crateName = "windows-sys"; + version = "0.59.0"; + edition = "2021"; + sha256 = "0fw5672ziw8b3zpmnbp9pdv1famk74f1l9fcbc3zsrzdg56vqf0y"; + libName = "windows_sys"; + authors = [ + "Microsoft" + ]; + dependencies = [ + { + name = "windows-targets"; + packageId = "windows-targets 0.52.6"; + } + ]; + features = { + "Wdk" = [ "Win32_Foundation" ]; + "Wdk_Devices" = [ "Wdk" ]; + "Wdk_Devices_Bluetooth" = [ "Wdk_Devices" ]; + "Wdk_Devices_HumanInterfaceDevice" = [ "Wdk_Devices" ]; + "Wdk_Foundation" = [ "Wdk" ]; + "Wdk_Graphics" = [ "Wdk" ]; + "Wdk_Graphics_Direct3D" = [ "Wdk_Graphics" ]; + "Wdk_NetworkManagement" = [ "Wdk" ]; + "Wdk_NetworkManagement_Ndis" = [ "Wdk_NetworkManagement" ]; + "Wdk_NetworkManagement_WindowsFilteringPlatform" = [ "Wdk_NetworkManagement" ]; + "Wdk_Storage" = [ "Wdk" ]; + "Wdk_Storage_FileSystem" = [ "Wdk_Storage" ]; + "Wdk_Storage_FileSystem_Minifilters" = [ "Wdk_Storage_FileSystem" ]; + "Wdk_System" = [ "Wdk" ]; + "Wdk_System_IO" = [ "Wdk_System" ]; + "Wdk_System_Memory" = [ "Wdk_System" ]; + "Wdk_System_OfflineRegistry" = [ "Wdk_System" ]; + "Wdk_System_Registry" = [ "Wdk_System" ]; + "Wdk_System_SystemInformation" = [ "Wdk_System" ]; + "Wdk_System_SystemServices" = [ "Wdk_System" ]; + "Wdk_System_Threading" = [ "Wdk_System" ]; + "Win32" = [ "Win32_Foundation" ]; + "Win32_Data" = [ "Win32" ]; + "Win32_Data_HtmlHelp" = [ "Win32_Data" ]; + "Win32_Data_RightsManagement" = [ "Win32_Data" ]; + "Win32_Devices" = [ "Win32" ]; + "Win32_Devices_AllJoyn" = [ "Win32_Devices" ]; + "Win32_Devices_BiometricFramework" = [ "Win32_Devices" ]; + "Win32_Devices_Bluetooth" = [ "Win32_Devices" ]; + "Win32_Devices_Communication" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceAndDriverInstallation" = [ "Win32_Devices" ]; + "Win32_Devices_DeviceQuery" = [ "Win32_Devices" ]; + "Win32_Devices_Display" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration" = [ "Win32_Devices" ]; + "Win32_Devices_Enumeration_Pnp" = [ "Win32_Devices_Enumeration" ]; + "Win32_Devices_Fax" = [ "Win32_Devices" ]; + "Win32_Devices_HumanInterfaceDevice" = [ "Win32_Devices" ]; + "Win32_Devices_PortableDevices" = [ "Win32_Devices" ]; + "Win32_Devices_Properties" = [ "Win32_Devices" ]; + "Win32_Devices_Pwm" = [ "Win32_Devices" ]; + "Win32_Devices_Sensors" = [ "Win32_Devices" ]; + "Win32_Devices_SerialCommunication" = [ "Win32_Devices" ]; + "Win32_Devices_Tapi" = [ "Win32_Devices" ]; + "Win32_Devices_Usb" = [ "Win32_Devices" ]; + "Win32_Devices_WebServicesOnDevices" = [ "Win32_Devices" ]; + "Win32_Foundation" = [ "Win32" ]; + "Win32_Gaming" = [ "Win32" ]; + "Win32_Globalization" = [ "Win32" ]; + "Win32_Graphics" = [ "Win32" ]; + "Win32_Graphics_Dwm" = [ "Win32_Graphics" ]; + "Win32_Graphics_Gdi" = [ "Win32_Graphics" ]; + "Win32_Graphics_GdiPlus" = [ "Win32_Graphics" ]; + "Win32_Graphics_Hlsl" = [ "Win32_Graphics" ]; + "Win32_Graphics_OpenGL" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing" = [ "Win32_Graphics" ]; + "Win32_Graphics_Printing_PrintTicket" = [ "Win32_Graphics_Printing" ]; + "Win32_Management" = [ "Win32" ]; + "Win32_Management_MobileDeviceManagementRegistration" = [ "Win32_Management" ]; + "Win32_Media" = [ "Win32" ]; + "Win32_Media_Audio" = [ "Win32_Media" ]; + "Win32_Media_DxMediaObjects" = [ "Win32_Media" ]; + "Win32_Media_KernelStreaming" = [ "Win32_Media" ]; + "Win32_Media_Multimedia" = [ "Win32_Media" ]; + "Win32_Media_Streaming" = [ "Win32_Media" ]; + "Win32_Media_WindowsMediaFormat" = [ "Win32_Media" ]; + "Win32_NetworkManagement" = [ "Win32" ]; + "Win32_NetworkManagement_Dhcp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Dns" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_InternetConnectionWizard" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_IpHelper" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Multicast" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Ndis" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetBios" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetManagement" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetShell" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_NetworkDiagnosticsFramework" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_P2P" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_QoS" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Rras" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_Snmp" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WNet" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WebDav" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WiFi" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsConnectionManager" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFilteringPlatform" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsFirewall" = [ "Win32_NetworkManagement" ]; + "Win32_NetworkManagement_WindowsNetworkVirtualization" = [ "Win32_NetworkManagement" ]; + "Win32_Networking" = [ "Win32" ]; + "Win32_Networking_ActiveDirectory" = [ "Win32_Networking" ]; + "Win32_Networking_Clustering" = [ "Win32_Networking" ]; + "Win32_Networking_HttpServer" = [ "Win32_Networking" ]; + "Win32_Networking_Ldap" = [ "Win32_Networking" ]; + "Win32_Networking_WebSocket" = [ "Win32_Networking" ]; + "Win32_Networking_WinHttp" = [ "Win32_Networking" ]; + "Win32_Networking_WinInet" = [ "Win32_Networking" ]; + "Win32_Networking_WinSock" = [ "Win32_Networking" ]; + "Win32_Networking_WindowsWebServices" = [ "Win32_Networking" ]; + "Win32_Security" = [ "Win32" ]; + "Win32_Security_AppLocker" = [ "Win32_Security" ]; + "Win32_Security_Authentication" = [ "Win32_Security" ]; + "Win32_Security_Authentication_Identity" = [ "Win32_Security_Authentication" ]; + "Win32_Security_Authorization" = [ "Win32_Security" ]; + "Win32_Security_Credentials" = [ "Win32_Security" ]; + "Win32_Security_Cryptography" = [ "Win32_Security" ]; + "Win32_Security_Cryptography_Catalog" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Certificates" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_Sip" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_Cryptography_UI" = [ "Win32_Security_Cryptography" ]; + "Win32_Security_DiagnosticDataQuery" = [ "Win32_Security" ]; + "Win32_Security_DirectoryServices" = [ "Win32_Security" ]; + "Win32_Security_EnterpriseData" = [ "Win32_Security" ]; + "Win32_Security_ExtensibleAuthenticationProtocol" = [ "Win32_Security" ]; + "Win32_Security_Isolation" = [ "Win32_Security" ]; + "Win32_Security_LicenseProtection" = [ "Win32_Security" ]; + "Win32_Security_NetworkAccessProtection" = [ "Win32_Security" ]; + "Win32_Security_WinTrust" = [ "Win32_Security" ]; + "Win32_Security_WinWlx" = [ "Win32_Security" ]; + "Win32_Storage" = [ "Win32" ]; + "Win32_Storage_Cabinets" = [ "Win32_Storage" ]; + "Win32_Storage_CloudFilters" = [ "Win32_Storage" ]; + "Win32_Storage_Compression" = [ "Win32_Storage" ]; + "Win32_Storage_DistributedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_FileHistory" = [ "Win32_Storage" ]; + "Win32_Storage_FileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_Imapi" = [ "Win32_Storage" ]; + "Win32_Storage_IndexServer" = [ "Win32_Storage" ]; + "Win32_Storage_InstallableFileSystems" = [ "Win32_Storage" ]; + "Win32_Storage_IscsiDisc" = [ "Win32_Storage" ]; + "Win32_Storage_Jet" = [ "Win32_Storage" ]; + "Win32_Storage_Nvme" = [ "Win32_Storage" ]; + "Win32_Storage_OfflineFiles" = [ "Win32_Storage" ]; + "Win32_Storage_OperationRecorder" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging" = [ "Win32_Storage" ]; + "Win32_Storage_Packaging_Appx" = [ "Win32_Storage_Packaging" ]; + "Win32_Storage_ProjectedFileSystem" = [ "Win32_Storage" ]; + "Win32_Storage_StructuredStorage" = [ "Win32_Storage" ]; + "Win32_Storage_Vhd" = [ "Win32_Storage" ]; + "Win32_Storage_Xps" = [ "Win32_Storage" ]; + "Win32_System" = [ "Win32" ]; + "Win32_System_AddressBook" = [ "Win32_System" ]; + "Win32_System_Antimalware" = [ "Win32_System" ]; + "Win32_System_ApplicationInstallationAndServicing" = [ "Win32_System" ]; + "Win32_System_ApplicationVerifier" = [ "Win32_System" ]; + "Win32_System_ClrHosting" = [ "Win32_System" ]; + "Win32_System_Com" = [ "Win32_System" ]; + "Win32_System_Com_Marshal" = [ "Win32_System_Com" ]; + "Win32_System_Com_StructuredStorage" = [ "Win32_System_Com" ]; + "Win32_System_Com_Urlmon" = [ "Win32_System_Com" ]; + "Win32_System_ComponentServices" = [ "Win32_System" ]; + "Win32_System_Console" = [ "Win32_System" ]; + "Win32_System_CorrelationVector" = [ "Win32_System" ]; + "Win32_System_DataExchange" = [ "Win32_System" ]; + "Win32_System_DeploymentServices" = [ "Win32_System" ]; + "Win32_System_DeveloperLicensing" = [ "Win32_System" ]; + "Win32_System_Diagnostics" = [ "Win32_System" ]; + "Win32_System_Diagnostics_Ceip" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_Debug_Extensions" = [ "Win32_System_Diagnostics_Debug" ]; + "Win32_System_Diagnostics_Etw" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ProcessSnapshotting" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_ToolHelp" = [ "Win32_System_Diagnostics" ]; + "Win32_System_Diagnostics_TraceLogging" = [ "Win32_System_Diagnostics" ]; + "Win32_System_DistributedTransactionCoordinator" = [ "Win32_System" ]; + "Win32_System_Environment" = [ "Win32_System" ]; + "Win32_System_ErrorReporting" = [ "Win32_System" ]; + "Win32_System_EventCollector" = [ "Win32_System" ]; + "Win32_System_EventLog" = [ "Win32_System" ]; + "Win32_System_EventNotificationService" = [ "Win32_System" ]; + "Win32_System_GroupPolicy" = [ "Win32_System" ]; + "Win32_System_HostCompute" = [ "Win32_System" ]; + "Win32_System_HostComputeNetwork" = [ "Win32_System" ]; + "Win32_System_HostComputeSystem" = [ "Win32_System" ]; + "Win32_System_Hypervisor" = [ "Win32_System" ]; + "Win32_System_IO" = [ "Win32_System" ]; + "Win32_System_Iis" = [ "Win32_System" ]; + "Win32_System_Ioctl" = [ "Win32_System" ]; + "Win32_System_JobObjects" = [ "Win32_System" ]; + "Win32_System_Js" = [ "Win32_System" ]; + "Win32_System_Kernel" = [ "Win32_System" ]; + "Win32_System_LibraryLoader" = [ "Win32_System" ]; + "Win32_System_Mailslots" = [ "Win32_System" ]; + "Win32_System_Mapi" = [ "Win32_System" ]; + "Win32_System_Memory" = [ "Win32_System" ]; + "Win32_System_Memory_NonVolatile" = [ "Win32_System_Memory" ]; + "Win32_System_MessageQueuing" = [ "Win32_System" ]; + "Win32_System_MixedReality" = [ "Win32_System" ]; + "Win32_System_Ole" = [ "Win32_System" ]; + "Win32_System_PasswordManagement" = [ "Win32_System" ]; + "Win32_System_Performance" = [ "Win32_System" ]; + "Win32_System_Performance_HardwareCounterProfiling" = [ "Win32_System_Performance" ]; + "Win32_System_Pipes" = [ "Win32_System" ]; + "Win32_System_Power" = [ "Win32_System" ]; + "Win32_System_ProcessStatus" = [ "Win32_System" ]; + "Win32_System_Recovery" = [ "Win32_System" ]; + "Win32_System_Registry" = [ "Win32_System" ]; + "Win32_System_RemoteDesktop" = [ "Win32_System" ]; + "Win32_System_RemoteManagement" = [ "Win32_System" ]; + "Win32_System_RestartManager" = [ "Win32_System" ]; + "Win32_System_Restore" = [ "Win32_System" ]; + "Win32_System_Rpc" = [ "Win32_System" ]; + "Win32_System_Search" = [ "Win32_System" ]; + "Win32_System_Search_Common" = [ "Win32_System_Search" ]; + "Win32_System_SecurityCenter" = [ "Win32_System" ]; + "Win32_System_Services" = [ "Win32_System" ]; + "Win32_System_SetupAndMigration" = [ "Win32_System" ]; + "Win32_System_Shutdown" = [ "Win32_System" ]; + "Win32_System_StationsAndDesktops" = [ "Win32_System" ]; + "Win32_System_SubsystemForLinux" = [ "Win32_System" ]; + "Win32_System_SystemInformation" = [ "Win32_System" ]; + "Win32_System_SystemServices" = [ "Win32_System" ]; + "Win32_System_Threading" = [ "Win32_System" ]; + "Win32_System_Time" = [ "Win32_System" ]; + "Win32_System_TpmBaseServices" = [ "Win32_System" ]; + "Win32_System_UserAccessLogging" = [ "Win32_System" ]; + "Win32_System_Variant" = [ "Win32_System" ]; + "Win32_System_VirtualDosMachines" = [ "Win32_System" ]; + "Win32_System_WindowsProgramming" = [ "Win32_System" ]; + "Win32_System_Wmi" = [ "Win32_System" ]; + "Win32_UI" = [ "Win32" ]; + "Win32_UI_Accessibility" = [ "Win32_UI" ]; + "Win32_UI_ColorSystem" = [ "Win32_UI" ]; + "Win32_UI_Controls" = [ "Win32_UI" ]; + "Win32_UI_Controls_Dialogs" = [ "Win32_UI_Controls" ]; + "Win32_UI_HiDpi" = [ "Win32_UI" ]; + "Win32_UI_Input" = [ "Win32_UI" ]; + "Win32_UI_Input_Ime" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_KeyboardAndMouse" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Pointer" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_Touch" = [ "Win32_UI_Input" ]; + "Win32_UI_Input_XboxController" = [ "Win32_UI_Input" ]; + "Win32_UI_InteractionContext" = [ "Win32_UI" ]; + "Win32_UI_Magnification" = [ "Win32_UI" ]; + "Win32_UI_Shell" = [ "Win32_UI" ]; + "Win32_UI_Shell_Common" = [ "Win32_UI_Shell" ]; + "Win32_UI_Shell_PropertiesSystem" = [ "Win32_UI_Shell" ]; + "Win32_UI_TabletPC" = [ "Win32_UI" ]; + "Win32_UI_TextServices" = [ "Win32_UI" ]; + "Win32_UI_WindowsAndMessaging" = [ "Win32_UI" ]; + "Win32_Web" = [ "Win32" ]; + "Win32_Web_InternetExplorer" = [ "Win32_Web" ]; + }; + resolvedDefaultFeatures = [ "Win32" "Win32_Foundation" "Win32_Storage" "Win32_Storage_FileSystem" "Win32_System" "Win32_System_Threading" "default" ]; }; "windows-targets 0.48.5" = rec { crateName = "windows-targets"; version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -19631,28 +19045,29 @@ rec { ]; }; - "windows-targets 0.52.5" = rec { + "windows-targets 0.52.6" = rec { crateName = "windows-targets"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1sz7jrnkygmmlj1ia8fk85wbyil450kq5qkh5qh9sh2rcnj161vg"; + sha256 = "0wwrx625nwlfp7k93r2rra568gad1mwd888h1jwnl0vfg5r4ywlv"; + libName = "windows_targets"; authors = [ "Microsoft" ]; dependencies = [ { name = "windows_aarch64_gnullvm"; - packageId = "windows_aarch64_gnullvm 0.52.5"; + packageId = "windows_aarch64_gnullvm 0.52.6"; target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; - packageId = "windows_aarch64_msvc 0.52.5"; + packageId = "windows_aarch64_msvc 0.52.6"; target = { target, features }: (("aarch64" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_i686_gnu"; - packageId = "windows_i686_gnu 0.52.5"; + packageId = "windows_i686_gnu 0.52.6"; target = { target, features }: (("x86" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { @@ -19662,22 +19077,22 @@ rec { } { name = "windows_i686_msvc"; - packageId = "windows_i686_msvc 0.52.5"; + packageId = "windows_i686_msvc 0.52.6"; target = { target, features }: (("x86" == target."arch" or null) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnu"; - packageId = "windows_x86_64_gnu 0.52.5"; + packageId = "windows_x86_64_gnu 0.52.6"; target = { target, features }: (("x86_64" == target."arch" or null) && ("gnu" == target."env" or null) && (!("llvm" == target."abi" or null)) && (!(target."windows_raw_dylib" or false))); } { name = "windows_x86_64_gnullvm"; - packageId = "windows_x86_64_gnullvm 0.52.5"; + packageId = "windows_x86_64_gnullvm 0.52.6"; target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; - packageId = "windows_x86_64_msvc 0.52.5"; + packageId = "windows_x86_64_msvc 0.52.6"; target = { target, features }: ((("x86_64" == target."arch" or null) || ("arm64ec" == target."arch" or null)) && ("msvc" == target."env" or null) && (!(target."windows_raw_dylib" or false))); } ]; @@ -19693,11 +19108,11 @@ rec { ]; }; - "windows_aarch64_gnullvm 0.52.5" = rec { + "windows_aarch64_gnullvm 0.52.6" = rec { crateName = "windows_aarch64_gnullvm"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "0qrjimbj67nnyn7zqy15mzzmqg0mn5gsr2yciqjxm3cb3vbyx23h"; + sha256 = "1lrcq38cr2arvmz19v32qaggvj8bh1640mdm9c2fr877h0hn591j"; authors = [ "Microsoft" ]; @@ -19713,11 +19128,11 @@ rec { ]; }; - "windows_aarch64_msvc 0.52.5" = rec { + "windows_aarch64_msvc 0.52.6" = rec { crateName = "windows_aarch64_msvc"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1dmga8kqlmln2ibckk6mxc9n59vdg8ziqa2zr8awcl720hazv1cr"; + sha256 = "0sfl0nysnz32yyfh773hpi49b1q700ah6y7sacmjbqjjn5xjmv09"; authors = [ "Microsoft" ]; @@ -19733,11 +19148,11 @@ rec { ]; }; - "windows_i686_gnu 0.52.5" = rec { + "windows_i686_gnu 0.52.6" = rec { crateName = "windows_i686_gnu"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "0w4np3l6qwlra9s2xpflqrs60qk1pz6ahhn91rr74lvdy4y0gfl8"; + sha256 = "02zspglbykh1jh9pi7gn8g1f97jh1rrccni9ivmrfbl0mgamm6wf"; authors = [ "Microsoft" ]; @@ -19745,9 +19160,9 @@ rec { }; "windows_i686_gnullvm" = rec { crateName = "windows_i686_gnullvm"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1s9f4gff0cixd86mw3n63rpmsm4pmr4ffndl6s7qa2h35492dx47"; + sha256 = "0rpdx1537mw6slcpqa0rm3qixmsb79nbhqy5fsm3q2q9ik9m5vhf"; authors = [ "Microsoft" ]; @@ -19763,11 +19178,11 @@ rec { ]; }; - "windows_i686_msvc 0.52.5" = rec { + "windows_i686_msvc 0.52.6" = rec { crateName = "windows_i686_msvc"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1gw7fklxywgpnwbwg43alb4hm0qjmx72hqrlwy5nanrxs7rjng6v"; + sha256 = "0rkcqmp4zzmfvrrrx01260q3xkpzi6fzi2x2pgdcdry50ny4h294"; authors = [ "Microsoft" ]; @@ -19783,11 +19198,11 @@ rec { ]; }; - "windows_x86_64_gnu 0.52.5" = rec { + "windows_x86_64_gnu 0.52.6" = rec { crateName = "windows_x86_64_gnu"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1n8p2mcf3lw6300k77a0knksssmgwb9hynl793mhkzyydgvlchjf"; + sha256 = "0y0sifqcb56a56mvn7xjgs8g43p33mfqkd8wj1yhrgxzma05qyhl"; authors = [ "Microsoft" ]; @@ -19803,11 +19218,11 @@ rec { ]; }; - "windows_x86_64_gnullvm 0.52.5" = rec { + "windows_x86_64_gnullvm 0.52.6" = rec { crateName = "windows_x86_64_gnullvm"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "15n56jrh4s5bz66zimavr1rmcaw6wa306myrvmbc6rydhbj9h8l5"; + sha256 = "03gda7zjx1qh8k9nnlgb7m3w3s1xkysg55hkd1wjch8pqhyv5m94"; authors = [ "Microsoft" ]; @@ -19823,11 +19238,11 @@ rec { ]; }; - "windows_x86_64_msvc 0.52.5" = rec { + "windows_x86_64_msvc 0.52.6" = rec { crateName = "windows_x86_64_msvc"; - version = "0.52.5"; + version = "0.52.6"; edition = "2021"; - sha256 = "1w1bn24ap8dp9i85s8mlg8cim2bl2368bd6qyvm0xzqvzmdpxi5y"; + sha256 = "1v7rb5cibyzx8vak29pdrk8nx9hycsjs4w0jgms08qk49jl6v7sq"; authors = [ "Microsoft" ]; @@ -19835,9 +19250,9 @@ rec { }; "winnow" = rec { crateName = "winnow"; - version = "0.6.14"; + version = "0.6.18"; edition = "2021"; - sha256 = "0bz2nmp7mqbz7z5z41p9gdimcwsmrmg4gnbj94dkqykn5l5c8kip"; + sha256 = "0vrsrnf2nm9jsk1161x1vacmi3ns4h3h10fib91rs28zd6jbvab8"; dependencies = [ { name = "memchr"; @@ -19855,31 +19270,6 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; - "winreg" = rec { - crateName = "winreg"; - version = "0.52.0"; - edition = "2018"; - sha256 = "19gh9vp7mp1ab84kc3ag48nm9y7xgjhh3xa4vxss1gylk1rsaxx2"; - authors = [ - "Igor Shaula <gentoo90@gmail.com>" - ]; - dependencies = [ - { - name = "cfg-if"; - packageId = "cfg-if"; - } - { - name = "windows-sys"; - packageId = "windows-sys 0.48.0"; - features = [ "Win32_Foundation" "Win32_System_Time" "Win32_System_Registry" "Win32_Security" "Win32_Storage_FileSystem" "Win32_System_Diagnostics_Debug" ]; - } - ]; - features = { - "chrono" = [ "dep:chrono" ]; - "serde" = [ "dep:serde" ]; - "serialization-serde" = [ "transactions" "serde" ]; - }; - }; "wu-manber" = rec { crateName = "wu-manber"; version = "0.1.0"; @@ -19890,6 +19280,7 @@ rec { rev = "0d5b22bea136659f7de60b102a7030e0daaa503d"; sha256 = "1zhk83lbq99xzyjwphv2qrb8f8qgfqwa5bbbvyzm0z0bljsjv0pd"; }; + libName = "wu_manber"; authors = [ "Joe Neeman <joeneeman@gmail.com>" ]; @@ -20009,6 +19400,7 @@ rec { edition = "2018"; sha256 = "0fqvglw01w3hp7xj9gdk1800x9j7v58s9w8ijiyiz2a7krb39s8m"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -20023,7 +19415,7 @@ rec { } { name = "syn"; - packageId = "syn 2.0.48"; + packageId = "syn 2.0.76"; } ]; @@ -20047,9 +19439,9 @@ rec { }; "zstd" = rec { crateName = "zstd"; - version = "0.13.0"; + version = "0.13.2"; edition = "2018"; - sha256 = "0401q54s9r35x2i7m1kwppgkj79g0pb6xz3xpby7qlkdb44k7yxz"; + sha256 = "1ygkr6wspm9clbp7ykyl0rv69cfsf9q4lic9wcqiwn34lrwbgwpw"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -20080,9 +19472,10 @@ rec { }; "zstd-safe" = rec { crateName = "zstd-safe"; - version = "7.0.0"; + version = "7.2.1"; edition = "2018"; - sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + sha256 = "0nch85m5cr493y26yvndm6a8j6sd9mxpr2awrim3dslcnr6sp8sl"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -20112,10 +19505,11 @@ rec { }; "zstd-sys" = rec { crateName = "zstd-sys"; - version = "2.0.9+zstd.1.5.5"; + version = "2.0.13+zstd.1.5.6"; edition = "2018"; links = "zstd"; - sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + sha256 = "1almbackh06am0d2kc4a089n3al91jg3ahgg9kcrg3zfrwhhzzrq"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; diff --git a/tvix/Cargo.toml b/tvix/Cargo.toml index 53b9134a567b..7387bf2424f2 100644 --- a/tvix/Cargo.toml +++ b/tvix/Cargo.toml @@ -27,6 +27,8 @@ members = [ "glue", "nar-bridge", "nix-compat", + "nix-compat-derive", + "nix-compat-derive-tests", "serde", "store", "tracing", @@ -37,6 +39,128 @@ members = [ # https://github.com/rust-lang/rust-clippy/issues/12281 blocks_in_conditions = "allow" +[workspace.dependencies] +anyhow = "1.0.86" +async-compression = "0.4.12" +async-process = "2.2.4" +async-stream = "0.3.5" +async-tempfile = "0.4.0" +axum = "0.7.5" +# https://github.com/liufuyang/bigtable_rs/pull/86 +bigtable_rs = { git = "https://github.com/liufuyang/bigtable_rs", rev = "1818355a5373a5bc2c84287e3a4e3807154ac8ef" } +bitflags = "2.6.0" +blake3 = "1.5.4" +bstr = "1.10.0" +bytes = "1.7.1" +clap = "4.5.16" +codemap = "0.1.3" +codemap-diagnostic = "0.1.2" +count-write = "0.1.0" +criterion = "0.5" +data-encoding = "2.6.0" +digest = "0.10.7" +dirs = "4.0.0" +ed25519 = "2.2.3" +ed25519-dalek = "2.1.1" +enum-primitive-derive = "0.3.0" +erased-serde = "0.4.5" +expect-test = "1.5.0" +fastcdc = "3.1.0" +fuse-backend-rs = "0.11.0" +futures = "0.3.30" +genawaiter = { version = "0.99.1", default-features = false } +glob = "0.3.1" +hex-literal = "0.4.1" +http = "1.1.0" +hyper-util = "0.1.7" +indicatif = "0.17.8" +itertools = "0.12.1" +lazy_static = "1.5.0" +lexical-core = "0.8.5" +libc = "0.2.158" +lru = "0.12.4" +magic = "0.16.2" +md-5 = "0.10.6" +mimalloc = "0.1.43" +nix = "0.27.1" +nohash-hasher = "0.2.0" +nom = "7.1.3" +num-traits = "0.2.19" +object_store = "0.10.2" +opentelemetry = "0.24.0" +opentelemetry-http = "0.13.0" +opentelemetry-otlp = "0.17.0" +opentelemetry_sdk = "0.24.1" +os_str_bytes = "6.6" +parking_lot = "0.12.3" +path-clean = "0.1" +petgraph = "0.6.5" +pin-project = "1.1" +pin-project-lite = "0.2.14" +pretty_assertions = "1.4.0" +proc-macro2 = "1.0.86" +proptest = { version = "1.5.0", default-features = false } +prost = "0.13.1" +prost-build = "0.13.1" +quote = "1.0.37" +redb = "2.1.2" +regex = "1.10.6" +reqwest = { version = "0.12.7", default-features = false } +reqwest-middleware = "0.3.3" +reqwest-tracing = { version = "0.5.3", default-features = false } +rnix = "0.11.0" +rowan = "*" +rstest = "0.19.0" +rstest_reuse = "0.6.0" +rustc-hash = "2.0.0" +rustyline = "10.1.1" +serde = "1.0.209" +serde_json = "1.0" +serde_qs = "0.12.0" +serde_tagged = "0.3.0" +serde_with = "3.9.0" +sha1 = "0.10.6" +sha2 = "0.10.8" +sled = "0.34.7" +smol_str = "0.2.2" +tabwriter = "1.4" +tempfile = "3.12.0" +test-strategy = "0.2.1" +thiserror = "1.0.63" +threadpool = "1.8.1" +tokio = "1.39.3" +tokio-listener = "0.4.3" +tokio-retry = "0.3.0" +tokio-stream = "0.1.15" +tokio-tar = "0.3.1" +tokio-test = "0.4.4" +tokio-util = "0.7.11" +tonic = "0.12.2" +tonic-build = "0.12.2" +tonic-health = { version = "0.12.2", default-features = false } +tonic-reflection = "0.12.2" +tower = "0.4.13" +tower-http = "0.5.2" +tracing = "0.1.40" +tracing-indicatif = "0.3.6" +tracing-opentelemetry = "0.25.0" +tracing-subscriber = "0.3.18" +tracing-tracy = "0.11.2" +trybuild = "1.0.99" +url = "2.5.2" +vhost = "0.6" +vhost-user-backend = "0.8" +virtio-bindings = "0.2.2" +virtio-queue = "0.7" +vm-memory = "0.10" +vmm-sys-util = "0.11" +vu128 = "1.1.0" +walkdir = "2.5.0" +# https://github.com/jneem/wu-manber/pull/1 +wu-manber = { git = "https://github.com/tvlfyi/wu-manber.git" } +xattr = "1.3.1" +zstd = "0.13.2" + # Add a profile to all targets that enables release optimisations, but # retains debug symbols. This is great for use with # benchmarking/profiling tools. diff --git a/tvix/boot/default.nix b/tvix/boot/default.nix index 7be05c815cdc..60eb2f1b7608 100644 --- a/tvix/boot/default.nix +++ b/tvix/boot/default.nix @@ -1,13 +1,16 @@ -{ depot, pkgs, ... }: +{ lib, pkgs, ... }: rec { # A binary that sets up /nix/store from virtiofs, lists all store paths, and # powers off the machine. - tvix-init = depot.nix.buildGo.program { + tvix-init = pkgs.buildGoModule rec { name = "tvix-init"; - srcs = [ - ./tvix-init.go - ]; + src = lib.fileset.toSource { + root = ./.; + fileset = ./tvix-init.go; + }; + vendorHash = null; + postPatch = "go mod init ${name}"; }; # A kernel with virtiofs support baked in diff --git a/tvix/boot/tests/default.nix b/tvix/boot/tests/default.nix index 7b9fbbbf8c57..97477572078e 100644 --- a/tvix/boot/tests/default.nix +++ b/tvix/boot/tests/default.nix @@ -119,14 +119,20 @@ let grep "${assertVMOutput}" output.txt ''; requiredSystemFeatures = [ "kvm" ]; + # HACK: The boot tests are sometimes flaky, and we don't want them to + # periodically fail other build. Have Buildkite auto-retry them 2 times + # on failure. + # Logs for individual failures are still available, so it won't hinder + # flakiness debuggability. + meta.ci.buildkiteExtraStepArgs = { + retry.automatic = true; + }; } // lib.optionalAttrs (isClosure && !useNarBridge) { __structuredAttrs = true; exportReferencesGraph.closure = [ path ]; }); - systemFor = sys: (depot.ops.nixos.nixosFor sys).system; - - testSystem = systemFor ({ modulesPath, pkgs, ... }: { + testSystem = (pkgs.nixos { # Set some options necessary to evaluate. boot.loader.systemd-boot.enable = true; # TODO: figure out how to disable this without causing eval to fail @@ -146,7 +152,10 @@ let # Don't warn about stateVersion. system.stateVersion = "24.05"; - }); + + # Speed-up evaluation and building. + documentation.enable = lib.mkForce false; + }).config.system.build.toplevel; in depot.nix.readTree.drvTargets diff --git a/tvix/build-go/build.pb.go b/tvix/build-go/build.pb.go index 84e866513f6f..c1fbf28b547a 100644 --- a/tvix/build-go/build.pb.go +++ b/tvix/build-go/build.pb.go @@ -66,8 +66,8 @@ type BuildRequest struct { // The list of all root nodes that should be visible in `inputs_dir` at the // time of the build. - // As root nodes are content-addressed, no additional signatures are needed - // to substitute / make these available in the build environment. + // As all references are content-addressed, no additional signatures are + // needed to substitute / make these available in the build environment. // Inputs MUST be sorted by their names. Inputs []*castore_go.Node `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` // The command (and its args) executed as the build script. diff --git a/tvix/build/Cargo.toml b/tvix/build/Cargo.toml index 8bb68783f0ea..b9073b7ff61a 100644 --- a/tvix/build/Cargo.toml +++ b/tvix/build/Cargo.toml @@ -4,34 +4,31 @@ version = "0.1.0" edition = "2021" [dependencies] -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -itertools = "0.12.0" -prost = "0.13.1" -thiserror = "1.0.56" -tokio = { version = "1.32.0" } -tokio-listener = { version = "0.4.1", features = [ "tonic012" ] } -tonic = { version = "0.12.0", features = ["tls", "tls-roots"] } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +itertools = { workspace = true } +prost = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tokio-listener = { workspace = true, features = ["tonic012"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } tvix-castore = { path = "../castore" } tvix-tracing = { path = "../tracing" } -tracing = "0.1.40" -url = "2.4.0" -mimalloc = "0.1.43" - -[dependencies.tonic-reflection] -optional = true -version = "0.12.0" +tracing = { workspace = true } +url = { workspace = true } +mimalloc = { workspace = true } +tonic-reflection = { workspace = true, optional = true } [build-dependencies] -prost-build = "0.13.1" -tonic-build = "0.12.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [features] default = [] tonic-reflection = ["dep:tonic-reflection", "tvix-castore/tonic-reflection"] [dev-dependencies] -rstest = "0.19.0" +rstest = { workspace = true } [lints] workspace = true diff --git a/tvix/build/build.rs b/tvix/build/build.rs index 09604c3e3b71..fe230cbeca8a 100644 --- a/tvix/build/build.rs +++ b/tvix/build/build.rs @@ -25,7 +25,7 @@ fn main() -> Result<()> { ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), diff --git a/tvix/build/default.nix b/tvix/build/default.nix index aafab92fd525..17b52354bbeb 100644 --- a/tvix/build/default.nix +++ b/tvix/build/default.nix @@ -4,8 +4,8 @@ runTests = true; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "tonic-reflection" ]; - }; + }); }) diff --git a/tvix/build/protos/build.proto b/tvix/build/protos/build.proto index f1f6bf0b05d8..7a3c49db4873 100644 --- a/tvix/build/protos/build.proto +++ b/tvix/build/protos/build.proto @@ -47,8 +47,8 @@ option go_package = "code.tvl.fyi/tvix/build-go;buildv1"; message BuildRequest { // The list of all root nodes that should be visible in `inputs_dir` at the // time of the build. - // As root nodes are content-addressed, no additional signatures are needed - // to substitute / make these available in the build environment. + // As all references are content-addressed, no additional signatures are + // needed to substitute / make these available in the build environment. // Inputs MUST be sorted by their names. repeated tvix.castore.v1.Node inputs = 1; diff --git a/tvix/build/protos/default.nix b/tvix/build/protos/default.nix index 790655ac7522..287b513136c9 100644 --- a/tvix/build/protos/default.nix +++ b/tvix/build/protos/default.nix @@ -1,17 +1,12 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "build-protos"; - root = depot.path.origSrc; - paths = [ - # We need to include castore.proto (only), as it's referred. - ../../castore/protos/castore.proto - ./build.proto - ./rpc_build.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + # We need to include castore.proto (only), as it's referred. + "^tvix(/castore(/protos(/castore\.proto)?)?)?$" + "^tvix(/build(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/build/src/bin/tvix-build.rs b/tvix/build/src/bin/tvix-build.rs index 93e85871caab..b840e031db80 100644 --- a/tvix/build/src/bin/tvix-build.rs +++ b/tvix/build/src/bin/tvix-build.rs @@ -90,11 +90,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> { #[cfg(feature = "tonic-reflection")] { - let reflection_svc = tonic_reflection::server::Builder::configure() - .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) - .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) - .build()?; - router = router.add_service(reflection_svc); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1alpha()?, + ); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1()?, + ); } info!(listen_address=%listen_address, "listening"); diff --git a/tvix/build/src/proto/mod.rs b/tvix/build/src/proto/mod.rs index e359b5b5b70e..b36049d05b9d 100644 --- a/tvix/build/src/proto/mod.rs +++ b/tvix/build/src/proto/mod.rs @@ -1,7 +1,7 @@ use std::path::{Path, PathBuf}; use itertools::Itertools; -use tvix_castore::proto::{NamedNode, ValidateNodeError}; +use tvix_castore::DirectoryError; mod grpc_buildservice_wrapper; @@ -19,7 +19,7 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("tvix #[derive(Debug, thiserror::Error)] pub enum ValidateBuildRequestError { #[error("invalid input node at position {0}: {1}")] - InvalidInputNode(usize, ValidateNodeError), + InvalidInputNode(usize, DirectoryError), #[error("input nodes are not sorted by name")] InputNodesNotSorted, @@ -123,20 +123,21 @@ impl BuildRequest { /// and all restrictions around paths themselves (relative, clean, …) need // to be fulfilled. pub fn validate(&self) -> Result<(), ValidateBuildRequestError> { - // validate all input nodes - for (i, n) in self.inputs.iter().enumerate() { - // ensure the input node itself is valid - n.validate() + // validate names. Make sure they're sorted + + let mut last_name: bytes::Bytes = "".into(); + for (i, node) in self.inputs.iter().enumerate() { + // TODO(flokli): store result somewhere + let (name, _node) = node + .clone() + .into_name_and_node() .map_err(|e| ValidateBuildRequestError::InvalidInputNode(i, e))?; - } - // now we can look at the names, and make sure they're sorted. - if !is_sorted( - self.inputs - .iter() - .map(|e| e.node.as_ref().unwrap().get_name()), - ) { - Err(ValidateBuildRequestError::InputNodesNotSorted)? + if name.as_ref() <= last_name.as_ref() { + return Err(ValidateBuildRequestError::InputNodesNotSorted); + } else { + last_name = name.into() + } } // validate working_dir diff --git a/tvix/castore/Cargo.toml b/tvix/castore/Cargo.toml index ded2292db750..b6752ae25af5 100644 --- a/tvix/castore/Cargo.toml +++ b/tvix/castore/Cargo.toml @@ -4,101 +4,68 @@ version = "0.1.0" edition = "2021" [dependencies] -async-compression = { version = "0.4.9", features = ["tokio", "zstd"]} -async-stream = "0.3.5" -async-tempfile = "0.4.0" -blake3 = { version = "1.3.1", features = ["rayon", "std", "traits-preview"] } -bstr = "1.6.0" -bytes = "1.4.0" -data-encoding = "2.6.0" -digest = "0.10.7" -fastcdc = { version = "3.1.0", features = ["tokio"] } -futures = "0.3.30" -lazy_static = "1.4.0" -object_store = { version = "0.10.1", features = ["http"] } -parking_lot = "0.12.1" -pin-project-lite = "0.2.13" -prost = "0.13.1" -sled = { version = "0.34.7" } -thiserror = "1.0.38" -tokio-stream = { version = "0.1.14", features = ["fs", "net"] } -tokio-util = { version = "0.7.9", features = ["io", "io-util", "codec"] } -tokio-tar = "0.3.1" -tokio = { version = "1.32.0", features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } -tonic = "0.12.0" -tower = "0.4.13" -tracing = "0.1.37" -tracing-indicatif = "0.3.6" +async-compression = { workspace = true, features = ["tokio", "zstd"] } +async-stream = { workspace = true } +async-tempfile = { workspace = true } +blake3 = { workspace = true, features = ["rayon", "std", "traits-preview"] } +bstr = { workspace = true } +bytes = { workspace = true } +data-encoding = { workspace = true } +digest = { workspace = true } +fastcdc = { workspace = true, features = ["tokio"] } +futures = { workspace = true } +lazy_static = { workspace = true } +object_store = { workspace = true, features = ["http"] } +parking_lot = { workspace = true } +pin-project-lite = { workspace = true } +prost = { workspace = true } +sled = { workspace = true } +thiserror = { workspace = true } +tokio-stream = { workspace = true, features = ["fs", "net"] } +tokio-util = { workspace = true, features = ["io", "io-util", "codec"] } +tokio-tar = { workspace = true } +tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } +tonic = { workspace = true } +tower = { workspace = true } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } tvix-tracing = { path = "../tracing", features = ["tonic"] } -url = "2.4.0" -walkdir = "2.4.0" -zstd = "0.13.0" -serde = { version = "1.0.197", features = [ "derive" ] } -serde_with = "3.7.0" -serde_qs = "0.12.0" -petgraph = "0.6.4" -erased-serde = "0.4.5" -serde_tagged = "0.3.0" -hyper-util = "0.1.6" -redb = "2.1.1" - -[dependencies.bigtable_rs] -optional = true -version = "0.2.10" - -[dependencies.fuse-backend-rs] -optional = true -version = "0.11.0" - -[dependencies.libc] -optional = true -version = "0.2.144" - -[dependencies.threadpool] -version = "1.8.1" -optional = true - -[dependencies.tonic-reflection] -optional = true -version = "0.12.0" - -[dependencies.vhost] -optional = true -version = "0.6" - -[dependencies.vhost-user-backend] -optional = true -version = "0.8" - -[dependencies.virtio-queue] -optional = true -version = "0.7" - -[dependencies.vm-memory] -optional = true -version = "0.10" - -[dependencies.vmm-sys-util] -optional = true -version = "0.11" - -[dependencies.virtio-bindings] -optional = true -version = "0.2.1" +url = { workspace = true } +walkdir = { workspace = true } +zstd = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_with = { workspace = true } +serde_qs = { workspace = true } +petgraph = { workspace = true } +erased-serde = { workspace = true } +serde_tagged = { workspace = true } +hyper-util = { workspace = true } +redb = { workspace = true } +bigtable_rs = { workspace = true, optional = true } +fuse-backend-rs = { workspace = true, optional = true } +libc = { workspace = true, optional = true } +threadpool = { workspace = true, optional = true } +tonic-reflection = { workspace = true, optional = true } +vhost = { workspace = true, optional = true } +vhost-user-backend = { workspace = true, optional = true } +virtio-queue = { workspace = true, optional = true } +vm-memory = { workspace = true, optional = true } +vmm-sys-util = { workspace = true, optional = true } +virtio-bindings = { workspace = true, optional = true } [build-dependencies] -prost-build = "0.13.1" -tonic-build = "0.12.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [dev-dependencies] -async-process = "2.1.0" -rstest = "0.19.0" -tempfile = "3.3.0" -tokio-retry = "0.3.0" -hex-literal = "0.4.1" -rstest_reuse = "0.6.0" -xattr = "1.3.1" -serde_json = "*" +async-process = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } +tokio-retry = { workspace = true } +hex-literal = { workspace = true } +rstest_reuse = { workspace = true } +xattr = { workspace = true } +serde_json = { workspace = true } [features] default = ["cloud"] diff --git a/tvix/castore/build.rs b/tvix/castore/build.rs index 98e2ab348528..a4591c845509 100644 --- a/tvix/castore/build.rs +++ b/tvix/castore/build.rs @@ -26,7 +26,7 @@ fn main() -> Result<()> { ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), diff --git a/tvix/castore/protos/default.nix b/tvix/castore/protos/default.nix index feef55690fb9..08bb8fcfeef1 100644 --- a/tvix/castore/protos/default.nix +++ b/tvix/castore/protos/default.nix @@ -1,16 +1,10 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "castore-protos"; - root = depot.path.origSrc; - paths = [ - ./castore.proto - ./rpc_blobstore.proto - ./rpc_directory.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + "^tvix(/castore(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/castore/src/digests.rs b/tvix/castore/src/digests.rs index ef9a7326b3fb..4d919ff0d873 100644 --- a/tvix/castore/src/digests.rs +++ b/tvix/castore/src/digests.rs @@ -6,7 +6,7 @@ use thiserror::Error; pub struct B3Digest(Bytes); // TODO: allow converting these errors to crate::Error -#[derive(Error, Debug)] +#[derive(Error, Debug, PartialEq)] pub enum Error { #[error("invalid digest length: {0}")] InvalidDigestLen(usize), diff --git a/tvix/castore/src/directoryservice/bigtable.rs b/tvix/castore/src/directoryservice/bigtable.rs index d10dddaf9f60..73ab4342d832 100644 --- a/tvix/castore/src/directoryservice/bigtable.rs +++ b/tvix/castore/src/directoryservice/bigtable.rs @@ -9,7 +9,9 @@ use std::sync::Arc; use tonic::async_trait; use tracing::{instrument, trace, warn}; -use super::{utils::traverse_directory, DirectoryPutter, DirectoryService, SimplePutter}; +use super::{ + utils::traverse_directory, Directory, DirectoryPutter, DirectoryService, SimplePutter, +}; use crate::composition::{CompositionContext, ServiceBuilder}; use crate::{proto, B3Digest, Error}; @@ -149,7 +151,7 @@ fn derive_directory_key(digest: &B3Digest) -> String { #[async_trait] impl DirectoryService for BigtableDirectoryService { #[instrument(skip(self, digest), err, fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { let mut client = self.client.clone(); let directory_key = derive_directory_key(digest); @@ -241,28 +243,20 @@ impl DirectoryService for BigtableDirectoryService { // Try to parse the value into a Directory message. let directory = proto::Directory::decode(Bytes::from(row_cell.value)) - .map_err(|e| Error::StorageError(format!("unable to decode directory proto: {}", e)))?; - - // validate the Directory. - directory - .validate() + .map_err(|e| Error::StorageError(format!("unable to decode directory proto: {}", e)))? + .try_into() .map_err(|e| Error::StorageError(format!("invalid Directory message: {}", e)))?; Ok(Some(directory)) } #[instrument(skip(self, directory), err, fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { let directory_digest = directory.digest(); let mut client = self.client.clone(); let directory_key = derive_directory_key(&directory_digest); - // Ensure the directory we're trying to upload passes validation - directory - .validate() - .map_err(|e| Error::InvalidRequest(format!("directory is invalid: {}", e)))?; - - let data = directory.encode_to_vec(); + let data = proto::Directory::from(directory).encode_to_vec(); if data.len() as u64 > CELL_SIZE_LIMIT { return Err(Error::StorageError( "Directory exceeds cell limit on Bigtable".into(), @@ -310,7 +304,7 @@ impl DirectoryService for BigtableDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { traverse_directory(self.clone(), root_directory_digest) } diff --git a/tvix/castore/src/directoryservice/combinators.rs b/tvix/castore/src/directoryservice/combinators.rs index 0fdc82c16cb0..4283142231f9 100644 --- a/tvix/castore/src/directoryservice/combinators.rs +++ b/tvix/castore/src/directoryservice/combinators.rs @@ -7,10 +7,9 @@ use futures::TryStreamExt; use tonic::async_trait; use tracing::{instrument, trace}; -use super::{DirectoryGraph, DirectoryService, RootToLeavesValidator, SimplePutter}; +use super::{Directory, DirectoryGraph, DirectoryService, RootToLeavesValidator, SimplePutter}; use crate::composition::{CompositionContext, ServiceBuilder}; use crate::directoryservice::DirectoryPutter; -use crate::proto; use crate::B3Digest; use crate::Error; @@ -40,7 +39,7 @@ where DS2: DirectoryService + Clone + 'static, { #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { match self.near.get(digest).await? { Some(directory) => { trace!("serving from cache"); @@ -82,7 +81,7 @@ where } #[instrument(skip_all)] - async fn put(&self, _directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, _directory: Directory) -> Result<B3Digest, Error> { Err(Error::StorageError("unimplemented".to_string())) } @@ -90,7 +89,7 @@ where fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { let near = self.near.clone(); let far = self.far.clone(); let digest = root_directory_digest.clone(); diff --git a/tvix/castore/src/directoryservice/directory_graph.rs b/tvix/castore/src/directoryservice/directory_graph.rs index e6b9b163370c..017cef024059 100644 --- a/tvix/castore/src/directoryservice/directory_graph.rs +++ b/tvix/castore/src/directoryservice/directory_graph.rs @@ -1,7 +1,5 @@ use std::collections::HashMap; -use bstr::ByteSlice; - use petgraph::{ graph::{DiGraph, NodeIndex}, visit::{Bfs, DfsPostOrder, EdgeRef, IntoNodeIdentifiers, Walker}, @@ -10,10 +8,7 @@ use petgraph::{ use tracing::instrument; use super::order_validator::{LeavesToRootValidator, OrderValidator, RootToLeavesValidator}; -use crate::{ - proto::{self, Directory, DirectoryNode}, - B3Digest, -}; +use crate::{path::PathComponent, B3Digest, Directory, Node}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -21,6 +16,11 @@ pub enum Error { ValidationError(String), } +struct EdgeWeight { + name: PathComponent, + size: u64, +} + /// This can be used to validate and/or re-order a Directory closure (DAG of /// connected Directories), and their insertion order. /// @@ -58,7 +58,7 @@ pub struct DirectoryGraph<O> { // // The option in the edge weight tracks the pending validation state of the respective edge, for example if // the child has not been added yet. - graph: DiGraph<Option<Directory>, Option<DirectoryNode>>, + graph: DiGraph<Option<Directory>, Option<EdgeWeight>>, // A lookup table from directory digest to node index. digest_to_node_ix: HashMap<B3Digest, NodeIndex>, @@ -67,18 +67,18 @@ pub struct DirectoryGraph<O> { } pub struct ValidatedDirectoryGraph { - graph: DiGraph<Option<Directory>, Option<DirectoryNode>>, + graph: DiGraph<Option<Directory>, Option<EdgeWeight>>, root: Option<NodeIndex>, } -fn check_edge(dir: &DirectoryNode, child: &Directory) -> Result<(), Error> { +fn check_edge(edge: &EdgeWeight, child: &Directory) -> Result<(), Error> { // Ensure the size specified in the child node matches our records. - if dir.size != child.size() { + if edge.size != child.size() { return Err(Error::ValidationError(format!( "'{}' has wrong size, specified {}, recorded {}", - dir.name.as_bstr(), - dir.size, + edge.name, + edge.size, child.size(), ))); } @@ -88,7 +88,7 @@ fn check_edge(dir: &DirectoryNode, child: &Directory) -> Result<(), Error> { impl DirectoryGraph<LeavesToRootValidator> { /// Insert a new Directory into the closure #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest(), directory.size=%directory.size()), err)] - pub fn add(&mut self, directory: proto::Directory) -> Result<(), Error> { + pub fn add(&mut self, directory: Directory) -> Result<(), Error> { if !self.order_validator.add_directory(&directory) { return Err(Error::ValidationError( "unknown directory was referenced".into(), @@ -108,7 +108,7 @@ impl DirectoryGraph<RootToLeavesValidator> { /// Insert a new Directory into the closure #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest(), directory.size=%directory.size()), err)] - pub fn add(&mut self, directory: proto::Directory) -> Result<(), Error> { + pub fn add(&mut self, directory: Directory) -> Result<(), Error> { let digest = directory.digest(); if !self.order_validator.digest_allowed(&digest) { return Err(Error::ValidationError("unexpected digest".into())); @@ -129,12 +129,7 @@ impl<O: OrderValidator> DirectoryGraph<O> { } /// Adds a directory which has already been confirmed to be in-order to the graph - pub fn add_order_unchecked(&mut self, directory: proto::Directory) -> Result<(), Error> { - // Do some basic validation - directory - .validate() - .map_err(|e| Error::ValidationError(e.to_string()))?; - + pub fn add_order_unchecked(&mut self, directory: Directory) -> Result<(), Error> { let digest = directory.digest(); // Teach the graph about the existence of a node with this digest @@ -149,23 +144,32 @@ impl<O: OrderValidator> DirectoryGraph<O> { } // set up edges to all child directories - for subdir in &directory.directories { - let subdir_digest: B3Digest = subdir.digest.clone().try_into().unwrap(); - - let child_ix = *self - .digest_to_node_ix - .entry(subdir_digest) - .or_insert_with(|| self.graph.add_node(None)); - - let pending_edge_check = match &self.graph[child_ix] { - Some(child) => { - // child is already available, validate the edge now - check_edge(subdir, child)?; - None - } - None => Some(subdir.clone()), // pending validation - }; - self.graph.add_edge(ix, child_ix, pending_edge_check); + for (name, node) in directory.nodes() { + if let Node::Directory { digest, size } = node { + let child_ix = *self + .digest_to_node_ix + .entry(digest.clone()) + .or_insert_with(|| self.graph.add_node(None)); + + let pending_edge_check = match &self.graph[child_ix] { + Some(child) => { + // child is already available, validate the edge now + check_edge( + &EdgeWeight { + name: name.clone(), + size: *size, + }, + child, + )?; + None + } + None => Some(EdgeWeight { + name: name.clone(), + size: *size, + }), // pending validation + }; + self.graph.add_edge(ix, child_ix, pending_edge_check); + } } // validate the edges from parents to this node @@ -183,6 +187,7 @@ impl<O: OrderValidator> DirectoryGraph<O> { .expect("edge not found") .take() .expect("edge is already validated"); + check_edge(&edge_weight, &directory)?; } @@ -266,37 +271,37 @@ impl ValidatedDirectoryGraph { .filter_map(move |i| nodes[i.index()].weight.take()) } } - -#[cfg(test)] -mod tests { - use crate::{ - fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}, - proto::{self, Directory}, - }; - use lazy_static::lazy_static; - use rstest::rstest; - - lazy_static! { +/* pub static ref BROKEN_DIRECTORY : Directory = Directory { - symlinks: vec![proto::SymlinkNode { + symlinks: vec![SymlinkNode { name: "".into(), // invalid name! target: "doesntmatter".into(), }], ..Default::default() }; - - pub static ref BROKEN_PARENT_DIRECTORY: Directory = Directory { - directories: vec![proto::DirectoryNode { - name: "foo".into(), - digest: DIRECTORY_A.digest().into(), - size: DIRECTORY_A.size() + 42, // wrong! - }], - ..Default::default() - }; - } +*/ +#[cfg(test)] +mod tests { + use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}; + use crate::{Directory, Node}; + use lazy_static::lazy_static; + use rstest::rstest; use super::{DirectoryGraph, LeavesToRootValidator, RootToLeavesValidator}; + lazy_static! { + pub static ref BROKEN_PARENT_DIRECTORY: Directory = + Directory::try_from_iter([ + ( + "foo".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_A.digest(), + size: DIRECTORY_A.size() + 42, // wrong! + } + ) + ]).unwrap(); + } + #[rstest] /// Uploading an empty directory should succeed. #[case::empty_directory(&[&*DIRECTORY_A], false, Some(vec![&*DIRECTORY_A]))] @@ -312,8 +317,6 @@ mod tests { #[case::unconnected_node(&[&*DIRECTORY_A, &*DIRECTORY_C, &*DIRECTORY_B], false, None)] /// Uploading B (referring to A) should fail immediately, because A was never uploaded. #[case::dangling_pointer(&[&*DIRECTORY_B], true, None)] - /// Uploading a directory failing validation should fail immediately. - #[case::failing_validation(&[&*BROKEN_DIRECTORY], true, None)] /// Uploading a directory which refers to another Directory with a wrong size should fail. #[case::wrong_size_in_parent(&[&*DIRECTORY_A, &*BROKEN_PARENT_DIRECTORY], true, None)] fn test_uploads( @@ -366,8 +369,6 @@ mod tests { #[case::unconnected_node(&*DIRECTORY_C, &[&*DIRECTORY_C, &*DIRECTORY_B], true, None)] /// Downloading B (specified as the root) but receiving A instead should fail immediately, because A has no connection to B (the root). #[case::dangling_pointer(&*DIRECTORY_B, &[&*DIRECTORY_A], true, None)] - /// Downloading a directory failing validation should fail immediately. - #[case::failing_validation(&*BROKEN_DIRECTORY, &[&*BROKEN_DIRECTORY], true, None)] /// Downloading a directory which refers to another Directory with a wrong size should fail. #[case::wrong_size_in_parent(&*BROKEN_PARENT_DIRECTORY, &[&*BROKEN_PARENT_DIRECTORY, &*DIRECTORY_A], true, None)] fn test_downloads( diff --git a/tvix/castore/src/directoryservice/grpc.rs b/tvix/castore/src/directoryservice/grpc.rs index 4dc3931ed410..9696c5631949 100644 --- a/tvix/castore/src/directoryservice/grpc.rs +++ b/tvix/castore/src/directoryservice/grpc.rs @@ -1,9 +1,9 @@ use std::collections::HashSet; -use super::{DirectoryPutter, DirectoryService}; +use super::{Directory, DirectoryPutter, DirectoryService}; use crate::composition::{CompositionContext, ServiceBuilder}; use crate::proto::{self, get_directory_request::ByWhat}; -use crate::{B3Digest, Error}; +use crate::{B3Digest, DirectoryError, Error}; use async_stream::try_stream; use futures::stream::BoxStream; use std::sync::Arc; @@ -41,10 +41,7 @@ where T::Future: Send, { #[instrument(level = "trace", skip_all, fields(directory.digest = %digest))] - async fn get( - &self, - digest: &B3Digest, - ) -> Result<Option<crate::proto::Directory>, crate::Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, crate::Error> { // Get a new handle to the gRPC client, and copy the digest. let mut grpc_client = self.grpc_client.clone(); let digest_cpy = digest.clone(); @@ -72,15 +69,10 @@ where "requested directory with digest {}, but got {}", digest, actual_digest ))) - } else if let Err(e) = directory.validate() { - // Validate the Directory itself is valid. - warn!("directory failed validation: {}", e.to_string()); - Err(crate::Error::StorageError(format!( - "directory {} failed validation: {}", - digest, e, - ))) } else { - Ok(Some(directory)) + Ok(Some(directory.try_into().map_err(|_| { + Error::StorageError("invalid root digest length in response".to_string()) + })?)) } } Ok(None) => Ok(None), @@ -90,11 +82,11 @@ where } #[instrument(level = "trace", skip_all, fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: crate::proto::Directory) -> Result<B3Digest, crate::Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, crate::Error> { let resp = self .grpc_client .clone() - .put(tokio_stream::once(directory)) + .put(tokio_stream::once(proto::Directory::from(directory))) .await; match resp { @@ -113,7 +105,7 @@ where fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { let mut grpc_client = self.grpc_client.clone(); let root_directory_digest = root_directory_digest.clone(); @@ -135,14 +127,6 @@ where loop { match stream.message().await { Ok(Some(directory)) => { - // validate the directory itself. - if let Err(e) = directory.validate() { - Err(crate::Error::StorageError(format!( - "directory {} failed validation: {}", - directory.digest(), - e, - )))?; - } // validate we actually expected that directory, and move it from expected to received. let directory_digest = directory.digest(); let was_expected = expected_directory_digests.remove(&directory_digest); @@ -168,6 +152,9 @@ where .insert(child_directory_digest); } + let directory = directory.try_into() + .map_err(|e: DirectoryError| Error::StorageError(e.to_string()))?; + yield directory; }, Ok(None) if expected_directory_digests.len() == 1 && expected_directory_digests.contains(&root_directory_digest) => { @@ -279,11 +266,11 @@ pub struct GRPCPutter { #[async_trait] impl DirectoryPutter for GRPCPutter { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), crate::Error> { + async fn put(&mut self, directory: Directory) -> Result<(), crate::Error> { match self.rq { // If we're not already closed, send the directory to directory_sender. Some((_, ref directory_sender)) => { - if directory_sender.send(directory).is_err() { + if directory_sender.send(directory.into()).is_err() { // If the channel has been prematurely closed, invoke close (so we can peek at the error code) // That error code is much more helpful, because it // contains the error message from the server. diff --git a/tvix/castore/src/directoryservice/memory.rs b/tvix/castore/src/directoryservice/memory.rs index ada4606a5a57..b039d9bc7d84 100644 --- a/tvix/castore/src/directoryservice/memory.rs +++ b/tvix/castore/src/directoryservice/memory.rs @@ -1,4 +1,4 @@ -use crate::{proto, B3Digest, Error}; +use crate::{B3Digest, Error}; use futures::stream::BoxStream; use std::collections::HashMap; use std::sync::Arc; @@ -7,8 +7,9 @@ use tonic::async_trait; use tracing::{instrument, warn}; use super::utils::traverse_directory; -use super::{DirectoryPutter, DirectoryService, SimplePutter}; +use super::{Directory, DirectoryPutter, DirectoryService, SimplePutter}; use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::proto; #[derive(Clone, Default)] pub struct MemoryDirectoryService { @@ -18,7 +19,7 @@ pub struct MemoryDirectoryService { #[async_trait] impl DirectoryService for MemoryDirectoryService { #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { let db = self.db.read().await; match db.get(digest) { @@ -37,35 +38,20 @@ impl DirectoryService for MemoryDirectoryService { ))); } - // Validate the Directory itself is valid. - if let Err(e) = directory.validate() { - warn!("directory failed validation: {}", e.to_string()); - return Err(Error::StorageError(format!( - "directory {} failed validation: {}", - actual_digest, e, - ))); - } - - Ok(Some(directory.clone())) + Ok(Some(directory.clone().try_into().map_err(|e| { + crate::Error::StorageError(format!("corrupted directory: {}", e)) + })?)) } } } #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { let digest = directory.digest(); - // validate the directory itself. - if let Err(e) = directory.validate() { - return Err(Error::InvalidRequest(format!( - "directory {} failed validation: {}", - digest, e, - ))); - } - // store it let mut db = self.db.write().await; - db.insert(digest.clone(), directory); + db.insert(digest.clone(), directory.into()); Ok(digest) } @@ -74,7 +60,7 @@ impl DirectoryService for MemoryDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { traverse_directory(self.clone(), root_directory_digest) } diff --git a/tvix/castore/src/directoryservice/mod.rs b/tvix/castore/src/directoryservice/mod.rs index 17a78b179349..25162e4de853 100644 --- a/tvix/castore/src/directoryservice/mod.rs +++ b/tvix/castore/src/directoryservice/mod.rs @@ -1,5 +1,5 @@ use crate::composition::{Registry, ServiceBuilder}; -use crate::{proto, B3Digest, Error}; +use crate::{B3Digest, Directory, Error}; use futures::stream::BoxStream; use tonic::async_trait; @@ -19,7 +19,7 @@ mod traverse; mod utils; pub use self::combinators::{Cache, CacheConfig}; -pub use self::directory_graph::DirectoryGraph; +pub use self::directory_graph::{DirectoryGraph, ValidatedDirectoryGraph}; pub use self::from_addr::from_addr; pub use self::grpc::{GRPCDirectoryService, GRPCDirectoryServiceConfig}; pub use self::memory::{MemoryDirectoryService, MemoryDirectoryServiceConfig}; @@ -38,7 +38,7 @@ mod bigtable; pub use self::bigtable::{BigtableDirectoryService, BigtableParameters}; /// The base trait all Directory services need to implement. -/// This is a simple get and put of [crate::proto::Directory], returning their +/// This is a simple get and put of [Directory], returning their /// digest. #[async_trait] pub trait DirectoryService: Send + Sync { @@ -50,14 +50,14 @@ pub trait DirectoryService: Send + Sync { /// Directory digests that are at the "root", aka the last element that's /// sent to a DirectoryPutter. This makes sense for implementations bundling /// closures of directories together in batches. - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error>; + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error>; /// Uploads a single Directory message, and returns the calculated /// digest, or an error. An error *must* also be returned if the message is /// not valid. - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error>; + async fn put(&self, directory: Directory) -> Result<B3Digest, Error>; - /// Looks up a closure of [proto::Directory]. - /// Ideally this would be a `impl Stream<Item = Result<proto::Directory, Error>>`, + /// Looks up a closure of [Directory]. + /// Ideally this would be a `impl Stream<Item = Result<Directory, Error>>`, /// and we'd be able to add a default implementation for it here, but /// we can't have that yet. /// @@ -75,9 +75,9 @@ pub trait DirectoryService: Send + Sync { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>>; + ) -> BoxStream<'static, Result<Directory, Error>>; - /// Allows persisting a closure of [proto::Directory], which is a graph of + /// Allows persisting a closure of [Directory], which is a graph of /// connected Directory messages. fn put_multiple_start(&self) -> Box<dyn DirectoryPutter>; } @@ -87,18 +87,18 @@ impl<A> DirectoryService for A where A: AsRef<dyn DirectoryService> + Send + Sync, { - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { self.as_ref().get(digest).await } - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { self.as_ref().put(directory).await } fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { self.as_ref().get_recursive(root_directory_digest) } @@ -107,7 +107,7 @@ where } } -/// Provides a handle to put a closure of connected [proto::Directory] elements. +/// Provides a handle to put a closure of connected [Directory] elements. /// /// The consumer can periodically call [DirectoryPutter::put], starting from the /// leaves. Once the root is reached, [DirectoryPutter::close] can be called to @@ -119,12 +119,12 @@ where /// but a single file or symlink. #[async_trait] pub trait DirectoryPutter: Send { - /// Put a individual [proto::Directory] into the store. + /// Put a individual [Directory] into the store. /// Error semantics and behaviour is up to the specific implementation of /// this trait. /// Due to bursting, the returned error might refer to an object previously /// sent via `put`. - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error>; + async fn put(&mut self, directory: Directory) -> Result<(), Error>; /// Close the stream, and wait for any errors. /// If there's been any invalid Directory message uploaded, and error *must* diff --git a/tvix/castore/src/directoryservice/object_store.rs b/tvix/castore/src/directoryservice/object_store.rs index a9a2cc8ef5c0..5b5281abcd2f 100644 --- a/tvix/castore/src/directoryservice/object_store.rs +++ b/tvix/castore/src/directoryservice/object_store.rs @@ -17,10 +17,11 @@ use tracing::{instrument, trace, warn, Level}; use url::Url; use super::{ - DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator, RootToLeavesValidator, + Directory, DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator, + RootToLeavesValidator, }; use crate::composition::{CompositionContext, ServiceBuilder}; -use crate::{proto, B3Digest, Error}; +use crate::{proto, B3Digest, Error, Node}; /// Stores directory closures in an object store. /// Notably, this makes use of the option to disallow accessing child directories except when @@ -78,13 +79,17 @@ impl DirectoryService for ObjectStoreDirectoryService { /// This is the same steps as for get_recursive anyways, so we just call get_recursive and /// return the first element of the stream and drop the request. #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { self.get_recursive(digest).take(1).next().await.transpose() } #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { - if !directory.directories.is_empty() { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { + // Ensure the directory doesn't contain other directory children + if directory + .nodes() + .any(|(_, e)| matches!(e, Node::Directory { .. })) + { return Err(Error::InvalidRequest( "only put_multiple_start is supported by the ObjectStoreDirectoryService for directories with children".into(), )); @@ -99,7 +104,7 @@ impl DirectoryService for ObjectStoreDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { // Check that we are not passing on bogus from the object store to the client, and that the // trust chain from the root digest to the leaves is intact let mut order_validator = @@ -145,6 +150,10 @@ impl DirectoryService for ObjectStoreDirectoryService { warn!("unable to parse directory {}: {}", digest, e); Error::StorageError(e.to_string()) })?; + let directory = Directory::try_from(directory).map_err(|e| { + warn!("unable to convert directory {}: {}", digest, e); + Error::StorageError(e.to_string()) + })?; // Allow the children to appear next order_validator.add_directory_unchecked(&directory); @@ -244,7 +253,7 @@ impl ObjectStoreDirectoryPutter { #[async_trait] impl DirectoryPutter for ObjectStoreDirectoryPutter { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { + async fn put(&mut self, directory: Directory) -> Result<(), Error> { match self.directory_validator { None => return Err(Error::StorageError("already closed".to_string())), Some(ref mut validator) => { @@ -302,7 +311,7 @@ impl DirectoryPutter for ObjectStoreDirectoryPutter { for directory in directories { directories_sink - .send(directory.encode_to_vec().into()) + .send(proto::Directory::from(directory).encode_to_vec().into()) .await?; } diff --git a/tvix/castore/src/directoryservice/order_validator.rs b/tvix/castore/src/directoryservice/order_validator.rs index 6045f5d24198..973af92e1294 100644 --- a/tvix/castore/src/directoryservice/order_validator.rs +++ b/tvix/castore/src/directoryservice/order_validator.rs @@ -1,7 +1,8 @@ use std::collections::HashSet; use tracing::warn; -use crate::{proto::Directory, B3Digest}; +use super::Directory; +use crate::{B3Digest, Node}; pub trait OrderValidator { /// Update the order validator's state with the directory @@ -47,10 +48,11 @@ impl RootToLeavesValidator { self.expected_digests.insert(directory.digest()); } - for subdir in &directory.directories { - // Allow the children to appear next - let subdir_digest = subdir.digest.clone().try_into().unwrap(); - self.expected_digests.insert(subdir_digest); + // Allow the children to appear next + for (_, node) in directory.nodes() { + if let Node::Directory { digest, .. } = node { + self.expected_digests.insert(digest.clone()); + } } } } @@ -79,15 +81,20 @@ impl OrderValidator for LeavesToRootValidator { fn add_directory(&mut self, directory: &Directory) -> bool { let digest = directory.digest(); - for subdir in &directory.directories { - let subdir_digest = subdir.digest.clone().try_into().unwrap(); // this has been validated in validate_directory() - if !self.allowed_references.contains(&subdir_digest) { - warn!( - directory.digest = %digest, - subdirectory.digest = %subdir_digest, - "unexpected directory reference" - ); - return false; + for (_, node) in directory.nodes() { + if let Node::Directory { + digest: subdir_node_digest, + .. + } = node + { + if !self.allowed_references.contains(subdir_node_digest) { + warn!( + directory.digest = %digest, + subdirectory.digest = %subdir_node_digest, + "unexpected directory reference" + ); + return false; + } } } @@ -101,8 +108,8 @@ impl OrderValidator for LeavesToRootValidator { mod tests { use super::{LeavesToRootValidator, RootToLeavesValidator}; use crate::directoryservice::order_validator::OrderValidator; + use crate::directoryservice::Directory; use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C}; - use crate::proto::Directory; use rstest::rstest; #[rstest] diff --git a/tvix/castore/src/directoryservice/redb.rs b/tvix/castore/src/directoryservice/redb.rs index 51dc87f92574..d253df503bb3 100644 --- a/tvix/castore/src/directoryservice/redb.rs +++ b/tvix/castore/src/directoryservice/redb.rs @@ -5,15 +5,15 @@ use std::{path::PathBuf, sync::Arc}; use tonic::async_trait; use tracing::{instrument, warn}; +use super::{ + traverse_directory, Directory, DirectoryGraph, DirectoryPutter, DirectoryService, + LeavesToRootValidator, +}; use crate::{ composition::{CompositionContext, ServiceBuilder}, digests, proto, B3Digest, Error, }; -use super::{ - traverse_directory, DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator, -}; - const DIRECTORY_TABLE: TableDefinition<[u8; digests::B3_LEN], Vec<u8>> = TableDefinition::new("directory"); @@ -69,7 +69,7 @@ fn create_schema(db: &redb::Database) -> Result<(), redb::Error> { #[async_trait] impl DirectoryService for RedbDirectoryService { #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { let db = self.db.clone(); // Retrieves the protobuf-encoded Directory for the corresponding digest. @@ -107,13 +107,10 @@ impl DirectoryService for RedbDirectoryService { let directory = match proto::Directory::decode(&*directory_data.value()) { Ok(dir) => { // The returned Directory must be valid. - if let Err(e) = dir.validate() { + dir.try_into().map_err(|e| { warn!(err=%e, "Directory failed validation"); - return Err(Error::StorageError( - "Directory failed validation".to_string(), - )); - } - dir + Error::StorageError("Directory failed validation".to_string()) + })? } Err(e) => { warn!(err=%e, "failed to parse Directory"); @@ -125,26 +122,21 @@ impl DirectoryService for RedbDirectoryService { } #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { tokio::task::spawn_blocking({ let db = self.db.clone(); move || { let digest = directory.digest(); - // Validate the directory. - if let Err(e) = directory.validate() { - warn!(err=%e, "Directory failed validation"); - return Err(Error::StorageError( - "Directory failed validation".to_string(), - )); - } - // Store the directory in the table. let txn = db.begin_write()?; { let mut table = txn.open_table(DIRECTORY_TABLE)?; let digest_as_array: [u8; digests::B3_LEN] = digest.clone().into(); - table.insert(digest_as_array, directory.encode_to_vec())?; + table.insert( + digest_as_array, + proto::Directory::from(directory).encode_to_vec(), + )?; } txn.commit()?; @@ -158,7 +150,7 @@ impl DirectoryService for RedbDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { // FUTUREWORK: Ideally we should have all of the directory traversing happen in a single // redb transaction to avoid constantly closing and opening new transactions for the // database. @@ -185,7 +177,7 @@ pub struct RedbDirectoryPutter { #[async_trait] impl DirectoryPutter for RedbDirectoryPutter { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { + async fn put(&mut self, directory: Directory) -> Result<(), Error> { match self.directory_validator { None => return Err(Error::StorageError("already closed".to_string())), Some(ref mut validator) => { @@ -228,7 +220,10 @@ impl DirectoryPutter for RedbDirectoryPutter { for directory in directories { let digest_as_array: [u8; digests::B3_LEN] = directory.digest().into(); - table.insert(digest_as_array, directory.encode_to_vec())?; + table.insert( + digest_as_array, + proto::Directory::from(directory).encode_to_vec(), + )?; } } diff --git a/tvix/castore/src/directoryservice/simple_putter.rs b/tvix/castore/src/directoryservice/simple_putter.rs index dc54e3d11d18..b4daaee61b22 100644 --- a/tvix/castore/src/directoryservice/simple_putter.rs +++ b/tvix/castore/src/directoryservice/simple_putter.rs @@ -1,7 +1,6 @@ use super::DirectoryPutter; use super::DirectoryService; -use super::{DirectoryGraph, LeavesToRootValidator}; -use crate::proto; +use super::{Directory, DirectoryGraph, LeavesToRootValidator}; use crate::B3Digest; use crate::Error; use tonic::async_trait; @@ -29,7 +28,7 @@ impl<DS: DirectoryService> SimplePutter<DS> { #[async_trait] impl<DS: DirectoryService + 'static> DirectoryPutter for SimplePutter<DS> { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { + async fn put(&mut self, directory: Directory) -> Result<(), Error> { match self.directory_validator { None => return Err(Error::StorageError("already closed".to_string())), Some(ref mut validator) => { diff --git a/tvix/castore/src/directoryservice/sled.rs b/tvix/castore/src/directoryservice/sled.rs index 5766dec1a5c2..4f3a860d14e4 100644 --- a/tvix/castore/src/directoryservice/sled.rs +++ b/tvix/castore/src/directoryservice/sled.rs @@ -1,5 +1,3 @@ -use crate::proto::Directory; -use crate::{proto, B3Digest, Error}; use futures::stream::BoxStream; use prost::Message; use std::ops::Deref; @@ -9,8 +7,9 @@ use tonic::async_trait; use tracing::{instrument, warn}; use super::utils::traverse_directory; -use super::{DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator}; +use super::{Directory, DirectoryGraph, DirectoryPutter, DirectoryService, LeavesToRootValidator}; use crate::composition::{CompositionContext, ServiceBuilder}; +use crate::{proto, B3Digest, Error}; #[derive(Clone)] pub struct SledDirectoryService { @@ -44,7 +43,7 @@ impl SledDirectoryService { #[async_trait] impl DirectoryService for SledDirectoryService { #[instrument(skip(self, digest), fields(directory.digest = %digest))] - async fn get(&self, digest: &B3Digest) -> Result<Option<proto::Directory>, Error> { + async fn get(&self, digest: &B3Digest) -> Result<Option<Directory>, Error> { let resp = tokio::task::spawn_blocking({ let db = self.db.clone(); let digest = digest.clone(); @@ -61,7 +60,7 @@ impl DirectoryService for SledDirectoryService { None => Ok(None), // The directory was found, try to parse the data as Directory message - Some(data) => match Directory::decode(&*data) { + Some(data) => match proto::Directory::decode(&*data) { Ok(directory) => { // Validate the retrieved Directory indeed has the // digest we expect it to have, to detect corruptions. @@ -73,14 +72,10 @@ impl DirectoryService for SledDirectoryService { ))); } - // Validate the Directory itself is valid. - if let Err(e) = directory.validate() { - warn!("directory failed validation: {}", e.to_string()); - return Err(Error::StorageError(format!( - "directory {} failed validation: {}", - actual_digest, e, - ))); - } + let directory = directory.try_into().map_err(|e| { + warn!("failed to retrieve directory: {}", e); + Error::StorageError(format!("failed to retrieve directory: {}", e)) + })?; Ok(Some(directory)) } @@ -93,22 +88,18 @@ impl DirectoryService for SledDirectoryService { } #[instrument(skip(self, directory), fields(directory.digest = %directory.digest()))] - async fn put(&self, directory: proto::Directory) -> Result<B3Digest, Error> { + async fn put(&self, directory: Directory) -> Result<B3Digest, Error> { tokio::task::spawn_blocking({ let db = self.db.clone(); move || { let digest = directory.digest(); - // validate the directory itself. - if let Err(e) = directory.validate() { - return Err(Error::InvalidRequest(format!( - "directory {} failed validation: {}", - digest, e, - ))); - } // store it - db.insert(digest.as_slice(), directory.encode_to_vec()) - .map_err(|e| Error::StorageError(e.to_string()))?; + db.insert( + digest.as_slice(), + proto::Directory::from(directory).encode_to_vec(), + ) + .map_err(|e| Error::StorageError(e.to_string()))?; Ok(digest) } @@ -120,7 +111,7 @@ impl DirectoryService for SledDirectoryService { fn get_recursive( &self, root_directory_digest: &B3Digest, - ) -> BoxStream<'static, Result<proto::Directory, Error>> { + ) -> BoxStream<'static, Result<Directory, Error>> { traverse_directory(self.clone(), root_directory_digest) } @@ -215,7 +206,7 @@ pub struct SledDirectoryPutter { #[async_trait] impl DirectoryPutter for SledDirectoryPutter { #[instrument(level = "trace", skip_all, fields(directory.digest=%directory.digest()), err)] - async fn put(&mut self, directory: proto::Directory) -> Result<(), Error> { + async fn put(&mut self, directory: Directory) -> Result<(), Error> { match self.directory_validator { None => return Err(Error::StorageError("already closed".to_string())), Some(ref mut validator) => { @@ -252,7 +243,10 @@ impl DirectoryPutter for SledDirectoryPutter { let mut batch = sled::Batch::default(); for directory in directories { - batch.insert(directory.digest().as_slice(), directory.encode_to_vec()); + batch.insert( + directory.digest().as_slice(), + proto::Directory::from(directory).encode_to_vec(), + ); } tree.apply_batch(batch).map_err(|e| { diff --git a/tvix/castore/src/directoryservice/tests/mod.rs b/tvix/castore/src/directoryservice/tests/mod.rs index b698f70ea469..ad189564bfe7 100644 --- a/tvix/castore/src/directoryservice/tests/mod.rs +++ b/tvix/castore/src/directoryservice/tests/mod.rs @@ -8,10 +8,8 @@ use rstest_reuse::{self, *}; use super::DirectoryService; use crate::directoryservice; -use crate::{ - fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C, DIRECTORY_D}, - proto::{self, Directory}, -}; +use crate::fixtures::{DIRECTORY_A, DIRECTORY_B, DIRECTORY_C, DIRECTORY_D}; +use crate::{Directory, Node}; mod utils; use self::utils::make_grpc_directory_service_client; @@ -41,10 +39,10 @@ async fn test_non_exist(directory_service: impl DirectoryService) { // recursive get assert_eq!( - Vec::<Result<proto::Directory, crate::Error>>::new(), + Vec::<Result<Directory, crate::Error>>::new(), directory_service .get_recursive(&DIRECTORY_A.digest()) - .collect::<Vec<Result<proto::Directory, crate::Error>>>() + .collect::<Vec<Result<Directory, crate::Error>>>() .await ); } @@ -212,58 +210,20 @@ async fn upload_reject_dangling_pointer(directory_service: impl DirectoryService } } -/// Try uploading a Directory failing its internal validation, ensure it gets -/// rejected. -#[apply(directory_services)] -#[tokio::test] -async fn upload_reject_failing_validation(directory_service: impl DirectoryService) { - let broken_directory = Directory { - symlinks: vec![proto::SymlinkNode { - name: "".into(), // wrong! - target: "doesntmatter".into(), - }], - ..Default::default() - }; - assert!(broken_directory.validate().is_err()); - - // Try to upload via single upload. - assert!( - directory_service - .put(broken_directory.clone()) - .await - .is_err(), - "single upload must fail" - ); - - // Try to upload via put_multiple. We're a bit more permissive here, the - // intermediate .put() might succeed, due to client-side bursting (in the - // case of gRPC), but then the close MUST fail. - let mut handle = directory_service.put_multiple_start(); - if handle.put(broken_directory).await.is_ok() { - assert!( - handle.close().await.is_err(), - "when succeeding put, close must fail" - ) - } -} - /// Try uploading a Directory that refers to a previously-uploaded directory. /// Both pass their isolated validation, but the size field in the parent is wrong. /// This should be rejected. #[apply(directory_services)] #[tokio::test] async fn upload_reject_wrong_size(directory_service: impl DirectoryService) { - let wrong_parent_directory = Directory { - directories: vec![proto::DirectoryNode { - name: "foo".into(), - digest: DIRECTORY_A.digest().into(), + let wrong_parent_directory = Directory::try_from_iter([( + "foo".try_into().unwrap(), + Node::Directory { + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size() + 42, // wrong! - }], - ..Default::default() - }; - - // Make sure isolated validation itself is ok - assert!(wrong_parent_directory.validate().is_ok()); + }, + )]) + .unwrap(); // Now upload both. Ensure it either fails during the second put, or during // the close. diff --git a/tvix/castore/src/directoryservice/traverse.rs b/tvix/castore/src/directoryservice/traverse.rs index 17a51ae2bbff..0bd67e9bcf1f 100644 --- a/tvix/castore/src/directoryservice/traverse.rs +++ b/tvix/castore/src/directoryservice/traverse.rs @@ -1,8 +1,4 @@ -use super::DirectoryService; -use crate::{ - proto::{node::Node, NamedNode}, - B3Digest, Error, Path, -}; +use crate::{directoryservice::DirectoryService, Error, Node, Path}; use tracing::{instrument, warn}; /// This descends from a (root) node to the given (sub)path, returning the Node @@ -17,19 +13,14 @@ where DS: AsRef<dyn DirectoryService>, { let mut parent_node = root_node; - for component in path.as_ref().components() { + for component in path.as_ref().components_bytes() { match parent_node { - Node::File(_) | Node::Symlink(_) => { + Node::File { .. } | Node::Symlink { .. } => { // There's still some path left, but the parent node is no directory. // This means the path doesn't exist, as we can't reach it. return Ok(None); } - Node::Directory(directory_node) => { - let digest: B3Digest = directory_node - .digest - .try_into() - .map_err(|_e| Error::StorageError("invalid digest length".to_string()))?; - + Node::Directory { digest, .. } => { // fetch the linked node from the directory_service. let directory = directory_service @@ -44,15 +35,16 @@ where })?; // look for the component in the [Directory]. - // FUTUREWORK: as the nodes() iterator returns in a sorted fashion, we - // could stop as soon as e.name is larger than the search string. - if let Some(child_node) = directory.nodes().find(|n| n.get_name() == component) { + if let Some((_child_name, child_node)) = directory + .into_nodes() + .find(|(name, _node)| name.as_ref() == component) + { // child node found, update prev_node to that and continue. - parent_node = child_node; + parent_node = child_node.clone(); } else { // child node not found means there's no such element inside the directory. return Ok(None); - } + }; } } } @@ -65,8 +57,8 @@ where mod tests { use crate::{ directoryservice, - fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP}, - PathBuf, + fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST}, + Node, PathBuf, }; use super::descend_to; @@ -88,21 +80,23 @@ mod tests { handle.close().await.expect("must upload"); // construct the node for DIRECTORY_COMPLICATED - let node_directory_complicated = - crate::proto::node::Node::Directory(crate::proto::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }); + let node_directory_complicated = Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), + size: DIRECTORY_COMPLICATED.size(), + }; // construct the node for DIRECTORY_COMPLICATED - let node_directory_with_keep = crate::proto::node::Node::Directory( - DIRECTORY_COMPLICATED.directories.first().unwrap().clone(), - ); + let node_directory_with_keep = Node::Directory { + digest: DIRECTORY_WITH_KEEP.digest(), + size: DIRECTORY_WITH_KEEP.size(), + }; // construct the node for the .keep file - let node_file_keep = - crate::proto::node::Node::File(DIRECTORY_WITH_KEEP.files.first().unwrap().clone()); + let node_file_keep = Node::File { + digest: EMPTY_BLOB_DIGEST.clone(), + size: 0, + executable: false, + }; // traversal to an empty subpath should return the root node. { diff --git a/tvix/castore/src/directoryservice/utils.rs b/tvix/castore/src/directoryservice/utils.rs index 726734f55eec..d073c2c3c8ec 100644 --- a/tvix/castore/src/directoryservice/utils.rs +++ b/tvix/castore/src/directoryservice/utils.rs @@ -1,21 +1,22 @@ +use super::Directory; use super::DirectoryService; -use crate::proto; use crate::B3Digest; use crate::Error; +use crate::Node; use async_stream::try_stream; use futures::stream::BoxStream; use std::collections::{HashSet, VecDeque}; use tracing::instrument; use tracing::warn; -/// Traverses a [proto::Directory] from the root to the children. +/// Traverses a [Directory] from the root to the children. /// /// This is mostly BFS, but directories are only returned once. #[instrument(skip(directory_service))] pub fn traverse_directory<'a, DS: DirectoryService + 'static>( directory_service: DS, root_directory_digest: &B3Digest, -) -> BoxStream<'a, Result<proto::Directory, Error>> { +) -> BoxStream<'a, Result<Directory, Error>> { // The list of all directories that still need to be traversed. The next // element is picked from the front, new elements are enqueued at the // back. @@ -50,16 +51,6 @@ pub fn traverse_directory<'a, DS: DirectoryService + 'static>( Some(dir) => dir, }; - - // validate, we don't want to send invalid directories. - current_directory.validate().map_err(|e| { - warn!("directory failed validation: {}", e.to_string()); - Error::StorageError(format!( - "invalid directory: {}", - current_directory_digest - )) - })?; - // We're about to send this directory, so let's avoid sending it again if a // descendant has it. sent_directory_digests.insert(current_directory_digest); @@ -67,16 +58,15 @@ pub fn traverse_directory<'a, DS: DirectoryService + 'static>( // enqueue all child directory digests to the work queue, as // long as they're not part of the worklist or already sent. // This panics if the digest looks invalid, it's supposed to be checked first. - for child_directory_node in ¤t_directory.directories { - // TODO: propagate error - let child_digest: B3Digest = child_directory_node.digest.clone().try_into().unwrap(); - - if worklist_directory_digests.contains(&child_digest) - || sent_directory_digests.contains(&child_digest) - { - continue; + for (_, child_directory_node) in current_directory.nodes() { + if let Node::Directory{digest: child_digest, ..} = child_directory_node { + if worklist_directory_digests.contains(child_digest) + || sent_directory_digests.contains(child_digest) + { + continue; + } + worklist_directory_digests.push_back(child_digest.clone()); } - worklist_directory_digests.push_back(child_digest); } yield current_directory; diff --git a/tvix/castore/src/errors.rs b/tvix/castore/src/errors.rs index 5bbcd7b04ef1..7b5d1a422c99 100644 --- a/tvix/castore/src/errors.rs +++ b/tvix/castore/src/errors.rs @@ -1,7 +1,13 @@ +use bstr::ByteSlice; use thiserror::Error; use tokio::task::JoinError; use tonic::Status; +use crate::{ + path::{PathComponent, PathComponentError}, + SymlinkTargetError, +}; + /// Errors related to communication with the store. #[derive(Debug, Error, PartialEq)] pub enum Error { @@ -12,6 +18,48 @@ pub enum Error { StorageError(String), } +/// Errors that occur during construction of [crate::Node] +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum ValidateNodeError { + /// Invalid digest length encountered + #[error("invalid digest length: {0}")] + InvalidDigestLen(usize), + /// Invalid symlink target + #[error("Invalid symlink target: {0}")] + InvalidSymlinkTarget(SymlinkTargetError), +} + +impl From<crate::digests::Error> for ValidateNodeError { + fn from(e: crate::digests::Error) -> Self { + match e { + crate::digests::Error::InvalidDigestLen(n) => ValidateNodeError::InvalidDigestLen(n), + } + } +} + +/// Errors that can occur when populating [crate::Directory] messages, +/// or parsing [crate::proto::Directory] +#[derive(Debug, thiserror::Error, PartialEq)] +pub enum DirectoryError { + /// Multiple elements with the same name encountered + #[error("{:?} is a duplicate name", .0)] + DuplicateName(PathComponent), + /// Node failed validation + #[error("invalid node with name {}: {:?}", .0, .1.to_string())] + InvalidNode(PathComponent, ValidateNodeError), + #[error("Total size exceeds u64::MAX")] + SizeOverflow, + /// Invalid name encountered + #[error("Invalid name: {0}")] + InvalidName(PathComponentError), + /// Elements are not in sorted order. Can only happen on protos + #[error("{:?} is not sorted", .0.as_bstr())] + WrongSorting(bytes::Bytes), + /// This can only happen if there's an unknown node type (on protos) + #[error("No node set")] + NoNodeSet, +} + impl From<JoinError> for Error { fn from(value: JoinError) -> Self { Error::StorageError(value.to_string()) diff --git a/tvix/castore/src/fixtures.rs b/tvix/castore/src/fixtures.rs index 3ebda64a818a..05bad916d55f 100644 --- a/tvix/castore/src/fixtures.rs +++ b/tvix/castore/src/fixtures.rs @@ -1,7 +1,4 @@ -use crate::{ - proto::{self, Directory, DirectoryNode, FileNode, SymlinkNode}, - B3Digest, -}; +use crate::{B3Digest, Directory, Node}; use lazy_static::lazy_static; pub const HELLOWORLD_BLOB_CONTENTS: &[u8] = b"Hello World!"; @@ -34,70 +31,74 @@ lazy_static! { pub static ref BLOB_B_DIGEST: B3Digest = blake3::hash(&BLOB_B).as_bytes().into(); // Directories - pub static ref DIRECTORY_WITH_KEEP: proto::Directory = proto::Directory { - directories: vec![], - files: vec![FileNode { - name: b".keep".to_vec().into(), - digest: EMPTY_BLOB_DIGEST.clone().into(), + pub static ref DIRECTORY_WITH_KEEP: Directory = Directory::try_from_iter([( + ".keep".try_into().unwrap(), + Node::File{ + digest: EMPTY_BLOB_DIGEST.clone(), size: 0, - executable: false, - }], - symlinks: vec![], - }; - pub static ref DIRECTORY_COMPLICATED: proto::Directory = proto::Directory { - directories: vec![DirectoryNode { - name: b"keep".to_vec().into(), - digest: DIRECTORY_WITH_KEEP.digest().into(), - size: DIRECTORY_WITH_KEEP.size(), - }], - files: vec![FileNode { - name: b".keep".to_vec().into(), - digest: EMPTY_BLOB_DIGEST.clone().into(), - size: 0, - executable: false, - }], - symlinks: vec![SymlinkNode { - name: b"aa".to_vec().into(), - target: b"/nix/store/somewhereelse".to_vec().into(), - }], - }; - pub static ref DIRECTORY_A: Directory = Directory::default(); - pub static ref DIRECTORY_B: Directory = Directory { - directories: vec![DirectoryNode { - name: b"a".to_vec().into(), - digest: DIRECTORY_A.digest().into(), - size: DIRECTORY_A.size(), - }], - ..Default::default() - }; - pub static ref DIRECTORY_C: Directory = Directory { - directories: vec![ - DirectoryNode { - name: b"a".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + executable: false + })]).unwrap(); + pub static ref DIRECTORY_COMPLICATED: Directory = Directory::try_from_iter([ + ( + "keep".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_WITH_KEEP.digest(), + size: DIRECTORY_WITH_KEEP.size() + } + ), + ( + ".keep".try_into().unwrap(), + Node::File{ + digest: EMPTY_BLOB_DIGEST.clone(), + size: 0, + executable: false + } + ), + ( + "aa".try_into().unwrap(), + Node::Symlink{ + target: "/nix/store/somewhereelse".try_into().unwrap() + } + ) + ]).unwrap(); + pub static ref DIRECTORY_A: Directory = Directory::new(); + pub static ref DIRECTORY_B: Directory = Directory::try_from_iter([( + "a".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), - }, - DirectoryNode { - name: b"a'".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + } + )]).unwrap(); + pub static ref DIRECTORY_C: Directory = Directory::try_from_iter([ + ( + "a".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), } - ], - ..Default::default() - }; - pub static ref DIRECTORY_D: proto::Directory = proto::Directory { - directories: vec![ - DirectoryNode { - name: b"a".to_vec().into(), - digest: DIRECTORY_A.digest().into(), + ), + ( + "a'".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_A.digest(), + size: DIRECTORY_A.size(), + } + ) + ]).unwrap(); + pub static ref DIRECTORY_D: Directory = Directory::try_from_iter([ + ( + "a".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_A.digest(), size: DIRECTORY_A.size(), - }, - DirectoryNode { - name: b"b'".to_vec().into(), - digest: DIRECTORY_B.digest().into(), + } + ), + ( + "b".try_into().unwrap(), + Node::Directory{ + digest: DIRECTORY_B.digest(), size: DIRECTORY_B.size(), } - ], - ..Default::default() - }; + ) + ]).unwrap(); } diff --git a/tvix/castore/src/fs/fuse/tests.rs b/tvix/castore/src/fs/fuse/tests.rs index bcebcf4a7292..9e01204d5da7 100644 --- a/tvix/castore/src/fs/fuse/tests.rs +++ b/tvix/castore/src/fs/fuse/tests.rs @@ -1,5 +1,4 @@ use bstr::ByteSlice; -use bytes::Bytes; use std::{ collections::BTreeMap, ffi::{OsStr, OsString}, @@ -12,13 +11,14 @@ use tempfile::TempDir; use tokio_stream::{wrappers::ReadDirStream, StreamExt}; use super::FuseDaemon; -use crate::fs::{TvixStoreFs, XATTR_NAME_BLOB_DIGEST, XATTR_NAME_DIRECTORY_DIGEST}; -use crate::proto as castorepb; -use crate::proto::node::Node; use crate::{ blobservice::{BlobService, MemoryBlobService}, directoryservice::{DirectoryService, MemoryDirectoryService}, - fixtures, + fixtures, Node, +}; +use crate::{ + fs::{TvixStoreFs, XATTR_NAME_BLOB_DIGEST, XATTR_NAME_DIRECTORY_DIGEST}, + PathComponent, }; const BLOB_A_NAME: &str = "00000000000000000000000000000000-test"; @@ -39,7 +39,7 @@ fn gen_svcs() -> (Arc<dyn BlobService>, Arc<dyn DirectoryService>) { fn do_mount<P: AsRef<Path>, BS, DS>( blob_service: BS, directory_service: DS, - root_nodes: BTreeMap<bytes::Bytes, Node>, + root_nodes: BTreeMap<PathComponent, Node>, mountpoint: P, list_root: bool, show_xattr: bool, @@ -60,7 +60,7 @@ where async fn populate_blob_a( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy(&mut Cursor::new(fixtures::BLOB_A.to_vec()), &mut bw) @@ -69,19 +69,18 @@ async fn populate_blob_a( bw.close().await.expect("must succeed closing"); root_nodes.insert( - BLOB_A_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_A_NAME.into(), - digest: fixtures::BLOB_A_DIGEST.clone().into(), + BLOB_A_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_A_DIGEST.clone(), size: fixtures::BLOB_A.len() as u64, executable: false, - }), + }, ); } async fn populate_blob_b( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy(&mut Cursor::new(fixtures::BLOB_B.to_vec()), &mut bw) @@ -90,20 +89,19 @@ async fn populate_blob_b( bw.close().await.expect("must succeed closing"); root_nodes.insert( - BLOB_B_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_B_NAME.into(), - digest: fixtures::BLOB_B_DIGEST.clone().into(), + BLOB_B_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_B_DIGEST.clone(), size: fixtures::BLOB_B.len() as u64, executable: false, - }), + }, ); } /// adds a blob containing helloworld and marks it as executable async fn populate_blob_helloworld( blob_service: &Arc<dyn BlobService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { let mut bw = blob_service.open_write().await; tokio::io::copy( @@ -115,42 +113,39 @@ async fn populate_blob_helloworld( bw.close().await.expect("must succeed closing"); root_nodes.insert( - HELLOWORLD_BLOB_NAME.into(), - Node::File(castorepb::FileNode { - name: HELLOWORLD_BLOB_NAME.into(), - digest: fixtures::HELLOWORLD_BLOB_DIGEST.clone().into(), + HELLOWORLD_BLOB_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::HELLOWORLD_BLOB_DIGEST.clone(), size: fixtures::HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: true, - }), + }, ); } -async fn populate_symlink(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_symlink(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - SYMLINK_NAME.into(), - Node::Symlink(castorepb::SymlinkNode { - name: SYMLINK_NAME.into(), - target: BLOB_A_NAME.into(), - }), + SYMLINK_NAME.try_into().unwrap(), + Node::Symlink { + target: BLOB_A_NAME.try_into().unwrap(), + }, ); } /// This writes a symlink pointing to /nix/store/somewhereelse, /// which is the same symlink target as "aa" inside DIRECTORY_COMPLICATED. -async fn populate_symlink2(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_symlink2(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - SYMLINK_NAME2.into(), - Node::Symlink(castorepb::SymlinkNode { - name: SYMLINK_NAME2.into(), - target: "/nix/store/somewhereelse".into(), - }), + SYMLINK_NAME2.try_into().unwrap(), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap(), + }, ); } async fn populate_directory_with_keep( blob_service: &Arc<dyn BlobService>, directory_service: &Arc<dyn DirectoryService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { // upload empty blob let mut bw = blob_service.open_write().await; @@ -166,45 +161,42 @@ async fn populate_directory_with_keep( .expect("must succeed uploading"); root_nodes.insert( - DIRECTORY_WITH_KEEP_NAME.into(), - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_WITH_KEEP_NAME.into(), - digest: fixtures::DIRECTORY_WITH_KEEP.digest().into(), + DIRECTORY_WITH_KEEP_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_WITH_KEEP.digest(), size: fixtures::DIRECTORY_WITH_KEEP.size(), - }), + }, ); } /// Create a root node for DIRECTORY_WITH_KEEP, but don't upload the Directory /// itself. -async fn populate_directorynode_without_directory(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_directorynode_without_directory(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - DIRECTORY_WITH_KEEP_NAME.into(), - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_WITH_KEEP_NAME.into(), - digest: fixtures::DIRECTORY_WITH_KEEP.digest().into(), + DIRECTORY_WITH_KEEP_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_WITH_KEEP.digest(), size: fixtures::DIRECTORY_WITH_KEEP.size(), - }), + }, ); } /// Insert BLOB_A, but don't provide the blob .keep is pointing to. -async fn populate_filenode_without_blob(root_nodes: &mut BTreeMap<Bytes, Node>) { +async fn populate_filenode_without_blob(root_nodes: &mut BTreeMap<PathComponent, Node>) { root_nodes.insert( - BLOB_A_NAME.into(), - Node::File(castorepb::FileNode { - name: BLOB_A_NAME.into(), - digest: fixtures::BLOB_A_DIGEST.clone().into(), + BLOB_A_NAME.try_into().unwrap(), + Node::File { + digest: fixtures::BLOB_A_DIGEST.clone(), size: fixtures::BLOB_A.len() as u64, executable: false, - }), + }, ); } async fn populate_directory_complicated( blob_service: &Arc<dyn BlobService>, directory_service: &Arc<dyn DirectoryService>, - root_nodes: &mut BTreeMap<Bytes, Node>, + root_nodes: &mut BTreeMap<PathComponent, Node>, ) { // upload empty blob let mut bw = blob_service.open_write().await; @@ -226,12 +218,11 @@ async fn populate_directory_complicated( .expect("must succeed uploading"); root_nodes.insert( - DIRECTORY_COMPLICATED_NAME.into(), - Node::Directory(castorepb::DirectoryNode { - name: DIRECTORY_COMPLICATED_NAME.into(), - digest: fixtures::DIRECTORY_COMPLICATED.digest().into(), + DIRECTORY_COMPLICATED_NAME.try_into().unwrap(), + Node::Directory { + digest: fixtures::DIRECTORY_COMPLICATED.digest(), size: fixtures::DIRECTORY_COMPLICATED.size(), - }), + }, ); } diff --git a/tvix/castore/src/fs/inodes.rs b/tvix/castore/src/fs/inodes.rs index bdd459543470..2696fdede378 100644 --- a/tvix/castore/src/fs/inodes.rs +++ b/tvix/castore/src/fs/inodes.rs @@ -2,10 +2,7 @@ //! about inodes, which present tvix-castore nodes in a filesystem. use std::time::Duration; -use bytes::Bytes; - -use crate::proto as castorepb; -use crate::B3Digest; +use crate::{path::PathComponent, B3Digest, Node}; #[derive(Clone, Debug)] pub enum InodeData { @@ -20,27 +17,23 @@ pub enum InodeData { /// lookup and did fetch the data. #[derive(Clone, Debug)] pub enum DirectoryInodeData { - Sparse(B3Digest, u64), // digest, size - Populated(B3Digest, Vec<(u64, castorepb::node::Node)>), // [(child_inode, node)] + Sparse(B3Digest, u64), // digest, size + Populated(B3Digest, Vec<(u64, PathComponent, Node)>), // [(child_inode, name, node)] } impl InodeData { /// Constructs a new InodeData by consuming a [Node]. - /// It splits off the orginal name, so it can be used later. - pub fn from_node(node: castorepb::node::Node) -> (Self, Bytes) { + pub fn from_node(node: &Node) -> Self { match node { - castorepb::node::Node::Directory(n) => ( - Self::Directory(DirectoryInodeData::Sparse( - n.digest.try_into().unwrap(), - n.size, - )), - n.name, - ), - castorepb::node::Node::File(n) => ( - Self::Regular(n.digest.try_into().unwrap(), n.size, n.executable), - n.name, - ), - castorepb::node::Node::Symlink(n) => (Self::Symlink(n.target), n.name), + Node::Directory { digest, size } => { + Self::Directory(DirectoryInodeData::Sparse(digest.clone(), *size)) + } + Node::File { + digest, + size, + executable, + } => Self::Regular(digest.clone(), *size, *executable), + Node::Symlink { target } => Self::Symlink(target.clone().into()), } } diff --git a/tvix/castore/src/fs/mod.rs b/tvix/castore/src/fs/mod.rs index b565ed60ac42..e700a25d3966 100644 --- a/tvix/castore/src/fs/mod.rs +++ b/tvix/castore/src/fs/mod.rs @@ -15,15 +15,13 @@ use self::{ inode_tracker::InodeTracker, inodes::{DirectoryInodeData, InodeData}, }; -use crate::proto as castorepb; use crate::{ blobservice::{BlobReader, BlobService}, directoryservice::DirectoryService, - proto::{node::Node, NamedNode}, - B3Digest, + path::PathComponent, + B3Digest, Node, }; use bstr::ByteVec; -use bytes::Bytes; use fuse_backend_rs::abi::fuse_abi::{stat64, OpenOptions}; use fuse_backend_rs::api::filesystem::{ Context, FileSystem, FsOptions, GetxattrReply, ListxattrReply, ROOT_ID, @@ -89,7 +87,7 @@ pub struct TvixStoreFs<BS, DS, RN> { show_xattr: bool, /// This maps a given basename in the root to the inode we allocated for the node. - root_nodes: RwLock<HashMap<Bytes, u64>>, + root_nodes: RwLock<HashMap<PathComponent, u64>>, /// This keeps track of inodes and data alongside them. inode_tracker: RwLock<InodeTracker>, @@ -105,7 +103,7 @@ pub struct TvixStoreFs<BS, DS, RN> { u64, ( Span, - Arc<Mutex<mpsc::Receiver<(usize, Result<Node, crate::Error>)>>>, + Arc<Mutex<mpsc::Receiver<(usize, Result<(PathComponent, Node), crate::Error>)>>>, ), >, >, @@ -156,7 +154,7 @@ where /// Retrieves the inode for a given root node basename, if present. /// This obtains a read lock on self.root_nodes. - fn get_inode_for_root_name(&self, name: &[u8]) -> Option<u64> { + fn get_inode_for_root_name(&self, name: &PathComponent) -> Option<u64> { self.root_nodes.read().get(name).cloned() } @@ -167,8 +165,12 @@ where /// It is ok if it's a [DirectoryInodeData::Sparse] - in that case, a lookup /// in self.directory_service is performed, and self.inode_tracker is updated with the /// [DirectoryInodeData::Populated]. + #[allow(clippy::type_complexity)] #[instrument(skip(self), err)] - fn get_directory_children(&self, ino: u64) -> io::Result<(B3Digest, Vec<(u64, Node)>)> { + fn get_directory_children( + &self, + ino: u64, + ) -> io::Result<(B3Digest, Vec<(u64, PathComponent, Node)>)> { let data = self.inode_tracker.read().get(ino).unwrap(); match *data { // if it's populated already, return children. @@ -198,13 +200,13 @@ where let children = { let mut inode_tracker = self.inode_tracker.write(); - let children: Vec<(u64, castorepb::node::Node)> = directory - .nodes() - .map(|child_node| { - let (inode_data, _) = InodeData::from_node(child_node.clone()); + let children: Vec<(u64, PathComponent, Node)> = directory + .into_nodes() + .map(|(child_name, child_node)| { + let inode_data = InodeData::from_node(&child_node); let child_ino = inode_tracker.put(inode_data); - (child_ino, child_node) + (child_ino, child_name, child_node) }) .collect(); @@ -238,12 +240,12 @@ where /// In the case the name can't be found, a libc::ENOENT is returned. fn name_in_root_to_ino_and_data( &self, - name: &std::ffi::CStr, + name: &PathComponent, ) -> io::Result<(u64, Arc<InodeData>)> { // Look up the inode for that root node. // If there's one, [self.inode_tracker] MUST also contain the data, // which we can then return. - if let Some(inode) = self.get_inode_for_root_name(name.to_bytes()) { + if let Some(inode) = self.get_inode_for_root_name(name) { return Ok(( inode, self.inode_tracker @@ -257,7 +259,8 @@ where // We don't have it yet, look it up in [self.root_nodes]. match self.tokio_handle.block_on({ let root_nodes_provider = self.root_nodes_provider.clone(); - async move { root_nodes_provider.get_by_basename(name.to_bytes()).await } + let name = name.clone(); + async move { root_nodes_provider.get_by_basename(&name).await } }) { // if there was an error looking up the root node, propagate up an IO error. Err(_e) => Err(io::Error::from_raw_os_error(libc::EIO)), @@ -265,15 +268,9 @@ where Ok(None) => Err(io::Error::from_raw_os_error(libc::ENOENT)), // The root node does exist Ok(Some(root_node)) => { - // The name must match what's passed in the lookup, otherwise this is also a ENOENT. - if root_node.get_name() != name.to_bytes() { - debug!(root_node.name=?root_node.get_name(), found_node.name=%name.to_string_lossy(), "node name mismatch"); - return Err(io::Error::from_raw_os_error(libc::ENOENT)); - } - // Let's check if someone else beat us to updating the inode tracker and // root_nodes map. This avoids locking inode_tracker for writing. - if let Some(ino) = self.root_nodes.read().get(name.to_bytes()) { + if let Some(ino) = self.root_nodes.read().get(name) { return Ok(( *ino, self.inode_tracker.read().get(*ino).expect("must exist"), @@ -287,9 +284,9 @@ where // insert the (sparse) inode data and register in // self.root_nodes. - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&root_node); let ino = inode_tracker.put(inode_data.clone()); - root_nodes.insert(name, ino); + root_nodes.insert(name.to_owned(), ino); Ok((ino, Arc::new(inode_data))) } @@ -345,13 +342,17 @@ where ) -> io::Result<fuse_backend_rs::api::filesystem::Entry> { debug!("lookup"); + // convert the CStr to a PathComponent + // If it can't be converted, we definitely don't have anything here. + let name: PathComponent = name.try_into().map_err(|_| std::io::ErrorKind::NotFound)?; + // This goes from a parent inode to a node. // - If the parent is [ROOT_ID], we need to check // [self.root_nodes] (fetching from a [RootNode] provider if needed) // - Otherwise, lookup the parent in [self.inode_tracker] (which must be // a [InodeData::Directory]), and find the child with that name. if parent == ROOT_ID { - let (ino, inode_data) = self.name_in_root_to_ino_and_data(name)?; + let (ino, inode_data) = self.name_in_root_to_ino_and_data(&name)?; debug!(inode_data=?&inode_data, ino=ino, "Some"); return Ok(inode_data.as_fuse_entry(ino)); @@ -364,7 +365,7 @@ where // Search for that name in the list of children and return the FileAttrs. // in the children, find the one with the desired name. - if let Some((child_ino, _)) = children.iter().find(|e| e.1.get_name() == name.to_bytes()) { + if let Some((child_ino, _, _)) = children.iter().find(|(_, n, _)| n == &name) { // lookup the child [InodeData] in [self.inode_tracker]. // We know the inodes for children have already been allocated. let child_inode_data = self.inode_tracker.read().get(*child_ino).unwrap(); @@ -400,8 +401,8 @@ where self.tokio_handle.spawn( async move { let mut stream = root_nodes_provider.list().enumerate(); - while let Some(node) = stream.next().await { - if tx.send(node).await.is_err() { + while let Some(e) = stream.next().await { + if tx.send(e).await.is_err() { // If we get a send error, it means the sync code // doesn't want any more entries. break; @@ -463,12 +464,12 @@ where .map_err(|_| crate::Error::StorageError("mutex poisoned".into()))?; while let Some((i, n)) = rx.blocking_recv() { - let root_node = n.map_err(|e| { + let (name, node) = n.map_err(|e| { warn!("failed to retrieve root node: {}", e); io::Error::from_raw_os_error(libc::EIO) })?; - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&node); // obtain the inode, or allocate a new one. let ino = self.get_inode_for_root_name(&name).unwrap_or_else(|| { @@ -483,7 +484,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), })?; // If the buffer is full, add_entry will return `Ok(0)`. if written == 0 { @@ -497,15 +498,17 @@ where let (parent_digest, children) = self.get_directory_children(inode)?; Span::current().record("directory.digest", parent_digest.to_string()); - for (i, (ino, child_node)) in children.into_iter().skip(offset as usize).enumerate() { - let (inode_data, name) = InodeData::from_node(child_node); + for (i, (ino, child_name, child_node)) in + children.into_iter().skip(offset as usize).enumerate() + { + let inode_data = InodeData::from_node(&child_node); // the second parameter will become the "offset" parameter on the next call. let written = add_entry(fuse_backend_rs::api::filesystem::DirEntry { ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: child_name.as_ref(), })?; // If the buffer is full, add_entry will return `Ok(0)`. if written == 0 { @@ -550,12 +553,12 @@ where .map_err(|_| crate::Error::StorageError("mutex poisoned".into()))?; while let Some((i, n)) = rx.blocking_recv() { - let root_node = n.map_err(|e| { + let (name, node) = n.map_err(|e| { warn!("failed to retrieve root node: {}", e); io::Error::from_raw_os_error(libc::EPERM) })?; - let (inode_data, name) = InodeData::from_node(root_node); + let inode_data = InodeData::from_node(&node); // obtain the inode, or allocate a new one. let ino = self.get_inode_for_root_name(&name).unwrap_or_else(|| { @@ -571,7 +574,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), }, inode_data.as_fuse_entry(ino), )?; @@ -587,8 +590,8 @@ where let (parent_digest, children) = self.get_directory_children(inode)?; Span::current().record("directory.digest", parent_digest.to_string()); - for (i, (ino, child_node)) in children.into_iter().skip(offset as usize).enumerate() { - let (inode_data, name) = InodeData::from_node(child_node); + for (i, (ino, name, child_node)) in children.into_iter().skip(offset as usize).enumerate() { + let inode_data = InodeData::from_node(&child_node); // the second parameter will become the "offset" parameter on the next call. let written = add_entry( @@ -596,7 +599,7 @@ where ino, offset: offset + (i as u64) + 1, type_: inode_data.as_fuse_type(), - name: &name, + name: name.as_ref(), }, inode_data.as_fuse_entry(ino), )?; diff --git a/tvix/castore/src/fs/root_nodes.rs b/tvix/castore/src/fs/root_nodes.rs index 6609e049a1fc..5ed1a4d8d6c0 100644 --- a/tvix/castore/src/fs/root_nodes.rs +++ b/tvix/castore/src/fs/root_nodes.rs @@ -1,7 +1,6 @@ use std::collections::BTreeMap; -use crate::{proto::node::Node, Error}; -use bytes::Bytes; +use crate::{path::PathComponent, Error, Node}; use futures::stream::BoxStream; use tonic::async_trait; @@ -11,11 +10,12 @@ use tonic::async_trait; pub trait RootNodes: Send + Sync { /// Looks up a root CA node based on the basename of the node in the root /// directory of the filesystem. - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<Node>, Error>; + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error>; - /// Lists all root CA nodes in the filesystem. An error can be returned - /// in case listing is not allowed - fn list(&self) -> BoxStream<Result<Node, Error>>; + /// Lists all root CA nodes in the filesystem, as a tuple of (base)name + /// and Node. + /// An error can be returned in case listing is not allowed. + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>>; } #[async_trait] @@ -23,15 +23,17 @@ pub trait RootNodes: Send + Sync { /// the key is the node name. impl<T> RootNodes for T where - T: AsRef<BTreeMap<Bytes, Node>> + Send + Sync, + T: AsRef<BTreeMap<PathComponent, Node>> + Send + Sync, { - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<Node>, Error> { + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error> { Ok(self.as_ref().get(name).cloned()) } - fn list(&self) -> BoxStream<Result<Node, Error>> { + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>> { Box::pin(tokio_stream::iter( - self.as_ref().iter().map(|(_, v)| Ok(v.clone())), + self.as_ref() + .iter() + .map(|(name, node)| Ok((name.to_owned(), node.to_owned()))), )) } } diff --git a/tvix/castore/src/import/archive.rs b/tvix/castore/src/import/archive.rs index cd5b1290e031..167f799efa0f 100644 --- a/tvix/castore/src/import/archive.rs +++ b/tvix/castore/src/import/archive.rs @@ -13,7 +13,7 @@ use tracing::{instrument, warn, Level}; use crate::blobservice::BlobService; use crate::directoryservice::DirectoryService; use crate::import::{ingest_entries, IngestionEntry, IngestionError}; -use crate::proto::node::Node; +use crate::Node; use super::blobs::{self, ConcurrentBlobUploader}; diff --git a/tvix/castore/src/import/fs.rs b/tvix/castore/src/import/fs.rs index dc7821b8101e..1332fdfe57b5 100644 --- a/tvix/castore/src/import/fs.rs +++ b/tvix/castore/src/import/fs.rs @@ -16,8 +16,7 @@ use walkdir::WalkDir; use crate::blobservice::BlobService; use crate::directoryservice::DirectoryService; -use crate::proto::node::Node; -use crate::B3Digest; +use crate::{B3Digest, Node}; use super::ingest_entries; use super::IngestionEntry; diff --git a/tvix/castore/src/import/mod.rs b/tvix/castore/src/import/mod.rs index a9ac0be6b064..6e10a64939a4 100644 --- a/tvix/castore/src/import/mod.rs +++ b/tvix/castore/src/import/mod.rs @@ -4,15 +4,9 @@ //! Specific implementations, such as ingesting from the filesystem, live in //! child modules. -use crate::directoryservice::DirectoryPutter; -use crate::directoryservice::DirectoryService; +use crate::directoryservice::{DirectoryPutter, DirectoryService}; use crate::path::{Path, PathBuf}; -use crate::proto::node::Node; -use crate::proto::Directory; -use crate::proto::DirectoryNode; -use crate::proto::FileNode; -use crate::proto::SymlinkNode; -use crate::B3Digest; +use crate::{B3Digest, Directory, Node, SymlinkTargetError}; use futures::{Stream, StreamExt}; use tracing::Level; @@ -65,14 +59,6 @@ where // we break the loop manually. .expect("Tvix bug: unexpected end of stream")?; - let name = entry - .path() - .file_name() - // If this is the root node, it will have an empty name. - .unwrap_or_default() - .to_owned() - .into(); - let node = match &mut entry { IngestionEntry::Dir { .. } => { // If the entry is a directory, we traversed all its children (and @@ -98,27 +84,31 @@ where IngestionError::UploadDirectoryError(entry.path().to_owned(), e) })?; - Node::Directory(DirectoryNode { - name, - digest: directory_digest.into(), + Node::Directory { + digest: directory_digest, size: directory_size, - }) + } } - IngestionEntry::Symlink { ref target, .. } => Node::Symlink(SymlinkNode { - name, - target: target.to_owned().into(), - }), + IngestionEntry::Symlink { ref target, .. } => Node::Symlink { + target: bytes::Bytes::copy_from_slice(target).try_into().map_err( + |e: SymlinkTargetError| { + IngestionError::UploadDirectoryError( + entry.path().to_owned(), + crate::Error::StorageError(format!("invalid symlink target: {}", e)), + ) + }, + )?, + }, IngestionEntry::Regular { size, executable, digest, .. - } => Node::File(FileNode { - name, - digest: digest.to_owned().into(), + } => Node::File { + digest: digest.clone(), size: *size, executable: *executable, - }), + }, }; let parent = entry @@ -129,8 +119,24 @@ where if parent == crate::Path::ROOT { break node; } else { + let name = entry + .path() + .file_name() + // If this is the root node, it will have an empty name. + .unwrap_or_else(|| "".try_into().unwrap()) + .to_owned(); + // record node in parent directory, creating a new [Directory] if not there yet. - directories.entry(parent.to_owned()).or_default().add(node); + directories + .entry(parent.to_owned()) + .or_default() + .add(name, node) + .map_err(|e| { + IngestionError::UploadDirectoryError( + entry.path().to_owned(), + crate::Error::StorageError(e.to_string()), + ) + })?; } }; @@ -155,15 +161,8 @@ where #[cfg(debug_assertions)] { - if let Node::Directory(directory_node) = &root_node { - debug_assert_eq!( - root_directory_digest, - directory_node - .digest - .to_vec() - .try_into() - .expect("invalid digest len") - ) + if let Node::Directory { digest, .. } = &root_node { + debug_assert_eq!(&root_directory_digest, digest); } else { unreachable!("Tvix bug: directory putter initialized but no root directory node"); } @@ -209,9 +208,8 @@ mod test { use rstest::rstest; use crate::fixtures::{DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST}; - use crate::proto::node::Node; - use crate::proto::{Directory, DirectoryNode, FileNode, SymlinkNode}; use crate::{directoryservice::MemoryDirectoryService, fixtures::DUMMY_DIGEST}; + use crate::{Directory, Node}; use super::ingest_entries; use super::IngestionEntry; @@ -223,18 +221,18 @@ mod test { executable: true, digest: DUMMY_DIGEST.clone(), }], - Node::File(FileNode { name: "foo".into(), digest: DUMMY_DIGEST.clone().into(), size: 42, executable: true } - ))] + Node::File{digest: DUMMY_DIGEST.clone(), size: 42, executable: true} + )] #[case::single_symlink(vec![IngestionEntry::Symlink { path: "foo".parse().unwrap(), target: b"blub".into(), }], - Node::Symlink(SymlinkNode { name: "foo".into(), target: "blub".into()}) + Node::Symlink{target: "blub".try_into().unwrap()} )] #[case::single_dir(vec![IngestionEntry::Dir { path: "foo".parse().unwrap(), }], - Node::Directory(DirectoryNode { name: "foo".into(), digest: Directory::default().digest().into(), size: Directory::default().size()}) + Node::Directory{digest: Directory::default().digest(), size: Directory::default().size()} )] #[case::dir_with_keep(vec![ IngestionEntry::Regular { @@ -247,7 +245,7 @@ mod test { path: "foo".parse().unwrap(), }, ], - Node::Directory(DirectoryNode { name: "foo".into(), digest: DIRECTORY_WITH_KEEP.digest().into(), size: DIRECTORY_WITH_KEEP.size() }) + Node::Directory{ digest: DIRECTORY_WITH_KEEP.digest(), size: DIRECTORY_WITH_KEEP.size()} )] /// This is intentionally a bit unsorted, though it still satisfies all /// requirements we have on the order of elements in the stream. @@ -275,7 +273,7 @@ mod test { path: "blub".parse().unwrap(), }, ], - Node::Directory(DirectoryNode { name: "blub".into(), digest: DIRECTORY_COMPLICATED.digest().into(), size:DIRECTORY_COMPLICATED.size() }) + Node::Directory{ digest: DIRECTORY_COMPLICATED.digest(), size: DIRECTORY_COMPLICATED.size() } )] #[tokio::test] async fn test_ingestion(#[case] entries: Vec<IngestionEntry>, #[case] exp_root_node: Node) { diff --git a/tvix/castore/src/lib.rs b/tvix/castore/src/lib.rs index 4fca9801c97b..8ac6ca3dd66a 100644 --- a/tvix/castore/src/lib.rs +++ b/tvix/castore/src/lib.rs @@ -10,15 +10,18 @@ pub mod fixtures; #[cfg(feature = "fs")] pub mod fs; +mod nodes; +pub use nodes::*; + mod path; -pub use path::{Path, PathBuf}; +pub use path::{Path, PathBuf, PathComponent, PathComponentError}; pub mod import; pub mod proto; pub mod tonic; pub use digests::{B3Digest, B3_LEN}; -pub use errors::Error; +pub use errors::{DirectoryError, Error, ValidateNodeError}; pub use hashing_reader::{B3HashingReader, HashingReader}; #[cfg(test)] diff --git a/tvix/castore/src/nodes/directory.rs b/tvix/castore/src/nodes/directory.rs new file mode 100644 index 000000000000..f80e055dde80 --- /dev/null +++ b/tvix/castore/src/nodes/directory.rs @@ -0,0 +1,287 @@ +use std::collections::btree_map::{self, BTreeMap}; + +use crate::{errors::DirectoryError, path::PathComponent, proto, B3Digest, Node}; + +/// A Directory contains nodes, which can be Directory, File or Symlink nodes. +/// It attaches names to these nodes, which is the basename in that directory. +/// These names: +/// - MUST not contain slashes or null bytes +/// - MUST not be '.' or '..' +/// - MUST be unique across all three lists +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct Directory { + nodes: BTreeMap<PathComponent, Node>, +} + +impl Directory { + /// Constructs a new, empty Directory. + pub fn new() -> Self { + Directory { + nodes: BTreeMap::new(), + } + } + + /// Construct a [Directory] from tuples of name and [Node]. + /// + /// Inserting multiple elements with the same name will yield an error, as + /// well as exceeding the maximum size. + pub fn try_from_iter<T: IntoIterator<Item = (PathComponent, Node)>>( + iter: T, + ) -> Result<Directory, DirectoryError> { + let mut nodes = BTreeMap::new(); + + iter.into_iter().try_fold(0u64, |size, (name, node)| { + check_insert_node(size, &mut nodes, name, node) + })?; + + Ok(Self { nodes }) + } + + /// The size of a directory is the number of all regular and symlink elements, + /// the number of directory elements, and their size fields. + pub fn size(&self) -> u64 { + // It's impossible to create a Directory where the size overflows, because we + // check before every add() that the size won't overflow. + (self.nodes.len() as u64) + + self + .nodes() + .map(|(_name, n)| match n { + Node::Directory { size, .. } => 1 + size, + Node::File { .. } | Node::Symlink { .. } => 1, + }) + .sum::<u64>() + } + + /// Calculates the digest of a Directory, which is the blake3 hash of a + /// Directory protobuf message, serialized in protobuf canonical form. + pub fn digest(&self) -> B3Digest { + proto::Directory::from(self.clone()).digest() + } + + /// Allows iterating over all nodes (directories, files and symlinks) + /// For each, it returns a tuple of its name and node. + /// The elements are sorted by their names. + pub fn nodes(&self) -> impl Iterator<Item = (&PathComponent, &Node)> + Send + Sync + '_ { + self.nodes.iter() + } + + /// Dissolves a Directory into its individual names and nodes. + /// The elements are sorted by their names. + pub fn into_nodes(self) -> impl Iterator<Item = (PathComponent, Node)> + Send + Sync { + self.nodes.into_iter() + } + + /// Adds the specified [Node] to the [Directory] with a given name. + /// + /// Inserting a node that already exists with the same name in the directory + /// will yield an error, as well as exceeding the maximum size. + /// + /// In case you want to construct a [Directory] from multiple elements, use + /// [from_iter] instead. + pub fn add(&mut self, name: PathComponent, node: Node) -> Result<(), DirectoryError> { + check_insert_node(self.size(), &mut self.nodes, name, node)?; + Ok(()) + } +} + +fn checked_sum(iter: impl IntoIterator<Item = u64>) -> Option<u64> { + iter.into_iter().try_fold(0u64, |acc, i| acc.checked_add(i)) +} + +/// Helper function dealing with inserting nodes into the nodes [BTreeMap], +/// after ensuring the new size doesn't overlow and the key doesn't exist already. +/// +/// Returns the new total size, or an error. +fn check_insert_node( + current_size: u64, + nodes: &mut BTreeMap<PathComponent, Node>, + name: PathComponent, + node: Node, +) -> Result<u64, DirectoryError> { + // Check that the even after adding this new directory entry, the size calculation will not + // overflow + let new_size = checked_sum([ + current_size, + 1, + match node { + Node::Directory { size, .. } => size, + _ => 0, + }, + ]) + .ok_or(DirectoryError::SizeOverflow)?; + + match nodes.entry(name) { + btree_map::Entry::Vacant(e) => { + e.insert(node); + } + btree_map::Entry::Occupied(occupied) => { + return Err(DirectoryError::DuplicateName(occupied.key().to_owned())) + } + } + + Ok(new_size) +} + +#[cfg(test)] +mod test { + use super::{Directory, Node}; + use crate::fixtures::DUMMY_DIGEST; + use crate::{DirectoryError, PathComponent}; + + #[test] + fn from_iter_single() { + Directory::try_from_iter([( + PathComponent::try_from("b").unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + )]) + .unwrap(); + } + + #[test] + fn from_iter_multiple() { + let d = Directory::try_from_iter([ + ( + "b".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "z".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ), + ( + "f".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "c".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "g".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true, + }, + ), + ( + "t".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ( + "o".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ( + "e".try_into().unwrap(), + Node::Symlink { + target: "a".try_into().unwrap(), + }, + ), + ]) + .unwrap(); + + // Convert to proto struct and back to ensure we are not generating any invalid structures + crate::Directory::try_from(crate::proto::Directory::from(d)) + .expect("directory should be valid"); + } + + #[test] + fn add_nodes_to_directory() { + let mut d = Directory::new(); + + d.add( + "b".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + d.add( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + + // Convert to proto struct and back to ensure we are not generating any invalid structures + crate::Directory::try_from(crate::proto::Directory::from(d)) + .expect("directory should be valid"); + } + + #[test] + fn validate_overflow() { + let mut d = Directory::new(); + + assert_eq!( + d.add( + "foo".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: u64::MAX + } + ), + Err(DirectoryError::SizeOverflow) + ); + } + + #[test] + fn add_duplicate_node_to_directory() { + let mut d = Directory::new(); + + d.add( + "a".try_into().unwrap(), + Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 1, + }, + ) + .unwrap(); + assert_eq!( + format!( + "{}", + d.add( + "a".try_into().unwrap(), + Node::File { + digest: DUMMY_DIGEST.clone(), + size: 1, + executable: true + } + ) + .expect_err("adding duplicate dir entry must fail") + ), + "\"a\" is a duplicate name" + ); + } +} diff --git a/tvix/castore/src/nodes/mod.rs b/tvix/castore/src/nodes/mod.rs new file mode 100644 index 000000000000..ac7aa1e666df --- /dev/null +++ b/tvix/castore/src/nodes/mod.rs @@ -0,0 +1,48 @@ +//! This holds types describing nodes in the tvix-castore model. +mod directory; +mod symlink_target; + +use crate::B3Digest; +pub use directory::Directory; +pub use symlink_target::{SymlinkTarget, SymlinkTargetError}; + +/// A Node is either a [DirectoryNode], [FileNode] or [SymlinkNode]. +/// Nodes themselves don't have names, what gives them names is either them +/// being inside a [Directory], or a root node with its own name attached to it. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Node { + /// A DirectoryNode is a pointer to a [Directory], by its [Directory::digest]. + /// It also records a`size`. + /// Such a node is either an element in the [Directory] it itself is contained in, + /// or a standalone root node. + Directory { + /// The blake3 hash of a Directory message, serialized in protobuf canonical form. + digest: B3Digest, + /// Number of child elements in the Directory referred to by `digest`. + /// Calculated by summing up the numbers of nodes, and for each directory, + /// its size field. Can be used for inode allocation. + /// This field is precisely as verifiable as any other Merkle tree edge. + /// Resolve `digest`, and you can compute it incrementally. Resolve the entire + /// tree, and you can fully compute it from scratch. + /// A credulous implementation won't reject an excessive size, but this is + /// harmless: you'll have some ordinals without nodes. Undersizing is obvious + /// and easy to reject: you won't have an ordinal for some nodes. + size: u64, + }, + /// A FileNode represents a regular or executable file in a Directory or at the root. + File { + /// The blake3 digest of the file contents + digest: B3Digest, + + /// The file content size + size: u64, + + /// Whether the file is executable + executable: bool, + }, + /// A SymlinkNode represents a symbolic link in a Directory or at the root. + Symlink { + /// The target of the symlink. + target: SymlinkTarget, + }, +} diff --git a/tvix/castore/src/nodes/symlink_target.rs b/tvix/castore/src/nodes/symlink_target.rs new file mode 100644 index 000000000000..e9a1a0bd05c2 --- /dev/null +++ b/tvix/castore/src/nodes/symlink_target.rs @@ -0,0 +1,223 @@ +use bstr::ByteSlice; +use std::fmt::{self, Debug, Display}; + +/// A wrapper type for symlink targets. +/// Internally uses a [bytes::Bytes], but disallows empty targets and those +/// containing null bytes. +#[repr(transparent)] +#[derive(Clone, PartialEq, Eq)] +pub struct SymlinkTarget { + inner: bytes::Bytes, +} + +/// The maximum length a symlink target can have. +/// Linux allows 4095 bytes here. +pub const MAX_TARGET_LEN: usize = 4095; + +impl AsRef<[u8]> for SymlinkTarget { + fn as_ref(&self) -> &[u8] { + self.inner.as_ref() + } +} + +impl From<SymlinkTarget> for bytes::Bytes { + fn from(value: SymlinkTarget) -> Self { + value.inner + } +} + +fn validate_symlink_target<B: AsRef<[u8]>>(symlink_target: B) -> Result<B, SymlinkTargetError> { + let v = symlink_target.as_ref(); + + if v.is_empty() { + return Err(SymlinkTargetError::Empty); + } + if v.len() > MAX_TARGET_LEN { + return Err(SymlinkTargetError::TooLong); + } + if v.contains(&0x00) { + return Err(SymlinkTargetError::Null); + } + + Ok(symlink_target) +} + +impl TryFrom<bytes::Bytes> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: bytes::Bytes) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(&value) { + return Err(SymlinkTargetError::Convert(value, Box::new(e))); + } + + Ok(Self { inner: value }) + } +} + +impl TryFrom<&'static [u8]> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(&value) { + return Err(SymlinkTargetError::Convert(value.into(), Box::new(e))); + } + + Ok(Self { + inner: bytes::Bytes::from_static(value), + }) + } +} + +impl TryFrom<&str> for SymlinkTarget { + type Error = SymlinkTargetError; + + fn try_from(value: &str) -> Result<Self, Self::Error> { + if let Err(e) = validate_symlink_target(value) { + return Err(SymlinkTargetError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value.as_bytes()), + }) + } +} + +impl Debug for SymlinkTarget { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(self.inner.as_bstr(), f) + } +} + +impl Display for SymlinkTarget { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(self.inner.as_bstr(), f) + } +} + +/// Errors created when constructing / converting to [SymlinkTarget]. +#[derive(Debug, PartialEq, Eq, thiserror::Error)] +#[cfg_attr(test, derive(Clone))] +pub enum SymlinkTargetError { + #[error("cannot be empty")] + Empty, + #[error("cannot contain null bytes")] + Null, + #[error("cannot be over {} bytes long", MAX_TARGET_LEN)] + TooLong, + #[error("unable to convert '{:?}", .0.as_bstr())] + Convert(bytes::Bytes, Box<Self>), +} + +#[cfg(test)] +mod tests { + use bytes::Bytes; + use rstest::rstest; + + use super::validate_symlink_target; + use super::{SymlinkTarget, SymlinkTargetError}; + + #[rstest] + #[case::empty(b"", SymlinkTargetError::Empty)] + #[case::null(b"foo\0", SymlinkTargetError::Null)] + fn errors(#[case] v: &'static [u8], #[case] err: SymlinkTargetError) { + { + assert_eq!( + Err(err.clone()), + validate_symlink_target(v), + "validate_symlink_target must fail as expected" + ); + } + + let exp_err_v = Bytes::from_static(v); + + // Bytes + { + let v = Bytes::from_static(v); + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + // &[u8] + { + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + // &str, if this is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Err(SymlinkTargetError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + SymlinkTarget::try_from(v), + "conversion must fail as expected" + ); + } + } + } + + #[test] + fn error_toolong() { + assert_eq!( + Err(SymlinkTargetError::TooLong), + validate_symlink_target("X".repeat(5000).into_bytes().as_slice()) + ) + } + + #[rstest] + #[case::boring(b"aa")] + #[case::dot(b".")] + #[case::dotsandslashes(b"./..")] + #[case::dotdot(b"..")] + #[case::slashes(b"a/b")] + #[case::slashes_and_absolute(b"/a/b")] + #[case::invalid_utf8(b"\xc5\xc4\xd6")] + fn success(#[case] v: &'static [u8]) { + let exp = SymlinkTarget { inner: v.into() }; + + // Bytes + { + let v: Bytes = v.into(); + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + + // &[u8] + { + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + + // &str, if this is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Ok(exp.clone()), + SymlinkTarget::try_from(v), + "conversion must succeed" + ) + } + } + } +} diff --git a/tvix/castore/src/path/component.rs b/tvix/castore/src/path/component.rs new file mode 100644 index 000000000000..78aca03c50fe --- /dev/null +++ b/tvix/castore/src/path/component.rs @@ -0,0 +1,268 @@ +use bstr::ByteSlice; +use std::fmt::{self, Debug, Display}; + +/// A wrapper type for validated path components in the castore model. +/// Internally uses a [bytes::Bytes], but disallows +/// slashes, and null bytes to be present, as well as +/// '.', '..' and the empty string. +/// It also rejects components that are too long (> 255 bytes). +#[repr(transparent)] +#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct PathComponent { + pub(super) inner: bytes::Bytes, +} + +/// The maximum length an individual path component can have. +/// Linux allows 255 bytes of actual name, so we pick that. +pub const MAX_NAME_LEN: usize = 255; + +impl AsRef<[u8]> for PathComponent { + fn as_ref(&self) -> &[u8] { + self.inner.as_ref() + } +} + +impl From<PathComponent> for bytes::Bytes { + fn from(value: PathComponent) -> Self { + value.inner + } +} + +pub(super) fn validate_name<B: AsRef<[u8]>>(name: B) -> Result<(), PathComponentError> { + match name.as_ref() { + b"" => Err(PathComponentError::Empty), + b".." => Err(PathComponentError::Parent), + b"." => Err(PathComponentError::CurDir), + v if v.len() > MAX_NAME_LEN => Err(PathComponentError::TooLong), + v if v.contains(&0x00) => Err(PathComponentError::Null), + v if v.contains(&b'/') => Err(PathComponentError::Slashes), + _ => Ok(()), + } +} + +impl TryFrom<bytes::Bytes> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: bytes::Bytes) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(&value) { + return Err(PathComponentError::Convert(value, Box::new(e))); + } + + Ok(Self { inner: value }) + } +} + +impl TryFrom<&'static [u8]> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert(value.into(), Box::new(e))); + } + + Ok(Self { + inner: bytes::Bytes::from_static(value), + }) + } +} + +impl TryFrom<&str> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &str) -> Result<Self, Self::Error> { + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value.as_bytes()), + }) + } +} + +impl TryFrom<&std::ffi::CStr> for PathComponent { + type Error = PathComponentError; + + fn try_from(value: &std::ffi::CStr) -> Result<Self, Self::Error> { + let value = value.to_bytes(); + if let Err(e) = validate_name(value) { + return Err(PathComponentError::Convert( + value.to_owned().into(), + Box::new(e), + )); + } + + Ok(Self { + inner: bytes::Bytes::copy_from_slice(value), + }) + } +} + +impl Debug for PathComponent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Debug::fmt(self.inner.as_bstr(), f) + } +} + +impl Display for PathComponent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + Display::fmt(self.inner.as_bstr(), f) + } +} + +/// Errors created when parsing / validating [PathComponent]. +#[derive(Debug, PartialEq, thiserror::Error)] +#[cfg_attr(test, derive(Clone))] +pub enum PathComponentError { + #[error("cannot be empty")] + Empty, + #[error("cannot contain null bytes")] + Null, + #[error("cannot be '.'")] + CurDir, + #[error("cannot be '..'")] + Parent, + #[error("cannot contain slashes")] + Slashes, + #[error("cannot be over {} bytes long", MAX_NAME_LEN)] + TooLong, + #[error("unable to convert '{:?}'", .0.as_bstr())] + Convert(bytes::Bytes, #[source] Box<Self>), +} + +#[cfg(test)] +mod tests { + use std::ffi::CString; + + use bytes::Bytes; + use rstest::rstest; + + use super::{validate_name, PathComponent, PathComponentError}; + + #[rstest] + #[case::empty(b"", PathComponentError::Empty)] + #[case::null(b"foo\0", PathComponentError::Null)] + #[case::curdir(b".", PathComponentError::CurDir)] + #[case::parent(b"..", PathComponentError::Parent)] + #[case::slashes1(b"a/b", PathComponentError::Slashes)] + #[case::slashes2(b"/", PathComponentError::Slashes)] + fn errors(#[case] v: &'static [u8], #[case] err: PathComponentError) { + { + assert_eq!( + Err(err.clone()), + validate_name(v), + "validate_name must fail as expected" + ); + } + + let exp_err_v = Bytes::from_static(v); + + // Bytes + { + let v = Bytes::from_static(v); + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + // &[u8] + { + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + // &str, if it is valid UTF-8 + { + if let Ok(v) = std::str::from_utf8(v) { + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + } + // &CStr, if it can be constructed (fails if the payload contains null bytes) + { + if let Ok(v) = CString::new(v) { + let v = v.as_ref(); + assert_eq!( + Err(PathComponentError::Convert( + exp_err_v.clone(), + Box::new(err.clone()) + )), + PathComponent::try_from(v), + "conversion must fail as expected" + ); + } + } + } + + #[test] + fn error_toolong() { + assert_eq!( + Err(PathComponentError::TooLong), + validate_name("X".repeat(500).into_bytes().as_slice()) + ) + } + + #[test] + fn success() { + let exp = PathComponent { inner: "aa".into() }; + + // Bytes + { + let v: Bytes = "aa".into(); + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &[u8] + { + let v: &[u8] = b"aa"; + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &str + { + let v: &str = "aa"; + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + + // &CStr + { + let v = CString::new("aa").expect("CString must construct"); + let v = v.as_c_str(); + assert_eq!( + Ok(exp.clone()), + PathComponent::try_from(v), + "conversion must succeed" + ); + } + } +} diff --git a/tvix/castore/src/path.rs b/tvix/castore/src/path/mod.rs index fcc2bd01fbd6..15f31a570da9 100644 --- a/tvix/castore/src/path.rs +++ b/tvix/castore/src/path/mod.rs @@ -1,5 +1,5 @@ //! Contains data structures to deal with Paths in the tvix-castore model. - +use bstr::ByteSlice; use std::{ borrow::Borrow, fmt::{self, Debug, Display}, @@ -8,9 +8,8 @@ use std::{ str::FromStr, }; -use bstr::ByteSlice; - -use crate::proto::validate_node_name; +mod component; +pub use component::{PathComponent, PathComponentError}; /// Represents a Path in the castore model. /// These are always relative, and platform-independent, which distinguishes @@ -38,7 +37,9 @@ impl Path { if !bytes.is_empty() { // Ensure all components are valid castore node names. for component in bytes.split_str(b"/") { - validate_node_name(component).ok()?; + if component::validate_name(component).is_err() { + return None; + } } } @@ -81,10 +82,26 @@ impl Path { Ok(v) } + /// Provides an iterator over the components of the path, + /// which are invividual [PathComponent]. + /// In case the path is empty, an empty iterator is returned. + pub fn components(&self) -> impl Iterator<Item = PathComponent> + '_ { + let mut iter = self.inner.split_str(&b"/"); + + // We don't want to return an empty element, consume it if it's the only one. + if self.inner.is_empty() { + let _ = iter.next(); + } + + iter.map(|b| PathComponent { + inner: bytes::Bytes::copy_from_slice(b), + }) + } + /// Produces an iterator over the components of the path, which are /// individual byte slices. /// In case the path is empty, an empty iterator is returned. - pub fn components(&self) -> impl Iterator<Item = &[u8]> { + pub fn components_bytes(&self) -> impl Iterator<Item = &[u8]> { let mut iter = self.inner.split_str(&b"/"); // We don't want to return an empty element, consume it if it's the only one. @@ -95,11 +112,16 @@ impl Path { iter } - /// Returns the final component of the Path, if there is one. - pub fn file_name(&self) -> Option<&[u8]> { + /// Returns the final component of the Path, if there is one, in bytes. + pub fn file_name(&self) -> Option<PathComponent> { self.components().last() } + /// Returns the final component of the Path, if there is one, in bytes. + pub fn file_name_bytes(&self) -> Option<&[u8]> { + self.components_bytes().last() + } + pub fn as_bytes(&self) -> &[u8] { &self.inner } @@ -211,7 +233,9 @@ impl PathBuf { /// Adjoins `name` to self. pub fn try_push(&mut self, name: &[u8]) -> Result<(), std::io::Error> { - validate_node_name(name).map_err(|_| std::io::ErrorKind::InvalidData)?; + if component::validate_name(name).is_err() { + return Err(std::io::ErrorKind::InvalidData.into()); + } if !self.inner.is_empty() { self.inner.push(b'/'); @@ -329,7 +353,7 @@ mod test { assert_eq!(s.as_bytes(), p.as_bytes(), "inner bytes mismatch"); assert_eq!( num_components, - p.components().count(), + p.components_bytes().count(), "number of components mismatch" ); } @@ -396,10 +420,10 @@ mod test { #[case("a", vec!["a"])] #[case("a/b", vec!["a", "b"])] #[case("a/b/c", vec!["a","b", "c"])] - pub fn components(#[case] p: PathBuf, #[case] exp_components: Vec<&str>) { + pub fn components_bytes(#[case] p: PathBuf, #[case] exp_components: Vec<&str>) { assert_eq!( exp_components, - p.components() + p.components_bytes() .map(|x| x.to_str().unwrap()) .collect::<Vec<_>>() ); diff --git a/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs b/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs index ce1d2bcd244a..62fdb34a25a0 100644 --- a/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs +++ b/tvix/castore/src/proto/grpc_directoryservice_wrapper.rs @@ -1,7 +1,5 @@ -use crate::directoryservice::DirectoryGraph; -use crate::directoryservice::LeavesToRootValidator; -use crate::proto; -use crate::{directoryservice::DirectoryService, B3Digest}; +use crate::directoryservice::{DirectoryGraph, DirectoryService, LeavesToRootValidator}; +use crate::{proto, B3Digest, DirectoryError}; use futures::stream::BoxStream; use futures::TryStreamExt; use std::ops::Deref; @@ -58,13 +56,16 @@ where Status::not_found(format!("directory {} not found", digest)) })?; - Box::pin(once(Ok(directory))) + Box::pin(once(Ok(directory.into()))) } else { // If recursive was requested, traverse via get_recursive. Box::pin( - self.directory_service.get_recursive(&digest).map_err(|e| { - tonic::Status::new(tonic::Code::Internal, e.to_string()) - }), + self.directory_service + .get_recursive(&digest) + .map_ok(proto::Directory::from) + .map_err(|e| { + tonic::Status::new(tonic::Code::Internal, e.to_string()) + }), ) } })) @@ -83,7 +84,9 @@ where let mut validator = DirectoryGraph::<LeavesToRootValidator>::default(); while let Some(directory) = req_inner.message().await? { validator - .add(directory) + .add(directory.try_into().map_err(|e: DirectoryError| { + tonic::Status::new(tonic::Code::Internal, e.to_string()) + })?) .map_err(|e| tonic::Status::new(tonic::Code::Internal, e.to_string()))?; } diff --git a/tvix/castore/src/proto/mod.rs b/tvix/castore/src/proto/mod.rs index a0cec896f753..8bc74b412676 100644 --- a/tvix/castore/src/proto/mod.rs +++ b/tvix/castore/src/proto/mod.rs @@ -1,18 +1,13 @@ -#![allow(non_snake_case)] -// https://github.com/hyperium/tonic/issues/1056 -use bstr::ByteSlice; -use std::{collections::HashSet, iter::Peekable, str}; - use prost::Message; +use std::cmp::Ordering; mod grpc_blobservice_wrapper; mod grpc_directoryservice_wrapper; +use crate::{path::PathComponent, B3Digest, DirectoryError}; pub use grpc_blobservice_wrapper::GRPCBlobServiceWrapper; pub use grpc_directoryservice_wrapper::GRPCDirectoryServiceWrapper; -use crate::{B3Digest, B3_LEN}; - tonic::include_proto!("tvix.castore.v1"); #[cfg(feature = "tonic-reflection")] @@ -24,38 +19,6 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("tvix #[cfg(test)] mod tests; -/// Errors that can occur during the validation of [Directory] messages. -#[derive(Debug, PartialEq, Eq, thiserror::Error)] -pub enum ValidateDirectoryError { - /// Elements are not in sorted order - #[error("{:?} is not sorted", .0.as_bstr())] - WrongSorting(Vec<u8>), - /// Multiple elements with the same name encountered - #[error("{:?} is a duplicate name", .0.as_bstr())] - DuplicateName(Vec<u8>), - /// Invalid node - #[error("invalid node with name {:?}: {:?}", .0.as_bstr(), .1.to_string())] - InvalidNode(Vec<u8>, ValidateNodeError), - #[error("Total size exceeds u32::MAX")] - SizeOverflow, -} - -/// Errors that occur during Node validation -#[derive(Debug, PartialEq, Eq, thiserror::Error)] -pub enum ValidateNodeError { - #[error("No node set")] - NoNodeSet, - /// Invalid digest length encountered - #[error("Invalid Digest length: {0}")] - InvalidDigestLen(usize), - /// Invalid name encountered - #[error("Invalid name: {}", .0.as_bstr())] - InvalidName(Vec<u8>), - /// Invalid symlink target - #[error("Invalid symlink target: {}", .0.as_bstr())] - InvalidSymlinkTarget(Vec<u8>), -} - /// Errors that occur during StatBlobResponse validation #[derive(Debug, PartialEq, Eq, thiserror::Error)] pub enum ValidateStatBlobResponseError { @@ -64,186 +27,6 @@ pub enum ValidateStatBlobResponseError { InvalidDigestLen(usize, usize), } -/// Checks a Node name for validity as an intermediate node. -/// We disallow slashes, null bytes, '.', '..' and the empty string. -pub(crate) fn validate_node_name(name: &[u8]) -> Result<(), ValidateNodeError> { - if name.is_empty() - || name == b".." - || name == b"." - || name.contains(&0x00) - || name.contains(&b'/') - { - Err(ValidateNodeError::InvalidName(name.to_owned())) - } else { - Ok(()) - } -} - -/// NamedNode is implemented for [FileNode], [DirectoryNode] and [SymlinkNode] -/// and [node::Node], so we can ask all of them for the name easily. -pub trait NamedNode { - fn get_name(&self) -> &[u8]; -} - -impl NamedNode for &FileNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for &DirectoryNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for &SymlinkNode { - fn get_name(&self) -> &[u8] { - &self.name - } -} - -impl NamedNode for node::Node { - fn get_name(&self) -> &[u8] { - match self { - node::Node::File(node_file) => &node_file.name, - node::Node::Directory(node_directory) => &node_directory.name, - node::Node::Symlink(node_symlink) => &node_symlink.name, - } - } -} - -impl Node { - /// Ensures the node has a valid enum kind (is Some), and passes its - // per-enum validation. - // The inner root node is returned for easier consumption. - pub fn validate(&self) -> Result<&node::Node, ValidateNodeError> { - if let Some(node) = self.node.as_ref() { - node.validate()?; - Ok(node) - } else { - Err(ValidateNodeError::NoNodeSet) - } - } -} - -impl node::Node { - /// Returns the node with a new name. - pub fn rename(self, name: bytes::Bytes) -> Self { - match self { - node::Node::Directory(n) => node::Node::Directory(DirectoryNode { name, ..n }), - node::Node::File(n) => node::Node::File(FileNode { name, ..n }), - node::Node::Symlink(n) => node::Node::Symlink(SymlinkNode { name, ..n }), - } - } - - /// Ensures the node has a valid name, and checks the type-specific fields too. - pub fn validate(&self) -> Result<(), ValidateNodeError> { - match self { - // for a directory root node, ensure the digest has the appropriate size. - node::Node::Directory(directory_node) => { - if directory_node.digest.len() != B3_LEN { - Err(ValidateNodeError::InvalidDigestLen( - directory_node.digest.len(), - ))?; - } - validate_node_name(&directory_node.name) - } - // for a file root node, ensure the digest has the appropriate size. - node::Node::File(file_node) => { - if file_node.digest.len() != B3_LEN { - Err(ValidateNodeError::InvalidDigestLen(file_node.digest.len()))?; - } - validate_node_name(&file_node.name) - } - // ensure the symlink target is not empty and doesn't contain null bytes. - node::Node::Symlink(symlink_node) => { - if symlink_node.target.is_empty() || symlink_node.target.contains(&b'\0') { - Err(ValidateNodeError::InvalidSymlinkTarget( - symlink_node.target.to_vec(), - ))?; - } - validate_node_name(&symlink_node.name) - } - } - } -} - -impl PartialOrd for node::Node { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for node::Node { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for FileNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for FileNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for SymlinkNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for SymlinkNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -impl PartialOrd for DirectoryNode { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) - } -} - -impl Ord for DirectoryNode { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.get_name().cmp(other.get_name()) - } -} - -/// Accepts a name, and a mutable reference to the previous name. -/// If the passed name is larger than the previous one, the reference is updated. -/// If it's not, an error is returned. -fn update_if_lt_prev<'n>( - prev_name: &mut &'n [u8], - name: &'n [u8], -) -> Result<(), ValidateDirectoryError> { - if *name < **prev_name { - return Err(ValidateDirectoryError::WrongSorting(name.to_vec())); - } - *prev_name = name; - Ok(()) -} - -/// Inserts the given name into a HashSet if it's not already in there. -/// If it is, an error is returned. -fn insert_once<'n>( - seen_names: &mut HashSet<&'n [u8]>, - name: &'n [u8], -) -> Result<(), ValidateDirectoryError> { - if seen_names.get(name).is_some() { - return Err(ValidateDirectoryError::DuplicateName(name.to_vec())); - } - seen_names.insert(name); - Ok(()) -} - fn checked_sum(iter: impl IntoIterator<Item = u64>) -> Option<u64> { iter.into_iter().try_fold(0u64, |acc, i| acc.checked_add(i)) } @@ -280,117 +63,211 @@ impl Directory { .as_bytes() .into() } +} - /// validate checks the directory for invalid data, such as: - /// - violations of name restrictions - /// - invalid digest lengths - /// - not properly sorted lists - /// - duplicate names in the three lists - pub fn validate(&self) -> Result<(), ValidateDirectoryError> { - let mut seen_names: HashSet<&[u8]> = HashSet::new(); - - let mut last_directory_name: &[u8] = b""; - let mut last_file_name: &[u8] = b""; - let mut last_symlink_name: &[u8] = b""; +impl TryFrom<Directory> for crate::Directory { + type Error = DirectoryError; + + fn try_from(value: Directory) -> Result<Self, Self::Error> { + // Check directories, files and symlinks are sorted + // We'll notice duplicates across all three fields when constructing the Directory. + // FUTUREWORK: use is_sorted() once stable, and/or implement the producer for + // [crate::Directory::try_from_iter] iterating over all three and doing all checks inline. + value + .directories + .iter() + .try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; + value.files.iter().try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; + value.symlinks.iter().try_fold(&b""[..], |prev_name, e| { + match e.name.as_ref().cmp(prev_name) { + Ordering::Less => Err(DirectoryError::WrongSorting(e.name.to_owned())), + Ordering::Equal => Err(DirectoryError::DuplicateName( + e.name + .to_owned() + .try_into() + .map_err(DirectoryError::InvalidName)?, + )), + Ordering::Greater => Ok(e.name.as_ref()), + } + })?; - // check directories - for directory_node in &self.directories { - node::Node::Directory(directory_node.clone()) - .validate() - .map_err(|e| { - ValidateDirectoryError::InvalidNode(directory_node.name.to_vec(), e) - })?; + // FUTUREWORK: use is_sorted() once stable, and/or implement the producer for + // [crate::Directory::try_from_iter] iterating over all three and doing all checks inline. + let mut elems: Vec<(PathComponent, crate::Node)> = + Vec::with_capacity(value.directories.len() + value.files.len() + value.symlinks.len()); - update_if_lt_prev(&mut last_directory_name, &directory_node.name)?; - insert_once(&mut seen_names, &directory_node.name)?; + for e in value.directories { + elems.push( + Node { + node: Some(node::Node::Directory(e)), + } + .into_name_and_node()?, + ); } - // check files - for file_node in &self.files { - node::Node::File(file_node.clone()) - .validate() - .map_err(|e| ValidateDirectoryError::InvalidNode(file_node.name.to_vec(), e))?; - - update_if_lt_prev(&mut last_file_name, &file_node.name)?; - insert_once(&mut seen_names, &file_node.name)?; + for e in value.files { + elems.push( + Node { + node: Some(node::Node::File(e)), + } + .into_name_and_node()?, + ) } - // check symlinks - for symlink_node in &self.symlinks { - node::Node::Symlink(symlink_node.clone()) - .validate() - .map_err(|e| ValidateDirectoryError::InvalidNode(symlink_node.name.to_vec(), e))?; - - update_if_lt_prev(&mut last_symlink_name, &symlink_node.name)?; - insert_once(&mut seen_names, &symlink_node.name)?; + for e in value.symlinks { + elems.push( + Node { + node: Some(node::Node::Symlink(e)), + } + .into_name_and_node()?, + ) } - self.size_checked() - .ok_or(ValidateDirectoryError::SizeOverflow)?; - - Ok(()) + crate::Directory::try_from_iter(elems) } +} - /// Allows iterating over all three nodes ([DirectoryNode], [FileNode], - /// [SymlinkNode]) in an ordered fashion, as long as the individual lists - /// are sorted (which can be checked by the [Directory::validate]). - pub fn nodes(&self) -> DirectoryNodesIterator { - return DirectoryNodesIterator { - i_directories: self.directories.iter().peekable(), - i_files: self.files.iter().peekable(), - i_symlinks: self.symlinks.iter().peekable(), - }; - } +impl From<crate::Directory> for Directory { + fn from(value: crate::Directory) -> Self { + let mut directories = vec![]; + let mut files = vec![]; + let mut symlinks = vec![]; + + for (name, node) in value.into_nodes() { + match node { + crate::Node::File { + digest, + size, + executable, + } => files.push(FileNode { + name: name.into(), + digest: digest.into(), + size, + executable, + }), + crate::Node::Directory { digest, size } => directories.push(DirectoryNode { + name: name.into(), + digest: digest.into(), + size, + }), + crate::Node::Symlink { target } => { + symlinks.push(SymlinkNode { + name: name.into(), + target: target.into(), + }); + } + } + } - /// Adds the specified [node::Node] to the [Directory], preserving sorted entries. - /// This assumes the [Directory] to be sorted prior to adding the node. - /// - /// Inserting an element that already exists with the same name in the directory is not - /// supported. - pub fn add(&mut self, node: node::Node) { - debug_assert!( - !self.files.iter().any(|x| x.get_name() == node.get_name()), - "name already exists in files" - ); - debug_assert!( - !self - .directories - .iter() - .any(|x| x.get_name() == node.get_name()), - "name already exists in directories" - ); - debug_assert!( - !self - .symlinks - .iter() - .any(|x| x.get_name() == node.get_name()), - "name already exists in symlinks" - ); + Directory { + directories, + files, + symlinks, + } + } +} - match node { - node::Node::File(node) => { - let pos = self - .files - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.files.insert(pos, node); +impl Node { + /// Converts a proto [Node] to a [crate::Node], and splits off the name. + pub fn into_name_and_node(self) -> Result<(PathComponent, crate::Node), DirectoryError> { + match self.node.ok_or_else(|| DirectoryError::NoNodeSet)? { + node::Node::Directory(n) => { + let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?; + let digest = B3Digest::try_from(n.digest) + .map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?; + + let node = crate::Node::Directory { + digest, + size: n.size, + }; + + Ok((name, node)) } - node::Node::Directory(node) => { - let pos = self - .directories - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.directories.insert(pos, node); + node::Node::File(n) => { + let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?; + let digest = B3Digest::try_from(n.digest) + .map_err(|e| DirectoryError::InvalidNode(name.clone(), e.into()))?; + + let node = crate::Node::File { + digest, + size: n.size, + executable: n.executable, + }; + + Ok((name, node)) } - node::Node::Symlink(node) => { - let pos = self - .symlinks - .binary_search(&node) - .expect_err("Tvix bug: dir entry with name already exists"); - self.symlinks.insert(pos, node); + + node::Node::Symlink(n) => { + let name: PathComponent = n.name.try_into().map_err(DirectoryError::InvalidName)?; + + let node = crate::Node::Symlink { + target: n.target.try_into().map_err(|e| { + DirectoryError::InvalidNode( + name.clone(), + crate::ValidateNodeError::InvalidSymlinkTarget(e), + ) + })?, + }; + + Ok((name, node)) } } } + + /// Construsts a [Node] from a name and [crate::Node]. + /// The name is a [bytes::Bytes], not a [PathComponent], as we have use an + /// empty name in some places. + pub fn from_name_and_node(name: bytes::Bytes, n: crate::Node) -> Self { + match n { + crate::Node::Directory { digest, size } => Self { + node: Some(node::Node::Directory(DirectoryNode { + name, + digest: digest.into(), + size, + })), + }, + crate::Node::File { + digest, + size, + executable, + } => Self { + node: Some(node::Node::File(FileNode { + name, + digest: digest.into(), + size, + executable, + })), + }, + crate::Node::Symlink { target } => Self { + node: Some(node::Node::Symlink(SymlinkNode { + name, + target: target.into(), + })), + }, + } + } } impl StatBlobResponse { @@ -409,65 +286,3 @@ impl StatBlobResponse { Ok(()) } } - -/// Struct to hold the state of an iterator over all nodes of a Directory. -/// -/// Internally, this keeps peekable Iterators over all three lists of a -/// Directory message. -pub struct DirectoryNodesIterator<'a> { - // directory: &Directory, - i_directories: Peekable<std::slice::Iter<'a, DirectoryNode>>, - i_files: Peekable<std::slice::Iter<'a, FileNode>>, - i_symlinks: Peekable<std::slice::Iter<'a, SymlinkNode>>, -} - -/// looks at two elements implementing NamedNode, and returns true if "left -/// is smaller / comes first". -/// -/// Some(_) is preferred over None. -fn left_name_lt_right<A: NamedNode, B: NamedNode>(left: Option<&A>, right: Option<&B>) -> bool { - match left { - // if left is None, right always wins - None => false, - Some(left_inner) => { - // left is Some. - match right { - // left is Some, right is None - left wins. - None => true, - Some(right_inner) => { - // both are Some - compare the name. - return left_inner.get_name() < right_inner.get_name(); - } - } - } - } -} - -impl Iterator for DirectoryNodesIterator<'_> { - type Item = node::Node; - - // next returns the next node in the Directory. - // we peek at all three internal iterators, and pick the one with the - // smallest name, to ensure lexicographical ordering. - // The individual lists are already known to be sorted. - fn next(&mut self) -> Option<Self::Item> { - if left_name_lt_right(self.i_directories.peek(), self.i_files.peek()) { - // i_directories is still in the game, compare with symlinks - if left_name_lt_right(self.i_directories.peek(), self.i_symlinks.peek()) { - self.i_directories - .next() - .cloned() - .map(node::Node::Directory) - } else { - self.i_symlinks.next().cloned().map(node::Node::Symlink) - } - } else { - // i_files is still in the game, compare with symlinks - if left_name_lt_right(self.i_files.peek(), self.i_symlinks.peek()) { - self.i_files.next().cloned().map(node::Node::File) - } else { - self.i_symlinks.next().cloned().map(node::Node::Symlink) - } - } - } -} diff --git a/tvix/castore/src/proto/tests/directory.rs b/tvix/castore/src/proto/tests/directory.rs index 81b73a048d52..efbc4e9f2af1 100644 --- a/tvix/castore/src/proto/tests/directory.rs +++ b/tvix/castore/src/proto/tests/directory.rs @@ -1,7 +1,5 @@ -use crate::proto::{ - node, Directory, DirectoryNode, FileNode, SymlinkNode, ValidateDirectoryError, - ValidateNodeError, -}; +use crate::proto::{Directory, DirectoryError, DirectoryNode, FileNode, SymlinkNode}; +use crate::ValidateNodeError; use hex_literal::hex; @@ -149,7 +147,7 @@ fn digest() { #[test] fn validate_empty() { let d = Directory::default(); - assert_eq!(d.validate(), Ok(())); + assert!(crate::Directory::try_from(d).is_ok()); } #[test] @@ -157,18 +155,15 @@ fn validate_invalid_names() { { let d = Directory { directories: vec![DirectoryNode { - name: "".into(), + name: b"\0"[..].into(), digest: DUMMY_DIGEST.to_vec().into(), size: 42, }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"") - } - _ => panic!("unexpected error"), - }; + + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -180,12 +175,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b".") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -198,12 +189,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"..") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -214,12 +201,8 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"\x00") - } - _ => panic!("unexpected error"), - }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } { @@ -230,12 +213,20 @@ fn validate_invalid_names() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(n, ValidateNodeError::InvalidName(_)) => { - assert_eq!(n, b"foo/bar") - } - _ => panic!("unexpected error"), + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); + } + + { + let d = Directory { + symlinks: vec![SymlinkNode { + name: bytes::Bytes::copy_from_slice("X".repeat(500).into_bytes().as_slice()), + target: "foo".into(), + }], + ..Default::default() }; + let e = crate::Directory::try_from(d).expect_err("must fail"); + assert!(matches!(e, DirectoryError::InvalidName(_))); } } @@ -249,8 +240,8 @@ fn validate_invalid_digest() { }], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::InvalidNode(_, ValidateNodeError::InvalidDigestLen(n)) => { + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::InvalidNode(_, ValidateNodeError::InvalidDigestLen(n)) => { assert_eq!(n, 2) } _ => panic!("unexpected error"), @@ -276,15 +267,15 @@ fn validate_sorting() { ], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::WrongSorting(s) => { - assert_eq!(s, b"a"); + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::WrongSorting(s) => { + assert_eq!(s.as_ref(), b"a"); } _ => panic!("unexpected error"), } } - // "a" exists twice, bad. + // "a" exists twice (same types), bad. { let d = Directory { directories: vec![ @@ -301,9 +292,31 @@ fn validate_sorting() { ], ..Default::default() }; - match d.validate().expect_err("must fail") { - ValidateDirectoryError::DuplicateName(s) => { - assert_eq!(s, b"a"); + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::DuplicateName(s) => { + assert_eq!(s.as_ref(), b"a"); + } + _ => panic!("unexpected error"), + } + } + + // "a" exists twice (different types), bad. + { + let d = Directory { + directories: vec![DirectoryNode { + name: "a".into(), + digest: DUMMY_DIGEST.to_vec().into(), + size: 42, + }], + symlinks: vec![SymlinkNode { + name: "a".into(), + target: "b".into(), + }], + ..Default::default() + }; + match crate::Directory::try_from(d).expect_err("must fail") { + DirectoryError::DuplicateName(s) => { + assert_eq!(s.as_ref(), b"a"); } _ => panic!("unexpected error"), } @@ -327,7 +340,7 @@ fn validate_sorting() { ..Default::default() }; - d.validate().expect("validate shouldn't error"); + crate::Directory::try_from(d).expect("validate shouldn't error"); } // [b, c] and [a] are both properly sorted. @@ -352,101 +365,6 @@ fn validate_sorting() { ..Default::default() }; - d.validate().expect("validate shouldn't error"); + crate::Directory::try_from(d).expect("validate shouldn't error"); } } - -#[test] -fn validate_overflow() { - let d = Directory { - directories: vec![DirectoryNode { - name: "foo".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: u64::MAX, - }], - ..Default::default() - }; - - match d.validate().expect_err("must fail") { - ValidateDirectoryError::SizeOverflow => {} - _ => panic!("unexpected error"), - } -} - -#[test] -fn add_nodes_to_directory() { - let mut d = Directory { - ..Default::default() - }; - - d.add(node::Node::Directory(DirectoryNode { - name: "b".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::Directory(DirectoryNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::Directory(DirectoryNode { - name: "z".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - - d.add(node::Node::File(FileNode { - name: "f".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - d.add(node::Node::File(FileNode { - name: "c".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - d.add(node::Node::File(FileNode { - name: "g".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); - - d.add(node::Node::Symlink(SymlinkNode { - name: "t".into(), - target: "a".into(), - })); - d.add(node::Node::Symlink(SymlinkNode { - name: "o".into(), - target: "a".into(), - })); - d.add(node::Node::Symlink(SymlinkNode { - name: "e".into(), - target: "a".into(), - })); - - d.validate().expect("directory should be valid"); -} - -#[test] -#[cfg_attr(not(debug_assertions), ignore)] -#[should_panic = "name already exists in directories"] -fn add_duplicate_node_to_directory_panics() { - let mut d = Directory { - ..Default::default() - }; - - d.add(node::Node::Directory(DirectoryNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - })); - d.add(node::Node::File(FileNode { - name: "a".into(), - digest: DUMMY_DIGEST.to_vec().into(), - size: 1, - executable: true, - })); -} diff --git a/tvix/castore/src/proto/tests/directory_nodes_iterator.rs b/tvix/castore/src/proto/tests/directory_nodes_iterator.rs deleted file mode 100644 index 68f147a33210..000000000000 --- a/tvix/castore/src/proto/tests/directory_nodes_iterator.rs +++ /dev/null @@ -1,78 +0,0 @@ -use crate::proto::Directory; -use crate::proto::DirectoryNode; -use crate::proto::FileNode; -use crate::proto::NamedNode; -use crate::proto::SymlinkNode; - -#[test] -fn iterator() { - let d = Directory { - directories: vec![ - DirectoryNode { - name: "c".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "d".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "h".into(), - ..DirectoryNode::default() - }, - DirectoryNode { - name: "l".into(), - ..DirectoryNode::default() - }, - ], - files: vec![ - FileNode { - name: "b".into(), - ..FileNode::default() - }, - FileNode { - name: "e".into(), - ..FileNode::default() - }, - FileNode { - name: "g".into(), - ..FileNode::default() - }, - FileNode { - name: "j".into(), - ..FileNode::default() - }, - ], - symlinks: vec![ - SymlinkNode { - name: "a".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "f".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "i".into(), - ..SymlinkNode::default() - }, - SymlinkNode { - name: "k".into(), - ..SymlinkNode::default() - }, - ], - }; - - // We keep this strings here and convert to string to make the comparison - // less messy. - let mut node_names: Vec<String> = vec![]; - - for node in d.nodes() { - node_names.push(String::from_utf8(node.get_name().to_vec()).unwrap()); - } - - assert_eq!( - vec!["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"], - node_names - ); -} diff --git a/tvix/castore/src/proto/tests/mod.rs b/tvix/castore/src/proto/tests/mod.rs index 8d903bacb6c5..74334029e84c 100644 --- a/tvix/castore/src/proto/tests/mod.rs +++ b/tvix/castore/src/proto/tests/mod.rs @@ -1,2 +1 @@ mod directory; -mod directory_nodes_iterator; diff --git a/tvix/castore/src/tests/import.rs b/tvix/castore/src/tests/import.rs index 72fb06aea877..32c2c363689f 100644 --- a/tvix/castore/src/tests/import.rs +++ b/tvix/castore/src/tests/import.rs @@ -2,14 +2,11 @@ use crate::blobservice::{self, BlobService}; use crate::directoryservice; use crate::fixtures::*; use crate::import::fs::ingest_path; -use crate::proto; +use crate::Node; use tempfile::TempDir; #[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStrExt; - -#[cfg(target_family = "unix")] #[tokio::test] async fn symlink() { let blob_service = blobservice::from_addr("memory://").await.unwrap(); @@ -33,10 +30,9 @@ async fn symlink() { .expect("must succeed"); assert_eq!( - proto::node::Node::Symlink(proto::SymlinkNode { - name: "doesntmatter".into(), - target: "/nix/store/somewhereelse".into(), - }), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap() + }, root_node, ) } @@ -59,12 +55,11 @@ async fn single_file() { .expect("must succeed"); assert_eq!( - proto::node::Node::File(proto::FileNode { - name: "root".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, root_node, ); @@ -95,17 +90,10 @@ async fn complicated() { // ensure root_node matched expectations assert_eq!( - proto::node::Node::Directory(proto::DirectoryNode { - name: tmpdir - .path() - .file_name() - .unwrap() - .as_bytes() - .to_owned() - .into(), - digest: DIRECTORY_COMPLICATED.digest().into(), + Node::Directory { + digest: DIRECTORY_COMPLICATED.digest().clone(), size: DIRECTORY_COMPLICATED.size(), - }), + }, root_node, ); diff --git a/tvix/cli/Cargo.toml b/tvix/cli/Cargo.toml index 2b624917ee87..27cd5a6b395c 100644 --- a/tvix/cli/Cargo.toml +++ b/tvix/cli/Cargo.toml @@ -15,25 +15,23 @@ tvix-store = { path = "../store", default-features = false, features = []} tvix-eval = { path = "../eval" } tvix-glue = { path = "../glue" } tvix-tracing = { path = "../tracing" } -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -dirs = "4.0.0" -rustyline = "10.0.0" -rnix = "0.11.0" -rowan = "*" -smol_str = "0.2.0" -thiserror = "1.0.38" -tokio = "1.28.0" -tracing = "0.1.40" -tracing-indicatif = "0.3.6" -rustc-hash = "2.0.0" -mimalloc = "0.1.43" - -[dependencies.wu-manber] -git = "https://github.com/tvlfyi/wu-manber.git" +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +dirs = { workspace = true } +rustyline = { workspace = true } +rnix = { workspace = true } +rowan = { workspace = true } +smol_str = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +rustc-hash = { workspace = true } +mimalloc = { workspace = true } +wu-manber = { workspace = true } [dev-dependencies] -expect-test = "1.5.0" +expect-test = { workspace = true } [features] default = [] diff --git a/tvix/cli/default.nix b/tvix/cli/default.nix index 90394f6d28c7..175e088c2dea 100644 --- a/tvix/cli/default.nix +++ b/tvix/cli/default.nix @@ -49,24 +49,29 @@ let # Constructs a Derivation invoking tvix-cli inside a build, ensures the # calculated tvix output path matches what's passed in externally. - mkNixpkgsEvalTest = attrpath: expectedPath: - let - name = "tvix-eval-test-${builtins.replaceStrings [".drv"] ["-drv"] attrpath}"; - in - (pkgs.runCommand name { } '' - export SSL_CERT_FILE=/dev/null - TVIX_OUTPUT=$(${tvix-cli}/bin/tvix -E '(import ${pkgs.path} {}).${attrpath}') - EXPECTED='${/* the verbatim expected Tvix output: */ "=> \"${builtins.unsafeDiscardStringContext expectedPath}\" :: string"}' + mkNixpkgsEvalTest = + { attrPath ? null # An attribute that must already be accessible from `pkgs`. Should evaluate to a store path. + , expr ? null # A Nix expression that should evaluate to a store path. + , expectedPath # The expected store path that should match one of the above. + }: + assert lib.assertMsg (attrPath != null || expr != null) "Either 'attrPath' or 'expr' must be set."; + let + name = "tvix-eval-test-${builtins.replaceStrings [".drv"] ["-drv"] (if expr != null then "custom-expr" else attrPath)}"; + in + (pkgs.runCommand name { } '' + export SSL_CERT_FILE=/dev/null + TVIX_OUTPUT=$(${tvix-cli}/bin/tvix --no-warnings -E '${if expr != null then expr else "(import ${pkgs.path} {}).${attrPath}"}') + EXPECTED='${/* the verbatim expected Tvix output: */ "=> \"${builtins.unsafeDiscardStringContext expectedPath}\" :: string"}' - echo "Tvix output: ''${TVIX_OUTPUT}" - if [ "$TVIX_OUTPUT" != "$EXPECTED" ]; then - echo "Correct would have been ''${EXPECTED}" - exit 1 - fi + echo "Tvix output: ''${TVIX_OUTPUT}" + if [ "$TVIX_OUTPUT" != "$EXPECTED" ]; then + echo "Correct would have been ''${EXPECTED}" + exit 1 + fi - echo "Output was correct." - touch $out - ''); + echo "Output was correct." + touch $out + ''); benchmarks = { @@ -79,13 +84,24 @@ let }; evalTests = { - eval-nixpkgs-stdenv-drvpath = (mkNixpkgsEvalTest "stdenv.drvPath" pkgs.stdenv.drvPath); - eval-nixpkgs-stdenv-outpath = (mkNixpkgsEvalTest "stdenv.outPath" pkgs.stdenv.outPath); - eval-nixpkgs-hello-outpath = (mkNixpkgsEvalTest "hello.outPath" pkgs.hello.outPath); - eval-nixpkgs-firefox-outpath = (mkNixpkgsEvalTest "firefox.outPath" pkgs.firefox.outPath); - eval-nixpkgs-firefox-drvpath = (mkNixpkgsEvalTest "firefox.drvPath" pkgs.firefox.drvPath); - eval-nixpkgs-cross-stdenv-outpath = (mkNixpkgsEvalTest "pkgsCross.aarch64-multiplatform.stdenv.outPath" pkgs.pkgsCross.aarch64-multiplatform.stdenv.outPath); - eval-nixpkgs-cross-hello-outpath = (mkNixpkgsEvalTest "pkgsCross.aarch64-multiplatform.hello.outPath" pkgs.pkgsCross.aarch64-multiplatform.hello.outPath); + eval-nixpkgs-stdenv-drvpath = (mkNixpkgsEvalTest { attrPath = "stdenv.drvPath"; expectedPath = pkgs.stdenv.drvPath; }); + eval-nixpkgs-stdenv-outpath = (mkNixpkgsEvalTest { attrPath = "stdenv.outPath"; expectedPath = pkgs.stdenv.outPath; }); + eval-nixpkgs-hello-outpath = (mkNixpkgsEvalTest { attrPath = "hello.outPath"; expectedPath = pkgs.hello.outPath; }); + eval-nixpkgs-firefox-outpath = (mkNixpkgsEvalTest { attrPath = "firefox.outPath"; expectedPath = pkgs.firefox.outPath; }); + eval-nixpkgs-firefox-drvpath = (mkNixpkgsEvalTest { attrPath = "firefox.drvPath"; expectedPath = pkgs.firefox.drvPath; }); + eval-nixpkgs-cross-stdenv-outpath = (mkNixpkgsEvalTest { attrPath = "pkgsCross.aarch64-multiplatform.stdenv.outPath"; expectedPath = pkgs.pkgsCross.aarch64-multiplatform.stdenv.outPath; }); + eval-nixpkgs-cross-hello-outpath = (mkNixpkgsEvalTest { attrPath = "pkgsCross.aarch64-multiplatform.hello.outPath"; expectedPath = pkgs.pkgsCross.aarch64-multiplatform.hello.outPath; }); + # Our CI runner currently uses Nix version lower than 2.12, which means it uses the old JSON library. + # The NixOS docs generate a JSON file with all the NixOS options, and so output is different between Tvix (and Nix 2.12+) and our CI runner's Nix version, + # so we disable the NixOS docs generation for now. TODO(kranzes): Re-enable NixOS docs once the CI runner is using a newer Nix version. + eval-nixpkgs-nixos-gnome-installer-drvpath = (mkNixpkgsEvalTest { + expr = "(import ${pkgs.path}/nixos/release.nix { configuration = { documentation.nixos.enable = (import ${pkgs.path}/lib).mkForce false; }; }).iso_gnome.${pkgs.system}.drvPath"; + expectedPath = (import "${pkgs.path}/nixos/release.nix" { configuration.documentation.nixos.enable = lib.mkForce false; }).iso_gnome.${pkgs.system}.drvPath; + }); + eval-nixpkgs-nixos-gnome-installer-outpath = (mkNixpkgsEvalTest { + expr = "(import ${pkgs.path}/nixos/release.nix { configuration = { documentation.nixos.enable = (import ${pkgs.path}/lib).mkForce false; }; }).iso_gnome.${pkgs.system}.outPath"; + expectedPath = (import "${pkgs.path}/nixos/release.nix" { configuration.documentation.nixos.enable = lib.mkForce false; }).iso_gnome.${pkgs.system}.outPath; + }); }; in { @@ -94,5 +110,5 @@ in }; # Expose benchmarks and evalTests as standard CI targets. - passthru = benchmarks // evalTests; + passthru = previousAttrs.passthru // benchmarks // evalTests; }) diff --git a/tvix/cli/src/args.rs b/tvix/cli/src/args.rs index a4d1bcae157e..36f9a6a262dd 100644 --- a/tvix/cli/src/args.rs +++ b/tvix/cli/src/args.rs @@ -4,6 +4,14 @@ use clap::Parser; use tracing::Level; use tvix_store::utils::ServiceUrlsMemory; +/// Provides a CLI interface to trigger evaluation using tvix-eval. +/// +/// Uses configured tvix-[ca]store and tvix-build components, +/// and by default a set of builtins similar to these present in Nix. +/// +/// None of the stores available add to the local `/nix/store` location. +/// +/// The CLI interface is not stable and subject to change. #[derive(Parser, Clone)] pub struct Args { /// A global log level to use when printing logs. @@ -64,4 +72,15 @@ pub struct Args { #[arg(long, env, default_value = "dummy://")] pub build_service_addr: String, + + /// An optional path in which Derivations encountered during evaluation + /// are dumped into, after evaluation. If it doesn't exist, the directory is created. + /// + /// Files dumped there are named like they would show up in `/nix/store`, + /// if produced by Nix. Existing files are not overwritten. + /// + /// This is only for debugging and diffing purposes for post-eval inspection; + /// Tvix does not read from these. + #[clap(long)] + pub drv_dumpdir: Option<PathBuf>, } diff --git a/tvix/cli/src/lib.rs b/tvix/cli/src/lib.rs index 2351da13a771..beb4c505207c 100644 --- a/tvix/cli/src/lib.rs +++ b/tvix/cli/src/lib.rs @@ -112,10 +112,10 @@ pub fn evaluate( eval_builder = eval_builder.add_builtins(impure_builtins()); eval_builder = add_derivation_builtins(eval_builder, Rc::clone(&tvix_store_io)); eval_builder = add_fetcher_builtins(eval_builder, Rc::clone(&tvix_store_io)); - eval_builder = add_import_builtins(eval_builder, tvix_store_io); - eval_builder = configure_nix_path(eval_builder, &args.nix_search_path); + eval_builder = add_import_builtins(eval_builder, Rc::clone(&tvix_store_io)); } }; + eval_builder = configure_nix_path(eval_builder, &args.nix_search_path); if let Some(source_map) = source_map { eval_builder = eval_builder.with_source_map(source_map); @@ -173,6 +173,21 @@ pub fn evaluate( } } + if let Some(dumpdir) = &args.drv_dumpdir { + // Dump all known derivations files to `dumpdir`. + std::fs::create_dir_all(dumpdir).expect("failed to create drv dumpdir"); + tvix_store_io + .known_paths + .borrow() + .get_derivations() + // Skip already dumped derivations. + .filter(|(drv_path, _)| !dumpdir.join(drv_path.to_string()).exists()) + .for_each(|(drv_path, drv)| { + std::fs::write(dumpdir.join(drv_path.to_string()), drv.to_aterm_bytes()) + .expect("failed to write drv to dumpdir"); + }) + } + Ok(EvalResult { globals, value: result.value, diff --git a/tvix/cli/tests/repl.rs b/tvix/cli/tests/repl.rs index c6644330976e..7b9b9e34550a 100644 --- a/tvix/cli/tests/repl.rs +++ b/tvix/cli/tests/repl.rs @@ -9,7 +9,11 @@ macro_rules! test_repl { #[test] fn $name() { let tokio_runtime = tokio::runtime::Runtime::new().unwrap(); - let args = tvix_cli::Args::parse_from(Vec::<OsString>::new()); + let args = tvix_cli::Args::parse_from(vec![ + OsString::from("tvix"), + OsString::from("--nix-search-path"), + OsString::from("nixpkgs=/tmp"), + ]); let mut repl = tvix_cli::Repl::new(init_io_handle(&tokio_runtime, &args), &args); $({ let result = repl.send($send.into()); @@ -83,3 +87,12 @@ test_repl!(explain() { => a 2-item attribute set "#]]; }); + +test_repl!(reference_nix_path() { + "<nixpkgs>" => expect![[r#" + => /tmp :: path + "#]]; + "<nixpkgs>" => expect![[r#" + => /tmp :: path + "#]]; +}); diff --git a/tvix/clippy.toml b/tvix/clippy.toml index be7709684c6f..31952cc80ad1 100644 --- a/tvix/clippy.toml +++ b/tvix/clippy.toml @@ -1,6 +1,8 @@ # prevents a false-positive lint on our types containing bytes::Bytes # https://rust-lang.github.io/rust-clippy/master/index.html#/mutable_key_type ignore-interior-mutability = [ + # make sure to specify the originating type name, not re-exports! "bytes::Bytes", - "tvix_castore::digests::B3Digest" + "tvix_castore::digests::B3Digest", + "tvix_castore::path::component::PathComponent" ] diff --git a/tvix/crate-hashes.json b/tvix/crate-hashes.json index 11679cb2ebdd..42b46c2515d2 100644 --- a/tvix/crate-hashes.json +++ b/tvix/crate-hashes.json @@ -1,3 +1,4 @@ { + "git+https://github.com/liufuyang/bigtable_rs?rev=1818355a5373a5bc2c84287e3a4e3807154ac8ef#0.2.10": "0mn6iw1z7gdxbarsqiwscbdr25nplwlvzs0rs51vgnnjfsnbgl6q", "git+https://github.com/tvlfyi/wu-manber.git#wu-manber@0.1.0": "1zhk83lbq99xzyjwphv2qrb8f8qgfqwa5bbbvyzm0z0bljsjv0pd" } \ No newline at end of file diff --git a/tvix/default.nix b/tvix/default.nix index f8aa47a108c5..8e09c5b88346 100644 --- a/tvix/default.nix +++ b/tvix/default.nix @@ -18,6 +18,7 @@ let (k: (lib.nameValuePair "${crates.internal.crates.${k}.crateName}-${crates.internal.crates.${k}.version}" crates.internal.crates.${k}.src.outputHash) ) [ + "bigtable_rs" "wu-manber" ]); }; @@ -40,59 +41,6 @@ in { inherit crates protos; - # Run crate2nix generate, ensure the output doesn't differ afterwards - # (and doesn't fail). - # - # Currently this re-downloads every crate every time - # crate2nix-check (but not crate2nix) is built. - # TODO(amjoseph): be less wasteful with bandwidth. - # - crate2nix-check = - let - outputHashAlgo = "sha256"; - in - pkgs.stdenv.mkDerivation { - inherit src; - - # Important: we include the hash of all Cargo related files in the derivation name. - # This forces the FOD to be rebuilt/re-verified whenever one of them changes. - name = "tvix-crate2nix-check-" + builtins.substring 0 8 (builtins.hashString "sha256" - (lib.concatMapStrings (f: builtins.hashFile "sha256" f) - ([ ./Cargo.toml ./Cargo.lock ] ++ (map (m: ./. + "/${m}/Cargo.toml") (lib.importTOML ./Cargo.toml).workspace.members)) - ) - ); - - nativeBuildInputs = with pkgs; [ git cacert cargo ]; - buildPhase = '' - export CARGO_HOME=$(mktemp -d) - - # The following command can be omitted, in which case - # crate2nix-generate will run it automatically, but won't show the - # output, which makes it look like the build is somehow "stuck" for a - # minute or two. - cargo metadata > /dev/null - - ${pkgs.crate2nix}/bin/crate2nix generate --all-features - ${pkgs.treefmt}/bin/treefmt Cargo.nix \ - --no-cache \ - --on-unmatched=debug \ - --config-file=${depot.tools.depotfmt.config} \ - --tree-root=. - - # technically unnecessary, but provides more-helpful output in case of error - diff -ur Cargo.nix ${src}/Cargo.nix - - # the FOD hash will check that the (re-)generated Cargo.nix matches the committed Cargo.nix - cp Cargo.nix $out - ''; - - # This is an FOD in order to allow `cargo` to perform network access. - outputHashMode = "flat"; - inherit outputHashAlgo; - outputHash = builtins.hashFile outputHashAlgo ./Cargo.nix; - env.SSL_CERT_FILE = "${pkgs.cacert.out}/etc/ssl/certs/ca-bundle.crt"; - }; - # Provide the Tvix logo in both .webp and .png format. logo = pkgs.runCommand "logo" { @@ -158,12 +106,22 @@ in buildPhase = "cargo clippy --tests --all-features --benches --examples -- -Dwarnings | tee $out"; }; + crate2nix-check = + let + crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; + in + crate2nix-check.command.overrideAttrs { + meta.ci.extraSteps = { + inherit crate2nix-check; + }; + }; + meta.ci.targets = [ "clippy" - "crate2nix-check" "shell" "rust-docs" + "crate2nix-check" ]; - utils = import ./utils.nix { inherit lib depot; }; + utils = import ./utils.nix { inherit pkgs lib depot; }; } diff --git a/tvix/docs/src/TODO.md b/tvix/docs/src/TODO.md index debad55a4f7c..af558c9580fe 100644 --- a/tvix/docs/src/TODO.md +++ b/tvix/docs/src/TODO.md @@ -25,20 +25,6 @@ sure noone is working on this, or has some specific design in mind already. with a different level of `--strict`, but the toplevel doc-comment suggests its generic? -### castore - - The `Directory` struct is currently being generated from the protobuf definitions. - We should change this, have `Directory` be our own type (holding a `B3Digest`), - rather than a `Vec<u8>`, and move impls to there. - The protobuf struct can stay in `castore/proto`, but should only be used - when converting to/from Protobuf definitons: - - gRPC client/server impls - - implementations that use protobuf as a internal data format - - `digest()` implementation of our stricter `Directory` struct - - The traits should use our stricter type. This would allow removing a lot of - the checks we currently have when converting from `Vec<u8>` to `B3Digest` in - various places. - ### Correctness > Performance A lot of the Nix behaviour isn't well documented out, and before going too deep into performance optimizations, we need to ensure we properly grasped all hidden @@ -158,8 +144,14 @@ there are ruled out, adding other types of builders might be interesting. - gVisor - Cloud Hypervisor (using similar technique as `//tvix//boot`). -Long-term, we want to extend traits and gRPC protocol to expose more telemetry, -logs etc, but this is something requiring a lot of designing. +Long-term, we want to extend traits and gRPC protocol. +This requires some more designing. Some goals: + + - use stricter castore types (and maybe stricter build types) instead of + proto types, add conversion code where necessary + - (more granular) control while a build is happening + - expose more telemetry and logs + ### Store composition - Combinators: list-by-priority, first-come-first-serve, cache @@ -220,12 +212,6 @@ logs etc, but this is something requiring a lot of designing. (https://github.com/apache/arrow-rs/pull/5650), there's no support on the local filesystem yet. We'd need to add support to this (through xattrs). -### DirectoryService - - Add an `object_store` variant, storing a Directory *closure* keyed by the - root `Directory` digest. This won't allow indexing intermediate Directory - nodes, but once we have `DirectoryService` composition, it shouldn't be an - issue. - ### PathInfoService - sqlite backend (different schema than the Nix one, we need the root nodes data!) diff --git a/tvix/docs/src/contributing/gerrit.md b/tvix/docs/src/contributing/gerrit.md index 71877d9d4aab..3644e8cb0200 100644 --- a/tvix/docs/src/contributing/gerrit.md +++ b/tvix/docs/src/contributing/gerrit.md @@ -10,14 +10,13 @@ StackOverflow account. Additionally if you would prefer not to use an SSO option or wish to have a backup authentication strategy in the event of downed server or otherwise, we -recommend setting up a TVL-specific LDAP account. Do note that our IdP -(Keycloak) sometimes has [problems doing SSO with GitHub][github-problematic], -so you might get an “unexpected error” while trying to sign in with GitHub; -that error is not your fault. You can create that account by following these -instructions: +recommend setting up a TVL-specific LDAP account. + +You can create such an account by following these instructions: 1. Checkout [TVL’s monorepo][check-out-monorepo] if you haven’t already -2. Be a member of `#tvl` on [hackint][], a communication network. +2. Be a member of `#tvix-dev` (and/or `#tvl`) on [hackint][], a communication + network. 3. Generate a user entry using [//web/pwcrypt](https://signup.tvl.fyi/). 4. Commit that generated user entry to our LDAP server configuration in [ops/users][ops-users] (for an example, see: @@ -106,7 +105,6 @@ system, as well as the other [attention set rules][attention-set-rules]. [ops-users]: https://code.tvl.fyi/tree/ops/users/default.nix [hackint]: https://hackint.org [github-diff]: https://gerrit.wikimedia.org/r/Documentation/intro-gerrit-walkthrough-github.html -[github-problematic]: https://b.tvl.fyi/issues/201 [attention sets]: https://gerrit-review.googlesource.com/Documentation/user-attention-set.html [attention-set-rules]: https://gerrit-review.googlesource.com/Documentation/user-attention-set.html#_rules [^keycloak]: [^amend]: `git commit --amend` diff --git a/tvix/eval/Cargo.toml b/tvix/eval/Cargo.toml index 9637165e8500..c99bea4f7125 100644 --- a/tvix/eval/Cargo.toml +++ b/tvix/eval/Cargo.toml @@ -8,41 +8,42 @@ name = "tvix_eval" [dependencies] builtin-macros = { path = "./builtin-macros", package = "tvix-eval-builtin-macros" } -bytes = "1.4.0" -bstr = { version = "1.8.0", features = ["serde"] } -codemap = "0.1.3" -codemap-diagnostic = "0.1.1" -dirs = "4.0.0" -genawaiter = { version = "0.99.1", default-features = false } -imbl = { version = "3.0", features = [ "serde" ] } -itertools = "0.12.0" -lazy_static = "1.4.0" -lexical-core = { version = "0.8.5", features = ["format", "parse-floats"] } -os_str_bytes = { version = "6.3", features = ["conversions"] } -path-clean = "0.1" -proptest = { version = "1.3.0", default-features = false, features = ["std", "alloc", "tempfile"], optional = true } -regex = "1.6.0" -rnix = "0.11.0" -rowan = "*" # pinned by rnix -serde = { version = "1.0", features = [ "rc", "derive" ] } -serde_json = "1.0" -smol_str = "0.2.0" -tabwriter = "1.2" -test-strategy = { version = "0.2.1", optional = true } +bytes = { workspace = true } +bstr = { workspace = true, features = ["serde"] } +codemap = { workspace = true } +codemap-diagnostic = { workspace = true } +dirs = { workspace = true } +genawaiter = { workspace = true } +itertools = { workspace = true } +lazy_static = { workspace = true } +lexical-core = { workspace = true, features = ["format", "parse-floats"] } +os_str_bytes = { workspace = true, features = ["conversions"] } +path-clean = { workspace = true } +proptest = { workspace = true, features = ["std", "alloc", "tempfile"], optional = true } +regex = { workspace = true } +rnix = { workspace = true } +rowan = { workspace = true } # pinned by rnix +serde = { workspace = true, features = ["rc", "derive"] } +serde_json = { workspace = true } +smol_str = { workspace = true } +tabwriter = { workspace = true } +test-strategy = { workspace = true, optional = true } toml = "0.6.0" -sha2 = "0.10.8" -sha1 = "0.10.6" -md-5 = "0.10.6" -data-encoding = "2.6.0" -rustc-hash = "2.0.0" +sha2 = { workspace = true } +sha1 = { workspace = true } +md-5 = { workspace = true } +data-encoding = { workspace = true } +rustc-hash = { workspace = true } +nohash-hasher = { workspace = true } +vu128 = { workspace = true } [dev-dependencies] -criterion = "0.5" -itertools = "0.12.0" -mimalloc = "0.1.43" -pretty_assertions = "1.2.1" -rstest = "0.19.0" -tempfile = "3.3.0" +criterion = { workspace = true } +itertools = { workspace = true } +mimalloc = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } [features] default = ["impure", "arbitrary", "nix_tests"] @@ -55,7 +56,7 @@ nix_tests = [] impure = [] # Enables Arbitrary impls for internal types (required to run tests) -arbitrary = ["proptest", "test-strategy", "imbl/proptest"] +arbitrary = ["proptest", "test-strategy"] # Don't leak strings (enable this if you care about peak memory usage of eval) # diff --git a/tvix/eval/builtin-macros/Cargo.toml b/tvix/eval/builtin-macros/Cargo.toml index 3a35ea12a0c0..0696d742b342 100644 --- a/tvix/eval/builtin-macros/Cargo.toml +++ b/tvix/eval/builtin-macros/Cargo.toml @@ -5,9 +5,9 @@ authors = [ "Griffin Smith <root@gws.fyi>" ] edition = "2021" [dependencies] -syn = { version = "1.0.57", features = ["full", "parsing", "printing", "visit", "visit-mut", "extra-traits"] } -quote = "1.0.8" -proc-macro2 = "1" +syn = { version = "1.0.109", features = ["full", "parsing", "printing", "visit", "visit-mut", "extra-traits"] } +quote = { workspace = true } +proc-macro2 = { workspace = true } [lib] proc-macro = true diff --git a/tvix/eval/default.nix b/tvix/eval/default.nix index 9dd5875f85a5..9370c81ced1c 100644 --- a/tvix/eval/default.nix +++ b/tvix/eval/default.nix @@ -8,9 +8,9 @@ testInputs = [ pkgs.nix ]; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "nix_tests" ]; override.testInputs = [ pkgs.nix ]; - }; + }); }) diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs index e961738e3653..f130bbc5b15f 100644 --- a/tvix/eval/src/builtins/mod.rs +++ b/tvix/eval/src/builtins/mod.rs @@ -6,7 +6,6 @@ use bstr::{ByteSlice, ByteVec}; use builtin_macros::builtins; use genawaiter::rc::Gen; -use imbl::OrdMap; use regex::Regex; use std::cmp::{self, Ordering}; use std::collections::BTreeMap; @@ -85,7 +84,6 @@ mod pure_builtins { use std::ffi::OsString; use bstr::{BString, ByteSlice, B}; - use imbl::Vector; use itertools::Itertools; use os_str_bytes::OsStringBytes; use rustc_hash::FxHashSet; @@ -246,7 +244,7 @@ mod pure_builtins { #[builtin("concatLists")] async fn builtin_concat_lists(co: GenCo, lists: Value) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::new(); + let mut out = Vec::new(); for value in lists.to_list()? { let list = try_value!(generators::request_force(&co, value).await).to_list()?; @@ -259,7 +257,7 @@ mod pure_builtins { #[builtin("concatMap")] async fn builtin_concat_map(co: GenCo, f: Value, list: Value) -> Result<Value, ErrorKind> { let list = list.to_list()?; - let mut res = imbl::Vector::new(); + let mut res = Vec::new(); for val in list { let out = generators::request_call_with(&co, f.clone(), [val]).await; let out = try_value!(generators::request_force(&co, out).await); @@ -387,13 +385,13 @@ mod pure_builtins { #[builtin("filter")] async fn builtin_filter(co: GenCo, pred: Value, list: Value) -> Result<Value, ErrorKind> { let list: NixList = list.to_list()?; - let mut out = imbl::Vector::new(); + let mut out = Vec::new(); for value in list { let result = generators::request_call_with(&co, pred.clone(), [value.clone()]).await; let verdict = try_value!(generators::request_force(&co, result).await); if verdict.as_bool()? { - out.push_back(value); + out.push(value); } } @@ -481,7 +479,7 @@ mod pure_builtins { let operator = attrs.select_required("operator")?; - let mut res = imbl::Vector::new(); + let mut res = Vec::new(); let mut done_keys: Vec<Value> = vec![]; while let Some(val) = work_set.pop_front() { @@ -499,7 +497,7 @@ mod pure_builtins { continue; } - res.push_back(val.clone()); + res.push(val.clone()); let op_result = generators::request_force( &co, @@ -520,14 +518,18 @@ mod pure_builtins { #[lazy] generator: Value, length: Value, ) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::<Value>::new(); let len = length.as_int()?; + let mut out = Vec::with_capacity( + len.try_into() + .map_err(|_| ErrorKind::Abort(format!("can not create list of size {}", len)))?, + ); + // the best span we can get… let span = generators::request_span(&co).await; for i in 0..len { let val = Value::Thunk(Thunk::new_suspended_call(generator.clone(), i.into(), span)); - out.push_back(val); + out.push(val); } Ok(Value::List(out.into())) @@ -548,7 +550,7 @@ mod pure_builtins { #[builtin("groupBy")] async fn builtin_group_by(co: GenCo, f: Value, list: Value) -> Result<Value, ErrorKind> { - let mut res: BTreeMap<NixString, imbl::Vector<Value>> = BTreeMap::new(); + let mut res: BTreeMap<NixString, Vec<Value>> = BTreeMap::new(); for val in list.to_list()? { let key = try_value!( generators::request_force( @@ -559,7 +561,7 @@ mod pure_builtins { ) .to_str()?; - res.entry(key).or_default().push_back(val); + res.entry(key).or_default().push(val); } Ok(Value::attrs(NixAttrs::from_iter( res.into_iter() @@ -625,7 +627,7 @@ mod pure_builtins { let elements = groups .into_iter() .map(|(key, group)| { - let mut outputs: Vector<NixString> = Vector::new(); + let mut outputs: Vec<NixString> = Vec::new(); let mut is_path = false; let mut all_outputs = false; @@ -638,7 +640,7 @@ mod pure_builtins { NixContextElement::Single { name, derivation } => { debug_assert!(derivation == key, "Unexpected group containing mixed keys, expected: {:?}, encountered {:?}", key, derivation); - outputs.push_back(name.clone().into()); + outputs.push(name.clone().into()); } NixContextElement::Derivation(drv_path) => { @@ -665,7 +667,7 @@ mod pure_builtins { vec_attrs.push(("outputs", Value::List(outputs .into_iter() .map(|s| s.into()) - .collect::<Vector<Value>>() + .collect::<Vec<Value>>() .into() ))); } @@ -792,7 +794,7 @@ mod pure_builtins { } let mut right_keys = right_set.keys(); - let mut out: OrdMap<NixString, Value> = OrdMap::new(); + let mut out: BTreeMap<NixString, Value> = BTreeMap::new(); // Both iterators have at least one entry let mut left = left_keys.next().unwrap(); @@ -973,15 +975,16 @@ mod pure_builtins { } #[builtin("map")] - async fn builtin_map(co: GenCo, #[lazy] f: Value, list: Value) -> Result<Value, ErrorKind> { - let mut out = imbl::Vector::<Value>::new(); + async fn builtin_map(co: GenCo, #[lazy] f: Value, list_val: Value) -> Result<Value, ErrorKind> { + let list = list_val.to_list()?; + let mut out = Vec::with_capacity(list.len()); // the best span we can get… let span = generators::request_span(&co).await; - for val in list.to_list()? { + for val in list { let result = Value::Thunk(Thunk::new_suspended_call(f.clone(), val, span)); - out.push_back(result) + out.push(result) } Ok(Value::List(out.into())) @@ -994,7 +997,7 @@ mod pure_builtins { attrs: Value, ) -> Result<Value, ErrorKind> { let attrs = attrs.to_attrs()?; - let mut out = imbl::OrdMap::new(); + let mut out: BTreeMap<NixString, Value> = BTreeMap::new(); // the best span we can get… let span = generators::request_span(&co).await; @@ -1040,7 +1043,7 @@ mod pure_builtins { // and then a compressor name will be extracted from that. grp.map(|g| Value::from(g.as_str())).unwrap_or(Value::Null) }) - .collect::<imbl::Vector<Value>>() + .collect::<Vec<Value>>() .into(), )), None => Ok(Value::Null), @@ -1083,17 +1086,17 @@ mod pure_builtins { #[builtin("partition")] async fn builtin_partition(co: GenCo, pred: Value, list: Value) -> Result<Value, ErrorKind> { - let mut right: imbl::Vector<Value> = Default::default(); - let mut wrong: imbl::Vector<Value> = Default::default(); + let mut right: Vec<Value> = Default::default(); + let mut wrong: Vec<Value> = Default::default(); let list: NixList = list.to_list()?; for elem in list { let result = generators::request_call_with(&co, pred.clone(), [elem.clone()]).await; if try_value!(generators::request_force(&co, result).await).as_bool()? { - right.push_back(elem); + right.push(elem); } else { - wrong.push_back(elem); + wrong.push(elem); }; } @@ -1248,12 +1251,12 @@ mod pure_builtins { let re = Regex::new(re.to_str()?).unwrap(); let mut capture_locations = re.capture_locations(); let num_captures = capture_locations.len(); - let mut ret = imbl::Vector::new(); + let mut ret = Vec::new(); let mut pos = 0; while let Some(thematch) = re.captures_read_at(&mut capture_locations, text, pos) { // push the unmatched characters preceding the match - ret.push_back(Value::from(NixString::new_inherit_context_from( + ret.push(Value::from(NixString::new_inherit_context_from( &s, &text[pos..thematch.start()], ))); @@ -1262,7 +1265,7 @@ mod pure_builtins { // group in the regex, containing the characters // matched by that capture group, or null if no match. // We skip capture 0; it represents the whole match. - let v: imbl::Vector<Value> = (1..num_captures) + let v: Vec<Value> = (1..num_captures) .map(|i| capture_locations.get(i)) .map(|o| { o.map(|(start, end)| { @@ -1273,7 +1276,7 @@ mod pure_builtins { .unwrap_or(Value::Null) }) .collect(); - ret.push_back(Value::List(NixList::from(v))); + ret.push(Value::List(NixList::from(v))); if pos == text.len() { break; } @@ -1283,7 +1286,7 @@ mod pure_builtins { // push the unmatched characters following the last match // Here, a surprising thing happens: we silently discard the original // context. This is as intended, Nix does the same. - ret.push_back(Value::from(&text[pos..])); + ret.push(Value::from(&text[pos..])); Ok(Value::List(NixList::from(ret))) } diff --git a/tvix/eval/src/chunk.rs b/tvix/eval/src/chunk.rs index e9c65db72590..2a5446a782ed 100644 --- a/tvix/eval/src/chunk.rs +++ b/tvix/eval/src/chunk.rs @@ -1,9 +1,10 @@ +use crate::opcode::{CodeIdx, ConstantIdx, Op, OpArg}; +use crate::value::Value; +use crate::{CoercionKind, SourceCode}; use std::io::Write; -use std::ops::{Index, IndexMut}; -use crate::opcode::{CodeIdx, ConstantIdx, OpCode}; -use crate::value::Value; -use crate::SourceCode; +/// Maximum size of a u64 encoded in the vu128 varint encoding. +const U64_VARINT_SIZE: usize = 9; /// Represents a source location from which one or more operations /// were compiled. @@ -30,39 +31,69 @@ struct SourceSpan { /// emitted by the compiler. #[derive(Debug, Default)] pub struct Chunk { - pub code: Vec<OpCode>, + pub code: Vec<u8>, pub constants: Vec<Value>, spans: Vec<SourceSpan>, + + /// Index of the last operation (i.e. not data) written to the code vector. + /// Some operations (e.g. jump patching) need to know this. + last_op: usize, } -impl Index<ConstantIdx> for Chunk { - type Output = Value; +impl Chunk { + pub fn push_op(&mut self, op: Op, span: codemap::Span) -> usize { + self.last_op = self.code.len(); + self.code.push(op as u8); + self.push_span(span, self.last_op); + self.last_op + } - fn index(&self, index: ConstantIdx) -> &Self::Output { - &self.constants[index.0] + pub fn push_uvarint(&mut self, data: u64) { + let mut encoded = [0u8; U64_VARINT_SIZE]; + let bytes_written = vu128::encode_u64(&mut encoded, data); + self.code.extend_from_slice(&encoded[..bytes_written]); } -} -impl Index<CodeIdx> for Chunk { - type Output = OpCode; + pub fn read_uvarint(&self, idx: usize) -> (u64, usize) { + debug_assert!( + idx < self.code.len(), + "invalid bytecode (missing varint operand)", + ); - fn index(&self, index: CodeIdx) -> &Self::Output { - &self.code[index.0] + if self.code.len() - idx >= U64_VARINT_SIZE { + vu128::decode_u64( + &self.code[idx..idx + U64_VARINT_SIZE] + .try_into() + .expect("size statically checked"), + ) + } else { + let mut tmp = [0u8; U64_VARINT_SIZE]; + tmp[..self.code.len() - idx].copy_from_slice(&self.code[idx..]); + vu128::decode_u64(&tmp) + } } -} -impl IndexMut<CodeIdx> for Chunk { - fn index_mut(&mut self, index: CodeIdx) -> &mut Self::Output { - &mut self.code[index.0] + pub fn push_u16(&mut self, data: u16) { + self.code.extend_from_slice(&data.to_le_bytes()) } -} -impl Chunk { - pub fn push_op(&mut self, data: OpCode, span: codemap::Span) -> CodeIdx { - let idx = self.code.len(); - self.code.push(data); - self.push_span(span, idx); - CodeIdx(idx) + /// Patches the argument to the jump operand of the jump at the given index + /// to point to the *next* instruction that will be emitted. + pub fn patch_jump(&mut self, idx: usize) { + let offset = (self.code.len() - idx - /* arg idx = */ 1 - /* jump arg size = */ 2) as u16; + self.code[idx + 1..idx + 3].copy_from_slice(&offset.to_le_bytes()) + } + + pub fn read_u16(&self, idx: usize) -> u16 { + if idx + 2 > self.code.len() { + panic!("Tvix bug: invalid bytecode (expected u16 operand not found)") + } + + let byte_array: &[u8; 2] = &self.code[idx..idx + 2] + .try_into() + .expect("fixed-size slice can not fail to convert to array"); + + u16::from_le_bytes(*byte_array) } /// Get the first span of a chunk, no questions asked. @@ -70,23 +101,13 @@ impl Chunk { self.spans[0].span } - /// Return a reference to the last op in the chunk, if any - pub fn last_op(&self) -> Option<&OpCode> { - self.code.last() - } - - /// Pop the last operation from the chunk and clean up its tracked - /// span. Used when the compiler backtracks. - pub fn pop_op(&mut self) { - // Simply drop the last op. - self.code.pop(); - - if let Some(span) = self.spans.last() { - // If the last span started at this op, drop it. - if span.start == self.code.len() { - self.spans.pop(); - } + /// Return the last op in the chunk together with its index, if any. + pub fn last_op(&self) -> Option<(Op, usize)> { + if self.code.is_empty() { + return None; } + + Some((self.code[self.last_op].into(), self.last_op)) } pub fn push_constant(&mut self, data: Value) -> ConstantIdx { @@ -100,8 +121,6 @@ impl Chunk { self.constants.get(constant.0) } - // Span tracking implementation - fn push_span(&mut self, span: codemap::Span, start: usize) { match self.spans.last_mut() { // We do not need to insert the same span again, as this @@ -136,76 +155,88 @@ impl Chunk { } /// Write the disassembler representation of the operation at - /// `idx` to the specified writer. + /// `idx` to the specified writer, and return how many bytes in the code to + /// skip for the next op. pub fn disassemble_op<W: Write>( &self, writer: &mut W, source: &SourceCode, width: usize, idx: CodeIdx, - ) -> Result<(), std::io::Error> { + ) -> Result<usize, std::io::Error> { write!(writer, "{:#width$x}\t ", idx.0, width = width)?; // Print continuation character if the previous operation was at // the same line, otherwise print the line. let line = source.get_line(self.get_span(idx)); - if idx.0 > 0 && source.get_line(self.get_span(CodeIdx(idx.0 - 1))) == line { + if idx.0 > 0 && source.get_line(self.get_span(idx - 1)) == line { write!(writer, " |\t")?; } else { write!(writer, "{:4}\t", line)?; } - let a = |idx| match &self[idx] { + let _fmt_constant = |idx: ConstantIdx| match &self.constants[idx.0] { Value::Thunk(t) => t.debug_repr(), Value::Closure(c) => format!("closure({:p})", c.lambda), Value::Blueprint(b) => format!("blueprint({:p})", b), val => format!("{}", val), }; - match self[idx] { - OpCode::OpConstant(idx) => { - writeln!(writer, "OpConstant({}@{})", a(idx), idx.0) - } - OpCode::OpClosure(idx) => { - writeln!(writer, "OpClosure({}@{})", a(idx), idx.0) - } - OpCode::OpThunkClosure(idx) => { - writeln!(writer, "OpThunkClosure({}@{})", a(idx), idx.0) + let op: Op = self.code[idx.0].into(); + + match op.arg_type() { + OpArg::None => { + writeln!(writer, "Op{:?}", op)?; + Ok(1) } - OpCode::OpThunkSuspended(idx) => { - writeln!(writer, "OpThunkSuspended({}@{})", a(idx), idx.0) + + OpArg::Fixed => { + let arg = self.read_u16(idx.0 + 1); + writeln!(writer, "Op{:?}({})", op, arg)?; + Ok(3) } - op => writeln!(writer, "{:?}", op), - }?; - Ok(()) - } + OpArg::Uvarint => { + let (arg, size) = self.read_uvarint(idx.0 + 1); + writeln!(writer, "Op{:?}({})", op, arg)?; + Ok(1 + size) + } - /// Extend this chunk with the content of another, moving out of the other - /// in the process. - /// - /// This is used by the compiler when it detects that it unnecessarily - /// thunked a nested expression. - pub fn extend(&mut self, other: Self) { - // Some operations need to be modified in certain ways before being - // valid as part of the new chunk. - let const_count = self.constants.len(); - for (idx, op) in other.code.iter().enumerate() { - let span = other.get_span(CodeIdx(idx)); - match op { - // As the constants shift, the index needs to be moved relatively. - OpCode::OpConstant(ConstantIdx(idx)) => { - self.push_op(OpCode::OpConstant(ConstantIdx(idx + const_count)), span) + _ => match op { + Op::CoerceToString => { + let kind: CoercionKind = self.code[idx.0 + 1].into(); + writeln!(writer, "Op{:?}({:?})", op, kind)?; + Ok(2) } - // Other operations either operate on relative offsets, or no - // offsets, and are safe to keep as-is. - _ => self.push_op(*op, span), - }; - } + Op::Closure | Op::ThunkClosure | Op::ThunkSuspended => { + let mut cidx = idx.0 + 1; - self.constants.extend(other.constants); - self.spans.extend(other.spans); + let (bp_idx, size) = self.read_uvarint(cidx); + cidx += size; + + let (packed_count, size) = self.read_uvarint(cidx); + cidx += size; + + let captures_with = packed_count & 0b1 == 1; + let count = packed_count >> 1; + + write!(writer, "Op{:?}(BP @ {}, ", op, bp_idx)?; + if captures_with { + write!(writer, "captures with, ")?; + } + writeln!(writer, "{} upvalues)", count)?; + + for _ in 0..count { + let (_, size) = self.read_uvarint(cidx); + cidx += size; + } + + Ok(cidx - idx.0) + } + _ => panic!("Tvix bug: don't know how to format argument for Op{:?}", op), + }, + } } } @@ -221,79 +252,49 @@ mod tests { #[test] fn push_op() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, dummy_span()); - assert_eq!(chunk.code.last().unwrap(), &OpCode::OpAdd); + let idx = chunk.push_op(Op::Add, dummy_span()); + assert_eq!(*chunk.code.last().unwrap(), Op::Add as u8); + assert_eq!(chunk.code[idx], Op::Add as u8); } #[test] - fn extend_empty() { + fn push_op_with_arg() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, dummy_span()); + let mut idx = chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(42); - let other = Chunk::default(); - chunk.extend(other); + assert_eq!(chunk.code[idx], Op::Constant as u8); - assert_eq!( - chunk.code, - vec![OpCode::OpAdd], - "code should not have changed" - ); + idx += 1; + let (arg, size) = chunk.read_uvarint(idx); + assert_eq!(idx + size, chunk.code.len()); + assert_eq!(arg, 42); } #[test] - fn extend_simple() { - let span = dummy_span(); + fn push_jump() { let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, span); - let mut other = Chunk::default(); - other.push_op(OpCode::OpSub, span); - other.push_op(OpCode::OpMul, span); + chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(0); - let expected_code = vec![OpCode::OpAdd, OpCode::OpSub, OpCode::OpMul]; + let idx = chunk.push_op(Op::Jump, dummy_span()); + chunk.push_u16(0); - chunk.extend(other); + chunk.push_op(Op::Constant, dummy_span()); + chunk.push_uvarint(1); - assert_eq!(chunk.code, expected_code, "code should have been extended"); - } + chunk.patch_jump(idx); + chunk.push_op(Op::Return, dummy_span()); - #[test] - fn extend_with_constant() { - let span = dummy_span(); - let mut chunk = Chunk::default(); - chunk.push_op(OpCode::OpAdd, span); - let cidx = chunk.push_constant(Value::Integer(0)); - assert_eq!( - cidx.0, 0, - "first constant in main chunk should have index 0" - ); - chunk.push_op(OpCode::OpConstant(cidx), span); - - let mut other = Chunk::default(); - other.push_op(OpCode::OpSub, span); - let other_cidx = other.push_constant(Value::Integer(1)); - assert_eq!( - other_cidx.0, 0, - "first constant in other chunk should have index 0" - ); - other.push_op(OpCode::OpConstant(other_cidx), span); - - chunk.extend(other); - - let expected_code = vec![ - OpCode::OpAdd, - OpCode::OpConstant(ConstantIdx(0)), - OpCode::OpSub, - OpCode::OpConstant(ConstantIdx(1)), // <- note: this was rewritten + #[rustfmt::skip] + let expected: Vec<u8> = vec![ + Op::Constant as u8, 0, + Op::Jump as u8, 2, 0, + Op::Constant as u8, 1, + Op::Return as u8, ]; - assert_eq!( - chunk.code, expected_code, - "code should have been extended and rewritten" - ); - - assert_eq!(chunk.constants.len(), 2); - assert!(matches!(chunk.constants[0], Value::Integer(0))); - assert!(matches!(chunk.constants[1], Value::Integer(1))); + assert_eq!(chunk.code, expected); } } diff --git a/tvix/eval/src/compiler/bindings.rs b/tvix/eval/src/compiler/bindings.rs index f5c6376eb1b3..6a3ae485936c 100644 --- a/tvix/eval/src/compiler/bindings.rs +++ b/tvix/eval/src/compiler/bindings.rs @@ -605,7 +605,7 @@ impl Compiler<'_, '_> { c.emit_force(&namespace); c.emit_constant(name.as_str().into(), &span); - c.push_op(OpCode::OpAttrsSelect, &span); + c.push_op(Op::AttrsSelect, &span); }) } @@ -632,7 +632,8 @@ impl Compiler<'_, '_> { if self.scope()[idx].needs_finaliser { let stack_idx = self.scope().stack_index(idx); let span = self.scope()[idx].span; - self.push_op(OpCode::OpFinalise(stack_idx), &OrEntireFile(span)); + self.push_op(Op::Finalise, &OrEntireFile(span)); + self.push_uvarint(stack_idx.0 as u64) } } } @@ -667,11 +668,8 @@ impl Compiler<'_, '_> { self.bind_values(bindings); if kind.is_attrs() { - self.push_op(OpCode::OpAttrs(Count(count)), node); - } - - if count == 0 { - self.unthunk(); + self.push_op(Op::Attrs, node); + self.push_uvarint(count as u64); } } @@ -697,7 +695,7 @@ impl Compiler<'_, '_> { self.scope_mut().end_scope(); self.emit_constant("body".into(), node); - self.push_op(OpCode::OpAttrsSelect, node); + self.push_op(Op::AttrsSelect, node); } /// Is the given identifier defined *by the user* in any current scope? @@ -718,8 +716,9 @@ impl Compiler<'_, '_> { match self.scope_mut().resolve_local(ident) { LocalPosition::Unknown => { // Are we possibly dealing with an upvalue? - if let Some(idx) = self.resolve_upvalue(self.contexts.len() - 1, ident, node) { - self.push_op(OpCode::OpGetUpvalue(idx), node); + if let Some(idx) = self.resolve_upvalue(self.contexts.len() - 1, ident) { + self.push_op(Op::GetUpvalue, node); + self.push_uvarint(idx.0 as u64); return; } @@ -742,7 +741,7 @@ impl Compiler<'_, '_> { self.thunk(slot, node, |c, _| { c.context_mut().captures_with_stack = true; c.emit_constant(ident.into(), node); - c.push_op(OpCode::OpResolveWith, node); + c.push_op(Op::ResolveWith, node); }); return; } @@ -753,18 +752,17 @@ impl Compiler<'_, '_> { LocalPosition::Known(idx) => { let stack_idx = self.scope().stack_index(idx); - self.push_op(OpCode::OpGetLocal(stack_idx), node); + self.push_op(Op::GetLocal, node); + self.push_uvarint(stack_idx.0 as u64); } // This identifier is referring to a value from the same scope which // is not yet defined. This identifier access must be thunked. LocalPosition::Recursive(idx) => self.thunk(slot, node, move |compiler, _| { - let upvalue_idx = compiler.add_upvalue( - compiler.contexts.len() - 1, - node, - UpvalueKind::Local(idx), - ); - compiler.push_op(OpCode::OpGetUpvalue(upvalue_idx), node); + let upvalue_idx = + compiler.add_upvalue(compiler.contexts.len() - 1, UpvalueKind::Local(idx)); + compiler.push_op(Op::GetUpvalue, node); + compiler.push_uvarint(upvalue_idx.0 as u64); }), }; } @@ -777,12 +775,7 @@ impl Compiler<'_, '_> { /// Private compiler helpers related to bindings. impl Compiler<'_, '_> { - fn resolve_upvalue<N: ToSpan>( - &mut self, - ctx_idx: usize, - name: &str, - node: &N, - ) -> Option<UpvalueIdx> { + fn resolve_upvalue(&mut self, ctx_idx: usize, name: &str) -> Option<UpvalueIdx> { if ctx_idx == 0 { // There can not be any upvalue at the outermost context. return None; @@ -795,7 +788,7 @@ impl Compiler<'_, '_> { // stack (i.e. in the right position) *during* their runtime // construction LocalPosition::Known(idx) | LocalPosition::Recursive(idx) => { - return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Local(idx))) + return Some(self.add_upvalue(ctx_idx, UpvalueKind::Local(idx))) } LocalPosition::Unknown => { /* continue below */ } @@ -803,19 +796,14 @@ impl Compiler<'_, '_> { // If the upvalue comes from even further up, we need to recurse to make // sure that the upvalues are created at each level. - if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name, node) { - return Some(self.add_upvalue(ctx_idx, node, UpvalueKind::Upvalue(idx))); + if let Some(idx) = self.resolve_upvalue(ctx_idx - 1, name) { + return Some(self.add_upvalue(ctx_idx, UpvalueKind::Upvalue(idx))); } None } - fn add_upvalue<N: ToSpan>( - &mut self, - ctx_idx: usize, - node: &N, - kind: UpvalueKind, - ) -> UpvalueIdx { + fn add_upvalue(&mut self, ctx_idx: usize, kind: UpvalueKind) -> UpvalueIdx { // If there is already an upvalue closing over the specified index, // retrieve that instead. for (idx, existing) in self.contexts[ctx_idx].scope.upvalues.iter().enumerate() { @@ -824,11 +812,7 @@ impl Compiler<'_, '_> { } } - let span = self.span_for(node); - self.contexts[ctx_idx] - .scope - .upvalues - .push(Upvalue { kind, span }); + self.contexts[ctx_idx].scope.upvalues.push(Upvalue { kind }); let idx = UpvalueIdx(self.contexts[ctx_idx].lambda.upvalue_count); self.contexts[ctx_idx].lambda.upvalue_count += 1; diff --git a/tvix/eval/src/compiler/mod.rs b/tvix/eval/src/compiler/mod.rs index 4878db1f1a84..33b70b87ce84 100644 --- a/tvix/eval/src/compiler/mod.rs +++ b/tvix/eval/src/compiler/mod.rs @@ -29,7 +29,7 @@ use std::rc::{Rc, Weak}; use crate::chunk::Chunk; use crate::errors::{CatchableErrorKind, Error, ErrorKind, EvalResult}; use crate::observer::CompilerObserver; -use crate::opcode::{CodeIdx, ConstantIdx, Count, JumpOffset, OpCode, UpvalueIdx}; +use crate::opcode::{CodeIdx, Op, Position, UpvalueIdx}; use crate::spans::ToSpan; use crate::value::{Closure, Formals, Lambda, NixAttrs, Thunk, Value}; use crate::warnings::{EvalWarning, WarningKind}; @@ -52,7 +52,6 @@ struct LambdaCtx { lambda: Lambda, scope: Scope, captures_with_stack: bool, - unthunk: bool, } impl LambdaCtx { @@ -61,7 +60,6 @@ impl LambdaCtx { lambda: Lambda::default(), scope: Default::default(), captures_with_stack: false, - unthunk: false, } } @@ -70,7 +68,6 @@ impl LambdaCtx { lambda: Lambda::default(), scope: self.scope.inherit(), captures_with_stack: false, - unthunk: false, } } } @@ -270,13 +267,37 @@ impl Compiler<'_, '_> { /// Push a single instruction to the current bytecode chunk and /// track the source span from which it was compiled. - fn push_op<T: ToSpan>(&mut self, data: OpCode, node: &T) -> CodeIdx { + fn push_op<T: ToSpan>(&mut self, data: Op, node: &T) -> CodeIdx { if self.dead_scope > 0 { return CodeIdx(0); } let span = self.span_for(node); - self.chunk().push_op(data, span) + CodeIdx(self.chunk().push_op(data, span)) + } + + fn push_u8(&mut self, data: u8) { + if self.dead_scope > 0 { + return; + } + + self.chunk().code.push(data); + } + + fn push_uvarint(&mut self, data: u64) { + if self.dead_scope > 0 { + return; + } + + self.chunk().push_uvarint(data); + } + + fn push_u16(&mut self, data: u16) { + if self.dead_scope > 0 { + return; + } + + self.chunk().push_u16(data); } /// Emit a single constant to the current bytecode chunk and track @@ -287,7 +308,8 @@ impl Compiler<'_, '_> { } let idx = self.chunk().push_constant(value); - self.push_op(OpCode::OpConstant(idx), node); + self.push_op(Op::Constant, node); + self.push_uvarint(idx.0 as u64); } } @@ -400,7 +422,7 @@ impl Compiler<'_, '_> { Value::UnresolvedPath(Box::new(home_relative_path.into())), node, ); - self.push_op(OpCode::OpResolveHomePath, node); + self.push_op(Op::ResolveHomePath, node); return; } else if raw_path.starts_with('<') { // TODO: decide what to do with findFile @@ -416,7 +438,7 @@ impl Compiler<'_, '_> { // Make a thunk to resolve the path (without using `findFile`, at least for now?) return self.thunk(slot, node, move |c, _| { c.emit_constant(Value::UnresolvedPath(Box::new(path.into())), node); - c.push_op(OpCode::OpFindFile, node); + c.push_op(Op::FindFile, node); }); } else { let mut buf = self.root_dir.clone(); @@ -452,13 +474,15 @@ impl Compiler<'_, '_> { ast::InterpolPart::Interpolation(ipol) => { self.compile(slot, ipol.expr().unwrap()); // implicitly forces as well - self.push_op( - OpCode::OpCoerceToString(CoercionKind { - strong: false, - import_paths: true, - }), - ipol, - ); + self.push_op(Op::CoerceToString, ipol); + + let encoded: u8 = CoercionKind { + strong: false, + import_paths: true, + } + .into(); + + self.push_u8(encoded); } ast::InterpolPart::Literal(lit) => { @@ -468,7 +492,8 @@ impl Compiler<'_, '_> { } if parts.len() != 1 { - self.push_op(OpCode::OpInterpolate(Count(parts.len())), parent_node); + self.push_op(Op::Interpolate, parent_node); + self.push_uvarint(parts.len() as u64); } } @@ -494,8 +519,8 @@ impl Compiler<'_, '_> { self.emit_force(op); let opcode = match op.operator().unwrap() { - ast::UnaryOpKind::Invert => OpCode::OpInvert, - ast::UnaryOpKind::Negate => OpCode::OpNegate, + ast::UnaryOpKind::Invert => Op::Invert, + ast::UnaryOpKind::Negate => Op::Negate, }; self.push_op(opcode, op); @@ -526,21 +551,21 @@ impl Compiler<'_, '_> { self.emit_force(&op.rhs().unwrap()); match op.operator().unwrap() { - BinOpKind::Add => self.push_op(OpCode::OpAdd, op), - BinOpKind::Sub => self.push_op(OpCode::OpSub, op), - BinOpKind::Mul => self.push_op(OpCode::OpMul, op), - BinOpKind::Div => self.push_op(OpCode::OpDiv, op), - BinOpKind::Update => self.push_op(OpCode::OpAttrsUpdate, op), - BinOpKind::Equal => self.push_op(OpCode::OpEqual, op), - BinOpKind::Less => self.push_op(OpCode::OpLess, op), - BinOpKind::LessOrEq => self.push_op(OpCode::OpLessOrEq, op), - BinOpKind::More => self.push_op(OpCode::OpMore, op), - BinOpKind::MoreOrEq => self.push_op(OpCode::OpMoreOrEq, op), - BinOpKind::Concat => self.push_op(OpCode::OpConcat, op), + BinOpKind::Add => self.push_op(Op::Add, op), + BinOpKind::Sub => self.push_op(Op::Sub, op), + BinOpKind::Mul => self.push_op(Op::Mul, op), + BinOpKind::Div => self.push_op(Op::Div, op), + BinOpKind::Update => self.push_op(Op::AttrsUpdate, op), + BinOpKind::Equal => self.push_op(Op::Equal, op), + BinOpKind::Less => self.push_op(Op::Less, op), + BinOpKind::LessOrEq => self.push_op(Op::LessOrEq, op), + BinOpKind::More => self.push_op(Op::More, op), + BinOpKind::MoreOrEq => self.push_op(Op::MoreOrEq, op), + BinOpKind::Concat => self.push_op(Op::Concat, op), BinOpKind::NotEqual => { - self.push_op(OpCode::OpEqual, op); - self.push_op(OpCode::OpInvert, op) + self.push_op(Op::Equal, op); + self.push_op(Op::Invert, op) } // Handled by separate branch above. @@ -561,20 +586,22 @@ impl Compiler<'_, '_> { self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); // If this value is false, jump over the right-hand side - the // whole expression is false. - let end_idx = self.push_op(OpCode::OpJumpIfFalse(JumpOffset(0)), node); + let end_idx = self.push_op(Op::JumpIfFalse, node); + self.push_u16(0); // Otherwise, remove the previous value and leave the // right-hand side on the stack. Its result is now the value // of the whole expression. - self.push_op(OpCode::OpPop, node); + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -589,16 +616,18 @@ impl Compiler<'_, '_> { self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); // Opposite of above: If this value is **true**, we can // short-circuit the right-hand side. - let end_idx = self.push_op(OpCode::OpJumpIfTrue(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let end_idx = self.push_op(Op::JumpIfTrue, node); + self.push_u16(0); + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -612,17 +641,20 @@ impl Compiler<'_, '_> { // Leave left-hand side value on the stack and invert it. self.compile(slot, node.lhs().unwrap()); self.emit_force(&node.lhs().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); - self.push_op(OpCode::OpInvert, node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); + self.push_op(Op::Invert, node); // Exactly as `||` (because `a -> b` = `!a || b`). - let end_idx = self.push_op(OpCode::OpJumpIfTrue(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let end_idx = self.push_op(Op::JumpIfTrue, node); + self.push_u16(0); + + self.push_op(Op::Pop, node); self.compile(slot, node.rhs().unwrap()); self.emit_force(&node.rhs().unwrap()); self.patch_jump(end_idx); - self.push_op(OpCode::OpAssertBool, node); + self.push_op(Op::AssertBool, node); self.patch_jump(throw_idx); } @@ -657,11 +689,8 @@ impl Compiler<'_, '_> { self.scope_mut().mark_initialised(item_slot); } - if count == 0 { - self.unthunk(); - } - - self.push_op(OpCode::OpList(Count(count)), node); + self.push_op(Op::List, node); + self.push_uvarint(count as u64); self.scope_mut().end_scope(); } @@ -690,7 +719,7 @@ impl Compiler<'_, '_> { // next nested element, for all fragments except the last one. for (count, fragment) in node.attrpath().unwrap().attrs().enumerate() { if count > 0 { - self.push_op(OpCode::OpAttrsTrySelect, &fragment); + self.push_op(Op::AttrsTrySelect, &fragment); self.emit_force(&fragment); } @@ -699,7 +728,7 @@ impl Compiler<'_, '_> { // After the last fragment, emit the actual instruction that // leaves a boolean on the stack. - self.push_op(OpCode::OpHasAttr, node); + self.push_op(Op::HasAttr, node); } /// When compiling select or select_or expressions, an optimisation is @@ -723,8 +752,9 @@ impl Compiler<'_, '_> { // set that is lacking a key, because that thunk is never // evaluated). If anything is missing, just move on. We may // want to emit warnings here in the future. - if let Some(OpCode::OpConstant(ConstantIdx(idx))) = self.chunk().code.last().cloned() { - let constant = &mut self.chunk().constants[idx]; + if let Some((Op::Constant, op_idx)) = self.chunk().last_op() { + let (idx, _) = self.chunk().read_uvarint(op_idx + 1); + let constant = &mut self.chunk().constants[idx as usize]; if let Value::Attrs(attrs) = constant { let mut path_iter = path.attrs(); @@ -736,10 +766,6 @@ impl Compiler<'_, '_> { if let Some(ident) = expr_static_attr_str(&attr) { if let Some(selected_value) = attrs.select(ident.as_bytes()) { *constant = selected_value.clone(); - - // If this worked, we can unthunk the current thunk. - self.unthunk(); - return true; } } @@ -773,7 +799,7 @@ impl Compiler<'_, '_> { self.emit_force(&set); self.compile_attr(slot, &fragment); - self.push_op(OpCode::OpAttrsSelect, &fragment); + self.push_op(Op::AttrsSelect, &fragment); } } @@ -823,11 +849,13 @@ impl Compiler<'_, '_> { for fragment in path.attrs() { self.emit_force(&fragment); self.compile_attr(slot, &fragment.clone()); - self.push_op(OpCode::OpAttrsTrySelect, &fragment); - jumps.push(self.push_op(OpCode::OpJumpIfNotFound(JumpOffset(0)), &fragment)); + self.push_op(Op::AttrsTrySelect, &fragment); + jumps.push(self.push_op(Op::JumpIfNotFound, &fragment)); + self.push_u16(0); } - let final_jump = self.push_op(OpCode::OpJump(JumpOffset(0)), &path); + let final_jump = self.push_op(Op::Jump, &path); + self.push_u16(0); for jump in jumps { self.patch_jump(jump); @@ -855,17 +883,22 @@ impl Compiler<'_, '_> { // Compile the assertion condition to leave its value on the stack. self.compile(slot, node.condition().unwrap()); self.emit_force(&node.condition().unwrap()); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), node); - let then_idx = self.push_op(OpCode::OpJumpIfFalse(JumpOffset(0)), node); - self.push_op(OpCode::OpPop, node); + let throw_idx = self.push_op(Op::JumpIfCatchable, node); + self.push_u16(0); + + let then_idx = self.push_op(Op::JumpIfFalse, node); + self.push_u16(0); + + self.push_op(Op::Pop, node); self.compile(slot, node.body().unwrap()); - let else_idx = self.push_op(OpCode::OpJump(JumpOffset(0)), node); + let else_idx = self.push_op(Op::Jump, node); + self.push_u16(0); self.patch_jump(then_idx); - self.push_op(OpCode::OpPop, node); - self.push_op(OpCode::OpAssertFail, &node.condition().unwrap()); + self.push_op(Op::Pop, node); + self.push_op(Op::AssertFail, &node.condition().unwrap()); self.patch_jump(else_idx); self.patch_jump(throw_idx); @@ -887,22 +920,20 @@ impl Compiler<'_, '_> { self.compile(slot, node.condition().unwrap()); self.emit_force(&node.condition().unwrap()); - let throw_idx = self.push_op( - OpCode::OpJumpIfCatchable(JumpOffset(0)), - &node.condition().unwrap(), - ); - let then_idx = self.push_op( - OpCode::OpJumpIfFalse(JumpOffset(0)), - &node.condition().unwrap(), - ); + let throw_idx = self.push_op(Op::JumpIfCatchable, &node.condition().unwrap()); + self.push_u16(0); + + let then_idx = self.push_op(Op::JumpIfFalse, &node.condition().unwrap()); + self.push_u16(0); - self.push_op(OpCode::OpPop, node); // discard condition value + self.push_op(Op::Pop, node); // discard condition value self.compile(slot, node.body().unwrap()); - let else_idx = self.push_op(OpCode::OpJump(JumpOffset(0)), node); + let else_idx = self.push_op(Op::Jump, node); + self.push_u16(0); self.patch_jump(then_idx); // patch jump *to* else_body - self.push_op(OpCode::OpPop, node); // discard condition value + self.push_op(Op::Pop, node); // discard condition value self.compile(slot, node.else_body().unwrap()); self.patch_jump(else_idx); // patch jump *over* else body @@ -931,11 +962,12 @@ impl Compiler<'_, '_> { self.scope_mut().push_with(); - self.push_op(OpCode::OpPushWith(with_idx), &node.namespace().unwrap()); + self.push_op(Op::PushWith, &node.namespace().unwrap()); + self.push_uvarint(with_idx.0 as u64); self.compile(slot, node.body().unwrap()); - self.push_op(OpCode::OpPopWith, node); + self.push_op(Op::PopWith, node); self.scope_mut().pop_with(); self.cleanup_scope(node); } @@ -995,13 +1027,15 @@ impl Compiler<'_, '_> { // At call time, the attribute set is already at the top of the stack. self.scope_mut().mark_initialised(set_idx); self.emit_force(pattern); - let throw_idx = self.push_op(OpCode::OpJumpIfCatchable(JumpOffset(0)), pattern); + let throw_idx = self.push_op(Op::JumpIfCatchable, pattern); + self.push_u16(0); + // Evaluation fails on a type error, even if the argument(s) are unused. - self.push_op(OpCode::OpAssertAttrs, pattern); + self.push_op(Op::AssertAttrs, pattern); let ellipsis = pattern.ellipsis_token().is_some(); if !ellipsis { - self.push_op(OpCode::OpValidateClosedFormals, pattern); + self.push_op(Op::ValidateClosedFormals, pattern); } // Similar to `let ... in ...`, we now do multiple passes over @@ -1041,7 +1075,8 @@ impl Compiler<'_, '_> { // attempt to select from it. let stack_idx = self.scope().stack_index(set_idx); for tracked_formal in entries.iter() { - self.push_op(OpCode::OpGetLocal(stack_idx), pattern); + self.push_op(Op::GetLocal, pattern); + self.push_uvarint(stack_idx.0 as u64); self.emit_literal_ident(&tracked_formal.pattern_entry().ident().unwrap()); let idx = tracked_formal.local_idx(); @@ -1070,14 +1105,14 @@ impl Compiler<'_, '_> { // we only know better after compiling the default expression, so // avoiding unnecessary locals would mean we'd need to modify the chunk // after the fact. - self.push_op(OpCode::OpAttrsTrySelect, &pattern_entry.ident().unwrap()); - let jump_to_default = - self.push_op(OpCode::OpJumpIfNotFound(JumpOffset(0)), default_expr); + self.push_op(Op::AttrsTrySelect, &pattern_entry.ident().unwrap()); + let jump_to_default = self.push_op(Op::JumpIfNotFound, default_expr); + self.push_u16(0); self.emit_constant(Value::FinaliseRequest(false), default_expr); - let jump_over_default = - self.push_op(OpCode::OpJump(JumpOffset(0)), default_expr); + let jump_over_default = self.push_op(Op::Jump, default_expr); + self.push_u16(0); self.patch_jump(jump_to_default); @@ -1089,7 +1124,7 @@ impl Compiler<'_, '_> { self.patch_jump(jump_over_default); } TrackedFormal::NoDefault { pattern_entry, .. } => { - self.push_op(OpCode::OpAttrsSelect, &pattern_entry.ident().unwrap()); + self.push_op(Op::AttrsSelect, &pattern_entry.ident().unwrap()); } } @@ -1113,23 +1148,16 @@ impl Compiler<'_, '_> { let finalise_request_stack_idx = self.scope().stack_index(*finalise_request_idx); // TODO(sterni): better spans - self.push_op( - OpCode::OpGetLocal(finalise_request_stack_idx), - pattern - ); + self.push_op(Op::GetLocal, pattern); + self.push_uvarint(finalise_request_stack_idx.0 as u64); let jump_over_finalise = - self.push_op( - OpCode::OpJumpIfNoFinaliseRequest( - JumpOffset(0)), - pattern - ); - self.push_op( - OpCode::OpFinalise(stack_idx), - pattern, - ); + self.push_op(Op::JumpIfNoFinaliseRequest, pattern); + self.push_u16(0); + self.push_op(Op::Finalise, pattern); + self.push_uvarint(stack_idx.0 as u64); self.patch_jump(jump_over_finalise); // Get rid of finaliser request value on the stack - self.push_op(OpCode::OpPop, pattern); + self.push_op(Op::Pop, pattern); } } } @@ -1188,12 +1216,6 @@ impl Compiler<'_, '_> { }) } - /// Mark the current thunk as redundant, i.e. possible to merge directly - /// into its parent lambda context without affecting runtime behaviour. - fn unthunk(&mut self) { - self.context_mut().unthunk = true; - } - /// Compile an expression into a runtime closure or thunk fn compile_lambda_or_thunk<N, F>( &mut self, @@ -1222,31 +1244,15 @@ impl Compiler<'_, '_> { self.patch_jump(throw_idx); } - // TODO: determine and insert enclosing name, if available. - // Pop the lambda context back off, and emit the finished // lambda as a constant. let mut compiled = self.contexts.pop().unwrap(); - // The compiler might have decided to unthunk, i.e. raise the compiled - // code to the parent context. In that case we do so and return right - // away. - if compiled.unthunk && is_suspended_thunk { - self.chunk().extend(compiled.lambda.chunk); - return; - } - // Emit an instruction to inform the VM that the chunk has ended. compiled .lambda .chunk - .push_op(OpCode::OpReturn, self.span_for(node)); - - // Capturing the with stack counts as an upvalue, as it is - // emitted as an upvalue data instruction. - if compiled.captures_with_stack { - compiled.lambda.upvalue_count += 1; - } + .push_op(Op::Return, self.span_for(node)); let lambda = Rc::new(compiled.lambda); if is_suspended_thunk { @@ -1256,7 +1262,7 @@ impl Compiler<'_, '_> { } // If no upvalues are captured, emit directly and move on. - if lambda.upvalue_count == 0 { + if lambda.upvalue_count == 0 && !compiled.captures_with_stack { self.emit_constant( if is_suspended_thunk { Value::Thunk(Thunk::new_suspended(lambda, span)) @@ -1276,12 +1282,13 @@ impl Compiler<'_, '_> { let code_idx = self.push_op( if is_suspended_thunk { - OpCode::OpThunkSuspended(blueprint_idx) + Op::ThunkSuspended } else { - OpCode::OpThunkClosure(blueprint_idx) + Op::ThunkClosure }, node, ); + self.push_uvarint(blueprint_idx.0 as u64); self.emit_upvalue_data( outer_slot, @@ -1292,18 +1299,21 @@ impl Compiler<'_, '_> { if !is_suspended_thunk && !self.scope()[outer_slot].needs_finaliser { if !self.scope()[outer_slot].must_thunk { - // The closure has upvalues, but is not recursive. Therefore no thunk is required, - // which saves us the overhead of Rc<RefCell<>> - self.chunk()[code_idx] = OpCode::OpClosure(blueprint_idx); + // The closure has upvalues, but is not recursive. Therefore no + // thunk is required, which saves us the overhead of + // Rc<RefCell<>> + self.chunk().code[code_idx.0] = Op::Closure as u8; } else { - // This case occurs when a closure has upvalue-references to itself but does not need a - // finaliser. Since no OpFinalise will be emitted later on we synthesize one here. - // It is needed here only to set [`Closure::is_finalised`] which is used for sanity checks. + // This case occurs when a closure has upvalue-references to + // itself but does not need a finaliser. Since no OpFinalise + // will be emitted later on we synthesize one here. It is needed + // here only to set [`Closure::is_finalised`] which is used for + // sanity checks. #[cfg(debug_assertions)] - self.push_op( - OpCode::OpFinalise(self.scope().stack_index(outer_slot)), - &self.span_for(node), - ); + { + self.push_op(Op::Finalise, &self.span_for(node)); + self.push_uvarint(self.scope().stack_index(outer_slot).0 as u64); + } } } } @@ -1316,7 +1326,7 @@ impl Compiler<'_, '_> { self.compile(slot, node.argument().unwrap()); self.compile(slot, node.lambda().unwrap()); self.emit_force(&node.lambda().unwrap()); - self.push_op(OpCode::OpCall, node); + self.push_op(Op::Call, node); } /// Emit the data instructions that the runtime needs to correctly @@ -1324,10 +1334,18 @@ impl Compiler<'_, '_> { fn emit_upvalue_data<T: ToSpan>( &mut self, slot: LocalIdx, - node: &T, + _: &T, // TODO upvalues: Vec<Upvalue>, capture_with: bool, ) { + // Push the count of arguments to be expected, with one bit set to + // indicate whether the with stack needs to be captured. + let mut count = (upvalues.len() as u64) << 1; + if capture_with { + count |= 1; + } + self.push_uvarint(count); + for upvalue in upvalues { match upvalue.kind { UpvalueKind::Local(idx) => { @@ -1337,27 +1355,22 @@ impl Compiler<'_, '_> { // If the target is not yet initialised, we need to defer // the local access if !target.initialised { - self.push_op(OpCode::DataDeferredLocal(stack_idx), &upvalue.span); + self.push_uvarint(Position::deferred_local(stack_idx).0); self.scope_mut().mark_needs_finaliser(slot); } else { // a self-reference if slot == idx { self.scope_mut().mark_must_thunk(slot); } - self.push_op(OpCode::DataStackIdx(stack_idx), &upvalue.span); + self.push_uvarint(Position::stack_index(stack_idx).0); } } UpvalueKind::Upvalue(idx) => { - self.push_op(OpCode::DataUpvalueIdx(idx), &upvalue.span); + self.push_uvarint(Position::upvalue_index(idx).0); } }; } - - if capture_with { - // TODO(tazjin): probably better to emit span for the ident that caused this - self.push_op(OpCode::DataCaptureWith, node); - } } /// Emit the literal string value of an identifier. Required for @@ -1374,20 +1387,7 @@ impl Compiler<'_, '_> { /// not known at the time when the jump operation itself is /// emitted. fn patch_jump(&mut self, idx: CodeIdx) { - let offset = JumpOffset(self.chunk().code.len() - 1 - idx.0); - - match &mut self.chunk().code[idx.0] { - OpCode::OpJump(n) - | OpCode::OpJumpIfFalse(n) - | OpCode::OpJumpIfTrue(n) - | OpCode::OpJumpIfCatchable(n) - | OpCode::OpJumpIfNotFound(n) - | OpCode::OpJumpIfNoFinaliseRequest(n) => { - *n = offset; - } - - op => panic!("attempted to patch unsupported op: {:?}", op), - } + self.chunk().patch_jump(idx.0); } /// Decrease scope depth of the current function and emit @@ -1403,7 +1403,8 @@ impl Compiler<'_, '_> { } if popcount > 0 { - self.push_op(OpCode::OpCloseScope(Count(popcount)), node); + self.push_op(Op::CloseScope, node); + self.push_uvarint(popcount as u64); } } @@ -1461,16 +1462,7 @@ impl Compiler<'_, '_> { } fn emit_force<N: ToSpan>(&mut self, node: &N) { - if let Some(&OpCode::OpConstant(c)) = self.chunk().last_op() { - if !self.chunk().get_constant(c).unwrap().is_thunk() { - // Optimization: Don't emit a force op for non-thunk constants, since they don't - // need one! - // TODO: this is probably doable for more ops (?) - return; - } - } - - self.push_op(OpCode::OpForce, node); + self.push_op(Op::Force, node); } fn emit_warning<N: ToSpan>(&mut self, node: &N, kind: WarningKind) { @@ -1673,10 +1665,11 @@ pub fn compile( c.emit_force(expr); if let Some(env) = env { if !env.is_empty() { - c.push_op(OpCode::OpCloseScope(Count(env.len())), &root_span); + c.push_op(Op::CloseScope, &root_span); + c.push_uvarint(env.len() as u64); } } - c.push_op(OpCode::OpReturn, &root_span); + c.push_op(Op::Return, &root_span); let lambda = Rc::new(c.contexts.pop().unwrap().lambda); c.observer.observe_compiled_toplevel(&lambda); diff --git a/tvix/eval/src/compiler/scope.rs b/tvix/eval/src/compiler/scope.rs index 1087e0153e42..bb1784e67b74 100644 --- a/tvix/eval/src/compiler/scope.rs +++ b/tvix/eval/src/compiler/scope.rs @@ -105,7 +105,6 @@ pub enum UpvalueKind { #[derive(Clone, Debug)] pub struct Upvalue { pub kind: UpvalueKind, - pub span: codemap::Span, } /// The index of a local in the scope's local array at compile time. diff --git a/tvix/eval/src/observer.rs b/tvix/eval/src/observer.rs index f5de399315c7..5e6526418b3b 100644 --- a/tvix/eval/src/observer.rs +++ b/tvix/eval/src/observer.rs @@ -13,7 +13,7 @@ use tabwriter::TabWriter; use crate::chunk::Chunk; use crate::generators::VMRequest; -use crate::opcode::{CodeIdx, OpCode}; +use crate::opcode::{CodeIdx, Op}; use crate::value::Lambda; use crate::SourceCode; use crate::Value; @@ -73,7 +73,7 @@ pub trait RuntimeObserver { /// Called when the runtime *begins* executing an instruction. The /// provided stack is the state at the beginning of the operation. - fn observe_execute_op(&mut self, _ip: CodeIdx, _: &OpCode, _: &[Value]) {} + fn observe_execute_op(&mut self, _ip: CodeIdx, _: &Op, _: &[Value]) {} } #[derive(Default)] @@ -112,8 +112,12 @@ impl<W: Write> DisassemblingObserver<W> { // calculate width of the widest address in the chunk let width = format!("{:#x}", chunk.code.len() - 1).len(); - for (idx, _) in chunk.code.iter().enumerate() { - let _ = chunk.disassemble_op(&mut self.writer, &self.source, width, CodeIdx(idx)); + let mut idx = 0; + while idx < chunk.code.len() { + let size = chunk + .disassemble_op(&mut self.writer, &self.source, width, CodeIdx(idx)) + .expect("writing debug output should work"); + idx += size; } } } @@ -304,7 +308,7 @@ impl<W: Write> RuntimeObserver for TracingObserver<W> { ); } - fn observe_execute_op(&mut self, ip: CodeIdx, op: &OpCode, stack: &[Value]) { + fn observe_execute_op(&mut self, ip: CodeIdx, op: &Op, stack: &[Value]) { self.maybe_write_time(); let _ = write!(&mut self.writer, "{:04} {:?}\t", ip.0, op); self.write_stack(stack); diff --git a/tvix/eval/src/opcode.rs b/tvix/eval/src/opcode.rs index f89c1c12e7fd..ddf1304b3aea 100644 --- a/tvix/eval/src/opcode.rs +++ b/tvix/eval/src/opcode.rs @@ -52,8 +52,7 @@ pub struct JumpOffset(pub usize); #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Count(pub usize); -/// All variants of this enum carry a bounded amount of data to -/// ensure that no heap allocations are needed for an Opcode. +/// Op represents all instructions in the Tvix abstract machine. /// /// In documentation comments, stack positions are referred to by /// indices written in `{}` as such, where required: @@ -70,187 +69,182 @@ pub struct Count(pub usize); /// /// Unless otherwise specified, operations leave their result at the /// top of the stack. -#[warn(variant_size_differences)] -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum OpCode { +#[repr(u8)] +#[derive(Debug, PartialEq, Eq)] +pub enum Op { /// Push a constant onto the stack. - OpConstant(ConstantIdx), + Constant, - // Unary operators - /// Discard a value from the stack. - OpPop, + /// Discard the value on top of the stack. + Pop, /// Invert the boolean at the top of the stack. - OpInvert, + Invert, - // Binary operators /// Invert the sign of the number at the top of the stack. - OpNegate, + Negate, /// Sum up the two numbers at the top of the stack. - OpAdd, + Add, /// Subtract the number at {1} from the number at {2}. - OpSub, + Sub, /// Multiply the two numbers at the top of the stack. - OpMul, + Mul, /// Divide the two numbers at the top of the stack. - OpDiv, + Div, - // Comparison operators /// Check the two values at the top of the stack for Nix-equality. - OpEqual, + Equal, /// Check whether the value at {2} is less than {1}. - OpLess, + Less, /// Check whether the value at {2} is less than or equal to {1}. - OpLessOrEq, + LessOrEq, /// Check whether the value at {2} is greater than {1}. - OpMore, + More, /// Check whether the value at {2} is greater than or equal to {1}. - OpMoreOrEq, + MoreOrEq, - // Logical operators & generic jumps /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand. - OpJump(JumpOffset), + Jump, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is `true`. - OpJumpIfTrue(JumpOffset), + JumpIfTrue, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is `false`. - OpJumpIfFalse(JumpOffset), + JumpIfFalse, /// Pop one stack item and jump forward in the bytecode /// specified by the number of instructions in its usize /// operand, *if* the value at the top of the stack is a /// Value::Catchable. - OpJumpIfCatchable(JumpOffset), + JumpIfCatchable, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is the internal value representing a missing /// attribute set key. - OpJumpIfNotFound(JumpOffset), + JumpIfNotFound, /// Jump forward in the bytecode specified by the number of /// instructions in its usize operand, *if* the value at the top /// of the stack is *not* the internal value requesting a /// stack value finalisation. - OpJumpIfNoFinaliseRequest(JumpOffset), + JumpIfNoFinaliseRequest, + + /// Construct an attribute set from the given number of key-value pairs on + /// the top of the stack. The operand gives the count of *pairs*, not the + /// number of *stack values* - the actual number of values popped off the + /// stack will be twice the argument to this op. + Attrs, - // Attribute sets - /// Construct an attribute set from the given number of key-value pairs on the top of the stack - /// - /// Note that this takes the count of *pairs*, not the number of *stack values* - the actual - /// number of values popped off the stack will be twice the argument to this op - OpAttrs(Count), /// Merge the attribute set at {2} into the attribute set at {1}, /// and leave the new set at the top of the stack. - OpAttrsUpdate, + AttrsUpdate, /// Select the attribute with the name at {1} from the set at {2}. - OpAttrsSelect, + AttrsSelect, /// Select the attribute with the name at {1} from the set at {2}, but leave /// a `Value::AttrNotFound` in the stack instead of failing if it is /// missing. - OpAttrsTrySelect, + AttrsTrySelect, /// Check for the presence of the attribute with the name at {1} in the set /// at {2}. - OpHasAttr, + HasAttr, /// Throw an error if the attribute set at the top of the stack has any attributes /// other than those listed in the formals of the current lambda /// /// Panics if the current frame is not a lambda with formals - OpValidateClosedFormals, + ValidateClosedFormals, - // `with`-handling /// Push a value onto the runtime `with`-stack to enable dynamic identifier /// resolution. The absolute stack index of the value is supplied as a usize /// operand. - OpPushWith(StackIdx), + PushWith, /// Pop the last runtime `with`-stack element. - OpPopWith, + PopWith, /// Dynamically resolve an identifier with the name at {1} from the runtime /// `with`-stack. - OpResolveWith, + ResolveWith, // Lists /// Construct a list from the given number of values at the top of the /// stack. - OpList(Count), + List, /// Concatenate the lists at {2} and {1}. - OpConcat, + Concat, // Strings /// Interpolate the given number of string fragments into a single string. - OpInterpolate(Count), + Interpolate, /// Force the Value on the stack and coerce it to a string - OpCoerceToString(crate::CoercionKind), + CoerceToString, // Paths /// Attempt to resolve the Value on the stack using the configured [`NixSearchPath`][] /// /// [`NixSearchPath`]: crate::nix_search_path::NixSearchPath - OpFindFile, + FindFile, /// Attempt to resolve a path literal relative to the home dir - OpResolveHomePath, + ResolveHomePath, // Type assertion operators /// Assert that the value at {1} is a boolean, and fail with a runtime error /// otherwise. - OpAssertBool, - OpAssertAttrs, + AssertBool, + AssertAttrs, /// Access local identifiers with statically known positions. - OpGetLocal(StackIdx), + GetLocal, /// Close scopes while leaving their expression value around. - OpCloseScope(Count), // number of locals to pop + CloseScope, /// Return an error indicating that an `assert` failed - OpAssertFail, + AssertFail, // Lambdas & closures /// Call the value at {1} in a new VM callframe - OpCall, + Call, /// Retrieve the upvalue at the given index from the closure or thunk /// currently under evaluation. - OpGetUpvalue(UpvalueIdx), + GetUpvalue, /// Construct a closure which has upvalues but no self-references - OpClosure(ConstantIdx), + Closure, /// Construct a closure which has self-references (direct or via upvalues) - OpThunkClosure(ConstantIdx), + ThunkClosure, /// Construct a suspended thunk, used to delay a computation for laziness. - OpThunkSuspended(ConstantIdx), + ThunkSuspended, /// Force the value at {1} until it is a `Thunk::Evaluated`. - OpForce, + Force, /// Finalise initialisation of the upvalues of the value in the given stack /// index (which must be a Value::Thunk) after the scope is fully bound. - OpFinalise(StackIdx), + Finalise, /// Final instruction emitted in a chunk. Does not have an /// inherent effect, but can simplify VM logic as a marker in some @@ -258,27 +252,140 @@ pub enum OpCode { /// /// Can be thought of as "returning" the value to the parent /// frame, hence the name. - OpReturn, - - // [`OpClosure`], [`OpThunkSuspended`], and [`OpThunkClosure`] have a - // variable number of arguments to the instruction, which is - // represented here by making their data part of the opcodes. - // Each of these two opcodes has a `ConstantIdx`, which must - // reference a `Value::Blueprint(Lambda)`. The `upvalue_count` - // field in that `Lambda` indicates the number of arguments it - // takes, and the opcode must be followed by exactly this number - // of `Data*` opcodes. The VM skips over these by advancing the - // instruction pointer. - // - // It is illegal for a `Data*` opcode to appear anywhere else. - /// Populate a static upvalue by copying from the stack immediately. - DataStackIdx(StackIdx), - /// Populate a static upvalue of a thunk by copying it the stack, but do - /// when the thunk is finalised (by OpFinalise) rather than immediately. - DataDeferredLocal(StackIdx), - /// Populate a static upvalue by copying it from the upvalues of an - /// enclosing scope. - DataUpvalueIdx(UpvalueIdx), - /// Populate dynamic upvalues by saving a copy of the with-stack. - DataCaptureWith, + Return, + + /// Sentinel value to signal invalid bytecode. This MUST always be the last + /// value in the enum. Do not move it! + Invalid, +} + +const _ASSERT_SMALL_OP: () = assert!(std::mem::size_of::<Op>() == 1); + +impl From<u8> for Op { + fn from(num: u8) -> Self { + if num >= Self::Invalid as u8 { + return Self::Invalid; + } + + // SAFETY: As long as `Invalid` remains the last variant of the enum, + // and as long as variant values are not specified manually, this + // conversion is safe. + unsafe { std::mem::transmute(num) } + } +} + +pub enum OpArg { + None, + Uvarint, + Fixed, + Custom, +} + +impl Op { + pub fn arg_type(&self) -> OpArg { + match self { + Op::Constant + | Op::Attrs + | Op::PushWith + | Op::List + | Op::Interpolate + | Op::GetLocal + | Op::CloseScope + | Op::GetUpvalue + | Op::Finalise => OpArg::Uvarint, + + Op::Jump + | Op::JumpIfTrue + | Op::JumpIfFalse + | Op::JumpIfCatchable + | Op::JumpIfNotFound + | Op::JumpIfNoFinaliseRequest => OpArg::Fixed, + + Op::CoerceToString | Op::Closure | Op::ThunkClosure | Op::ThunkSuspended => { + OpArg::Custom + } + _ => OpArg::None, + } + } +} + +/// Position is used to represent where to capture an upvalue from. +#[derive(Clone, Copy)] +pub struct Position(pub u64); + +impl Position { + pub fn stack_index(idx: StackIdx) -> Self { + Position((idx.0 as u64) << 2) + } + + pub fn deferred_local(idx: StackIdx) -> Self { + Position(((idx.0 as u64) << 2) | 1) + } + + pub fn upvalue_index(idx: UpvalueIdx) -> Self { + Position(((idx.0 as u64) << 2) | 2) + } + + pub fn runtime_stack_index(&self) -> Option<StackIdx> { + if (self.0 & 0b11) == 0 { + return Some(StackIdx((self.0 >> 2) as usize)); + } + + None + } + + pub fn runtime_deferred_local(&self) -> Option<StackIdx> { + if (self.0 & 0b11) == 1 { + return Some(StackIdx((self.0 >> 2) as usize)); + } + + None + } + + pub fn runtime_upvalue_index(&self) -> Option<UpvalueIdx> { + if (self.0 & 0b11) == 2 { + return Some(UpvalueIdx((self.0 >> 2) as usize)); + } + + None + } +} + +#[cfg(test)] +mod position_tests { + use super::Position; // he-he + use super::{StackIdx, UpvalueIdx}; + + #[test] + fn test_stack_index_position() { + let idx = StackIdx(42); + let pos = Position::stack_index(idx); + let result = pos.runtime_stack_index(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_deferred_local(), None); + assert_eq!(pos.runtime_upvalue_index(), None); + } + + #[test] + fn test_deferred_local_position() { + let idx = StackIdx(42); + let pos = Position::deferred_local(idx); + let result = pos.runtime_deferred_local(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_stack_index(), None); + assert_eq!(pos.runtime_upvalue_index(), None); + } + + #[test] + fn test_upvalue_index_position() { + let idx = UpvalueIdx(42); + let pos = Position::upvalue_index(idx); + let result = pos.runtime_upvalue_index(); + + assert_eq!(result, Some(idx)); + assert_eq!(pos.runtime_stack_index(), None); + assert_eq!(pos.runtime_deferred_local(), None); + } } diff --git a/tvix/eval/src/value/arbitrary.rs b/tvix/eval/src/value/arbitrary.rs index bf53f4fcb28a..49b9f2eea3fb 100644 --- a/tvix/eval/src/value/arbitrary.rs +++ b/tvix/eval/src/value/arbitrary.rs @@ -1,6 +1,6 @@ //! Support for configurable generation of arbitrary nix values -use imbl::proptest::{ord_map, vector}; +use proptest::collection::{btree_map, vec}; use proptest::{prelude::*, strategy::BoxedStrategy}; use std::ffi::OsString; @@ -33,16 +33,16 @@ impl Arbitrary for NixAttrs { fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { prop_oneof![ // Empty attrs representation - Just(Self(AttrsRep::Empty)), + Just(AttrsRep::Empty.into()), // KV representation (name/value pairs) ( any_with::<Value>(args.clone()), any_with::<Value>(args.clone()) ) - .prop_map(|(name, value)| Self(AttrsRep::KV { name, value })), + .prop_map(|(name, value)| AttrsRep::KV { name, value }.into()), // Map representation - ord_map(NixString::arbitrary(), Value::arbitrary_with(args), 0..100) - .prop_map(|map| Self(AttrsRep::Im(map))) + btree_map(NixString::arbitrary(), Value::arbitrary_with(args), 0..100) + .prop_map(|map| AttrsRep::Map(map).into()) ] .boxed() } @@ -53,7 +53,7 @@ impl Arbitrary for NixList { type Strategy = BoxedStrategy<Self>; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { - vector(<Value as Arbitrary>::arbitrary_with(args), 0..100) + vec(<Value as Arbitrary>::arbitrary_with(args), 0..100) .prop_map(NixList::from) .boxed() } diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index 33259c8058eb..00b913347418 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -6,10 +6,11 @@ //! Due to this, construction and management of attribute sets has //! some peculiarities that are encapsulated within this module. use std::borrow::Borrow; +use std::collections::{btree_map, BTreeMap}; use std::iter::FromIterator; +use std::rc::Rc; use bstr::BStr; -use imbl::{ordmap, OrdMap}; use lazy_static::lazy_static; use serde::de::{Deserializer, Error, Visitor}; use serde::Deserialize; @@ -36,7 +37,7 @@ pub(super) enum AttrsRep { #[default] Empty, - Im(OrdMap<NixString, Value>), + Map(BTreeMap<NixString, Value>), /// Warning: this represents a **two**-attribute attrset, with /// attribute names "name" and "value", like `{name="foo"; @@ -48,28 +49,6 @@ pub(super) enum AttrsRep { } impl AttrsRep { - /// Retrieve reference to a mutable map inside of an attrs, - /// optionally changing the representation if required. - fn map_mut(&mut self) -> &mut OrdMap<NixString, Value> { - match self { - AttrsRep::Im(m) => m, - - AttrsRep::Empty => { - *self = AttrsRep::Im(OrdMap::new()); - self.map_mut() - } - - AttrsRep::KV { name, value } => { - *self = AttrsRep::Im(ordmap! { - NAME_S.clone() => name.clone(), - VALUE_S.clone() => value.clone() - }); - - self.map_mut() - } - } - } - fn select(&self, key: &BStr) -> Option<&Value> { match self { AttrsRep::Empty => None, @@ -80,7 +59,7 @@ impl AttrsRep { _ => None, }, - AttrsRep::Im(map) => map.get(key), + AttrsRep::Map(map) => map.get(key), } } @@ -88,18 +67,18 @@ impl AttrsRep { match self { AttrsRep::Empty => false, AttrsRep::KV { .. } => key == "name" || key == "value", - AttrsRep::Im(map) => map.contains_key(key), + AttrsRep::Map(map) => map.contains_key(key), } } } #[repr(transparent)] #[derive(Clone, Debug, Default)] -pub struct NixAttrs(pub(super) AttrsRep); +pub struct NixAttrs(pub(super) Rc<AttrsRep>); -impl From<OrdMap<NixString, Value>> for NixAttrs { - fn from(map: OrdMap<NixString, Value>) -> Self { - NixAttrs(AttrsRep::Im(map)) +impl From<AttrsRep> for NixAttrs { + fn from(rep: AttrsRep) -> Self { + NixAttrs(Rc::new(rep)) } } @@ -112,34 +91,41 @@ where where T: IntoIterator<Item = (K, V)>, { - NixAttrs(AttrsRep::Im(iter.into_iter().collect())) + AttrsRep::Map( + iter.into_iter() + .map(|(k, v)| (k.into(), v.into())) + .collect(), + ) + .into() + } +} + +impl From<BTreeMap<NixString, Value>> for NixAttrs { + fn from(map: BTreeMap<NixString, Value>) -> Self { + AttrsRep::Map(map).into() } } impl TotalDisplay for NixAttrs { fn total_fmt(&self, f: &mut std::fmt::Formatter<'_>, set: &mut ThunkSet) -> std::fmt::Result { - f.write_str("{ ")?; - - match &self.0 { - AttrsRep::KV { name, value } => { - f.write_str("name = ")?; - name.total_fmt(f, set)?; - f.write_str("; ")?; - - f.write_str("value = ")?; - value.total_fmt(f, set)?; - f.write_str("; ")?; - } - - AttrsRep::Im(map) => { - for (name, value) in map { - write!(f, "{} = ", name.ident_str())?; - value.total_fmt(f, set)?; - f.write_str("; ")?; + if let Some(Value::String(s)) = self.select("type") { + if *s == "derivation" { + write!(f, "«derivation ")?; + if let Some(p) = self.select("drvPath") { + p.total_fmt(f, set)?; + } else { + write!(f, "???")?; } + return write!(f, "»"); } + } + + f.write_str("{ ")?; - AttrsRep::Empty => { /* no values to print! */ } + for (name, value) in self.iter_sorted() { + write!(f, "{} = ", name.ident_str())?; + value.total_fmt(f, set)?; + f.write_str("; ")?; } f.write_str("}") @@ -183,25 +169,22 @@ impl<'de> Deserialize<'de> for NixAttrs { impl NixAttrs { pub fn empty() -> Self { - Self(AttrsRep::Empty) + AttrsRep::Empty.into() } /// Compare two attribute sets by pointer equality. Only makes - /// sense for some attribute set reprsentations, i.e. returning + /// sense for some attribute set representations, i.e. returning /// `false` does not mean that the two attribute sets do not have /// equal *content*. pub fn ptr_eq(&self, other: &Self) -> bool { - match (&self.0, &other.0) { - (AttrsRep::Im(lhs), AttrsRep::Im(rhs)) => lhs.ptr_eq(rhs), - _ => false, - } + Rc::ptr_eq(&self.0, &other.0) } /// Return an attribute set containing the merge of the two /// provided sets. Keys from the `other` set have precedence. pub fn update(self, other: Self) -> Self { // Short-circuit on some optimal cases: - match (&self.0, &other.0) { + match (self.0.as_ref(), other.0.as_ref()) { (AttrsRep::Empty, AttrsRep::Empty) => return self, (AttrsRep::Empty, _) => return other, (_, AttrsRep::Empty) => return self, @@ -210,41 +193,44 @@ impl NixAttrs { // Explicitly handle all branches instead of falling // through, to ensure that we get at least some compiler // errors if variants are modified. - (AttrsRep::Im(_), AttrsRep::Im(_)) - | (AttrsRep::Im(_), AttrsRep::KV { .. }) - | (AttrsRep::KV { .. }, AttrsRep::Im(_)) => {} + (AttrsRep::Map(_), AttrsRep::Map(_)) + | (AttrsRep::Map(_), AttrsRep::KV { .. }) + | (AttrsRep::KV { .. }, AttrsRep::Map(_)) => {} }; // Slightly more advanced, but still optimised updates - match (self.0, other.0) { - (AttrsRep::Im(mut m), AttrsRep::KV { name, value }) => { + match (Rc::unwrap_or_clone(self.0), Rc::unwrap_or_clone(other.0)) { + (AttrsRep::Map(mut m), AttrsRep::KV { name, value }) => { m.insert(NAME_S.clone(), name); m.insert(VALUE_S.clone(), value); - NixAttrs(AttrsRep::Im(m)) + AttrsRep::Map(m).into() } - (AttrsRep::KV { name, value }, AttrsRep::Im(mut m)) => { + (AttrsRep::KV { name, value }, AttrsRep::Map(mut m)) => { match m.entry(NAME_S.clone()) { - imbl::ordmap::Entry::Vacant(e) => { + btree_map::Entry::Vacant(e) => { e.insert(name); } - imbl::ordmap::Entry::Occupied(_) => { /* name from `m` has precedence */ } + btree_map::Entry::Occupied(_) => { /* name from `m` has precedence */ } }; match m.entry(VALUE_S.clone()) { - imbl::ordmap::Entry::Vacant(e) => { + btree_map::Entry::Vacant(e) => { e.insert(value); } - imbl::ordmap::Entry::Occupied(_) => { /* value from `m` has precedence */ } + btree_map::Entry::Occupied(_) => { /* value from `m` has precedence */ } }; - NixAttrs(AttrsRep::Im(m)) + AttrsRep::Map(m).into() } // Plain merge of maps. - (AttrsRep::Im(m1), AttrsRep::Im(m2)) => NixAttrs(AttrsRep::Im(m2.union(m1))), + (AttrsRep::Map(mut m1), AttrsRep::Map(m2)) => { + m1.extend(m2); + AttrsRep::Map(m1).into() + } // Cases handled above by the borrowing match: _ => unreachable!(), @@ -253,16 +239,16 @@ impl NixAttrs { /// Return the number of key-value entries in an attrset. pub fn len(&self) -> usize { - match &self.0 { - AttrsRep::Im(map) => map.len(), + match self.0.as_ref() { + AttrsRep::Map(map) => map.len(), AttrsRep::Empty => 0, AttrsRep::KV { .. } => 2, } } pub fn is_empty(&self) -> bool { - match &self.0 { - AttrsRep::Im(map) => map.is_empty(), + match self.0.as_ref() { + AttrsRep::Map(map) => map.is_empty(), AttrsRep::Empty => true, AttrsRep::KV { .. } => false, } @@ -298,8 +284,8 @@ impl NixAttrs { /// Construct an iterator over all the key-value pairs in the attribute set. #[allow(clippy::needless_lifetimes)] pub fn iter<'a>(&'a self) -> Iter<KeyValue<'a>> { - Iter(match &self.0 { - AttrsRep::Im(map) => KeyValue::Im(map.iter()), + Iter(match &self.0.as_ref() { + AttrsRep::Map(map) => KeyValue::Map(map.iter()), AttrsRep::Empty => KeyValue::Empty, AttrsRep::KV { @@ -327,10 +313,12 @@ impl NixAttrs { /// Construct an iterator over all the keys of the attribute set pub fn keys(&self) -> Keys { - Keys(match &self.0 { + Keys(match self.0.as_ref() { AttrsRep::Empty => KeysInner::Empty, - AttrsRep::Im(m) => KeysInner::Im(m.keys()), AttrsRep::KV { .. } => KeysInner::KV(IterKV::default()), + + // TODO(tazjin): only sort when required, not always. + AttrsRep::Map(m) => KeysInner::Map(m.keys()), }) } @@ -349,7 +337,7 @@ impl NixAttrs { // Optimisation: Empty attribute set if count == 0 { - return Ok(Ok(NixAttrs(AttrsRep::Empty))); + return Ok(Ok(AttrsRep::Empty.into())); } // Optimisation: KV pattern @@ -359,14 +347,14 @@ impl NixAttrs { } } - let mut attrs = NixAttrs(AttrsRep::Im(OrdMap::new())); + let mut attrs_map = BTreeMap::new(); for _ in 0..count { let value = stack_slice.pop().unwrap(); let key = stack_slice.pop().unwrap(); match key { - Value::String(ks) => set_attr(&mut attrs, ks, value)?, + Value::String(ks) => set_attr(&mut attrs_map, ks, value)?, Value::Null => { // This is in fact valid, but leads to the value @@ -381,13 +369,13 @@ impl NixAttrs { } } - Ok(Ok(attrs)) + Ok(Ok(AttrsRep::Map(attrs_map).into())) } /// Construct an optimized "KV"-style attribute set given the value for the /// `"name"` key, and the value for the `"value"` key pub(crate) fn from_kv(name: Value, value: Value) -> Self { - NixAttrs(AttrsRep::KV { name, value }) + AttrsRep::KV { name, value }.into() } } @@ -396,12 +384,12 @@ impl IntoIterator for NixAttrs { type IntoIter = OwnedAttrsIterator; fn into_iter(self) -> Self::IntoIter { - match self.0 { + match Rc::unwrap_or_clone(self.0) { AttrsRep::Empty => OwnedAttrsIterator(IntoIterRepr::Empty), AttrsRep::KV { name, value } => OwnedAttrsIterator(IntoIterRepr::Finite( vec![(NAME_REF.clone(), name), (VALUE_REF.clone(), value)].into_iter(), )), - AttrsRep::Im(map) => OwnedAttrsIterator(IntoIterRepr::Im(map.into_iter())), + AttrsRep::Map(map) => OwnedAttrsIterator(IntoIterRepr::Map(map.into_iter())), } } } @@ -440,13 +428,17 @@ fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> { /// Set an attribute on an in-construction attribute set, while /// checking against duplicate keys. -fn set_attr(attrs: &mut NixAttrs, key: NixString, value: Value) -> Result<(), ErrorKind> { - match attrs.0.map_mut().entry(key) { - imbl::ordmap::Entry::Occupied(entry) => Err(ErrorKind::DuplicateAttrsKey { +fn set_attr( + map: &mut BTreeMap<NixString, Value>, + key: NixString, + value: Value, +) -> Result<(), ErrorKind> { + match map.entry(key) { + btree_map::Entry::Occupied(entry) => Err(ErrorKind::DuplicateAttrsKey { key: entry.key().to_string(), }), - imbl::ordmap::Entry::Vacant(entry) => { + btree_map::Entry::Vacant(entry) => { entry.insert(value); Ok(()) } @@ -484,7 +476,7 @@ pub enum KeyValue<'a> { at: IterKV, }, - Im(imbl::ordmap::Iter<'a, NixString, Value>), + Map(btree_map::Iter<'a, NixString, Value>), } /// Iterator over a Nix attribute set. @@ -498,7 +490,7 @@ impl<'a> Iterator for Iter<KeyValue<'a>> { fn next(&mut self) -> Option<Self::Item> { match &mut self.0 { - KeyValue::Im(inner) => inner.next(), + KeyValue::Map(inner) => inner.next(), KeyValue::Empty => None, KeyValue::KV { name, value, at } => match at { @@ -523,7 +515,7 @@ impl<'a> ExactSizeIterator for Iter<KeyValue<'a>> { match &self.0 { KeyValue::Empty => 0, KeyValue::KV { .. } => 2, - KeyValue::Im(inner) => inner.len(), + KeyValue::Map(inner) => inner.len(), } } } @@ -531,7 +523,7 @@ impl<'a> ExactSizeIterator for Iter<KeyValue<'a>> { enum KeysInner<'a> { Empty, KV(IterKV), - Im(imbl::ordmap::Keys<'a, NixString, Value>), + Map(btree_map::Keys<'a, NixString, Value>), } pub struct Keys<'a>(KeysInner<'a>); @@ -551,7 +543,7 @@ impl<'a> Iterator for Keys<'a> { Some(&VALUE_REF) } KeysInner::KV(IterKV::Done) => None, - KeysInner::Im(m) => m.next(), + KeysInner::Map(m) => m.next(), } } } @@ -571,7 +563,7 @@ impl<'a> ExactSizeIterator for Keys<'a> { match &self.0 { KeysInner::Empty => 0, KeysInner::KV(_) => 2, - KeysInner::Im(m) => m.len(), + KeysInner::Map(m) => m.len(), } } } @@ -580,7 +572,7 @@ impl<'a> ExactSizeIterator for Keys<'a> { pub enum IntoIterRepr { Empty, Finite(std::vec::IntoIter<(NixString, Value)>), - Im(imbl::ordmap::ConsumingIter<(NixString, Value)>), + Map(btree_map::IntoIter<NixString, Value>), } /// Wrapper type which hides the internal implementation details from @@ -595,7 +587,7 @@ impl Iterator for OwnedAttrsIterator { match &mut self.0 { IntoIterRepr::Empty => None, IntoIterRepr::Finite(inner) => inner.next(), - IntoIterRepr::Im(inner) => inner.next(), + IntoIterRepr::Map(m) => m.next(), } } } @@ -605,7 +597,7 @@ impl ExactSizeIterator for OwnedAttrsIterator { match &self.0 { IntoIterRepr::Empty => 0, IntoIterRepr::Finite(inner) => inner.len(), - IntoIterRepr::Im(inner) => inner.len(), + IntoIterRepr::Map(inner) => inner.len(), } } } @@ -615,7 +607,7 @@ impl DoubleEndedIterator for OwnedAttrsIterator { match &mut self.0 { IntoIterRepr::Empty => None, IntoIterRepr::Finite(inner) => inner.next_back(), - IntoIterRepr::Im(inner) => inner.next_back(), + IntoIterRepr::Map(inner) => inner.next_back(), } } } diff --git a/tvix/eval/src/value/attrs/tests.rs b/tvix/eval/src/value/attrs/tests.rs index 534b78a00d10..b79f45a71b28 100644 --- a/tvix/eval/src/value/attrs/tests.rs +++ b/tvix/eval/src/value/attrs/tests.rs @@ -9,7 +9,7 @@ fn test_empty_attrs() { .unwrap(); assert!( - matches!(attrs, NixAttrs(AttrsRep::Empty)), + matches!(attrs.0.as_ref(), AttrsRep::Empty), "empty attribute set should use optimised representation" ); } @@ -21,7 +21,7 @@ fn test_simple_attrs() { .unwrap(); assert!( - matches!(attrs, NixAttrs(AttrsRep::Im(_))), + matches!(attrs.0.as_ref(), AttrsRep::Map(_)), "simple attribute set should use map representation", ) } @@ -45,8 +45,8 @@ fn test_kv_attrs() { .expect("constructing K/V pair attrs should succeed") .unwrap(); - match kv_attrs { - NixAttrs(AttrsRep::KV { name, value }) + match kv_attrs.0.as_ref() { + AttrsRep::KV { name, value } if name.to_str().unwrap() == meaning_val.to_str().unwrap() || value.to_str().unwrap() == forty_two_val.to_str().unwrap() => {} diff --git a/tvix/eval/src/value/list.rs b/tvix/eval/src/value/list.rs index 2b8b3de28d19..3e4b23a93f42 100644 --- a/tvix/eval/src/value/list.rs +++ b/tvix/eval/src/value/list.rs @@ -2,8 +2,6 @@ use std::ops::Index; use std::rc::Rc; -use imbl::{vector, Vector}; - use serde::Deserialize; use super::thunk::ThunkSet; @@ -12,7 +10,7 @@ use super::Value; #[repr(transparent)] #[derive(Clone, Debug, Deserialize)] -pub struct NixList(Rc<Vector<Value>>); +pub struct NixList(Rc<Vec<Value>>); impl TotalDisplay for NixList { fn total_fmt(&self, f: &mut std::fmt::Formatter<'_>, set: &mut ThunkSet) -> std::fmt::Result { @@ -27,8 +25,8 @@ impl TotalDisplay for NixList { } } -impl From<Vector<Value>> for NixList { - fn from(vs: Vector<Value>) -> Self { +impl From<Vec<Value>> for NixList { + fn from(vs: Vec<Value>) -> Self { Self(Rc::new(vs)) } } @@ -54,10 +52,10 @@ impl NixList { stack_slice.len(), ); - NixList(Rc::new(Vector::from_iter(stack_slice))) + NixList(Rc::new(stack_slice)) } - pub fn iter(&self) -> vector::Iter<Value> { + pub fn iter(&self) -> std::slice::Iter<Value> { self.0.iter() } @@ -65,19 +63,14 @@ impl NixList { Rc::ptr_eq(&self.0, &other.0) } - pub fn into_inner(self) -> Vector<Value> { + pub fn into_inner(self) -> Vec<Value> { Rc::try_unwrap(self.0).unwrap_or_else(|rc| (*rc).clone()) } - - #[deprecated(note = "callers should avoid constructing from Vec")] - pub fn from_vec(vs: Vec<Value>) -> Self { - Self(Rc::new(Vector::from_iter(vs))) - } } impl IntoIterator for NixList { type Item = Value; - type IntoIter = imbl::vector::ConsumingIter<Value>; + type IntoIter = std::vec::IntoIter<Value>; fn into_iter(self) -> Self::IntoIter { self.into_inner().into_iter() @@ -86,7 +79,7 @@ impl IntoIterator for NixList { impl<'a> IntoIterator for &'a NixList { type Item = &'a Value; - type IntoIter = imbl::vector::Iter<'a, Value>; + type IntoIter = std::slice::Iter<'a, Value>; fn into_iter(self) -> Self::IntoIter { self.0.iter() diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index a5bc17c15294..2e78f20b49a0 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -84,7 +84,6 @@ pub enum Value { FinaliseRequest(bool), #[serde(skip)] - // TODO(tazjin): why is this in a Box? Catchable(Box<CatchableErrorKind>), } @@ -187,6 +186,21 @@ pub struct CoercionKind { pub import_paths: bool, } +impl From<CoercionKind> for u8 { + fn from(k: CoercionKind) -> u8 { + k.strong as u8 | (k.import_paths as u8) << 1 + } +} + +impl From<u8> for CoercionKind { + fn from(byte: u8) -> Self { + CoercionKind { + strong: byte & 0x01 != 0, + import_paths: byte & 0x02 != 0, + } + } +} + impl<T> From<T> for Value where T: Into<NixString>, @@ -196,14 +210,6 @@ where } } -/// Constructors -impl Value { - /// Construct a [`Value::Attrs`] from a [`NixAttrs`]. - pub fn attrs(attrs: NixAttrs) -> Self { - Self::Attrs(Box::new(attrs)) - } -} - /// Controls what kind of by-pointer equality comparison is allowed. /// /// See `//tvix/docs/value-pointer-equality.md` for details. @@ -220,6 +226,11 @@ pub enum PointerEquality { } impl Value { + /// Construct a [`Value::Attrs`] from a [`NixAttrs`]. + pub fn attrs(attrs: NixAttrs) -> Self { + Self::Attrs(Box::new(attrs)) + } + /// Deeply forces a value, traversing e.g. lists and attribute sets and forcing /// their contents, too. /// @@ -877,6 +888,12 @@ impl Value { | Value::FinaliseRequest(_) => "an internal Tvix evaluator value".into(), } } + + /// Constructs a thunk that will be evaluated lazily at runtime. This lets + /// users of Tvix implement their own lazy builtins and so on. + pub fn suspended_native_thunk(native: Box<dyn Fn() -> Result<Value, ErrorKind>>) -> Self { + Value::Thunk(Thunk::new_suspended_native(native)) + } } trait TotalDisplay { diff --git a/tvix/eval/src/value/string/context.rs b/tvix/eval/src/value/string/context.rs new file mode 100644 index 000000000000..e1c04735ddde --- /dev/null +++ b/tvix/eval/src/value/string/context.rs @@ -0,0 +1,161 @@ +use rustc_hash::FxHashSet; +use serde::Serialize; + +use super::NixString; + +#[derive(Clone, Debug, Serialize, Hash, PartialEq, Eq)] +pub enum NixContextElement { + /// A plain store path (e.g. source files copied to the store) + Plain(String), + + /// Single output of a derivation, represented by its name and its derivation path. + Single { name: String, derivation: String }, + + /// A reference to a complete derivation + /// including its source and its binary closure. + /// It is used for the `drvPath` attribute context. + /// The referred string is the store path to + /// the derivation path. + Derivation(String), +} + +/// Nix context strings representation in Tvix. This tracks a set of different kinds of string +/// dependencies that we can come across during manipulation of our language primitives, mostly +/// strings. There's some simple algebra of context strings and how they propagate w.r.t. primitive +/// operations, e.g. concatenation, interpolation and other string operations. +#[repr(transparent)] +#[derive(Clone, Debug, Serialize, Default)] +pub struct NixContext(FxHashSet<NixContextElement>); + +impl From<NixContextElement> for NixContext { + fn from(value: NixContextElement) -> Self { + let mut set = FxHashSet::default(); + set.insert(value); + Self(set) + } +} + +impl From<FxHashSet<NixContextElement>> for NixContext { + fn from(value: FxHashSet<NixContextElement>) -> Self { + Self(value) + } +} + +impl<const N: usize> From<[NixContextElement; N]> for NixContext { + fn from(value: [NixContextElement; N]) -> Self { + let mut set = FxHashSet::default(); + for elt in value { + set.insert(elt); + } + Self(set) + } +} + +impl NixContext { + /// Creates an empty context that can be populated + /// and passed to form a contextful [NixString], albeit + /// if the context is concretly empty, the resulting [NixString] + /// will be contextless. + pub fn new() -> Self { + Self::default() + } + + /// For internal consumers, we let people observe + /// if the [NixContext] is actually empty or not + /// to decide whether they want to skip the allocation + /// of a full blown [HashSet]. + pub(crate) fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Consumes a new [NixContextElement] and add it if not already + /// present in this context. + pub fn append(mut self, other: NixContextElement) -> Self { + self.0.insert(other); + self + } + + /// Extends the existing context with more context elements. + pub fn extend<T>(&mut self, iter: T) + where + T: IntoIterator<Item = NixContextElement>, + { + self.0.extend(iter) + } + + /// Copies from another [NixString] its context strings + /// in this context. + pub fn mimic(&mut self, other: &NixString) { + if let Some(context) = other.context() { + self.extend(context.iter().cloned()); + } + } + + /// Iterates over "plain" context elements, e.g. sources imported + /// in the store without more information, i.e. `toFile` or coerced imported paths. + /// It yields paths to the store. + pub fn iter_plain(&self) -> impl Iterator<Item = &str> { + self.iter().filter_map(|elt| { + if let NixContextElement::Plain(s) = elt { + Some(s.as_str()) + } else { + None + } + }) + } + + /// Iterates over "full derivations" context elements, e.g. something + /// referring to their `drvPath`, i.e. their full sources and binary closure. + /// It yields derivation paths. + pub fn iter_derivation(&self) -> impl Iterator<Item = &str> { + self.iter().filter_map(|elt| { + if let NixContextElement::Derivation(s) = elt { + Some(s.as_str()) + } else { + None + } + }) + } + + /// Iterates over "single" context elements, e.g. single derived paths, + /// or also known as the single output of a given derivation. + /// The first element of the tuple is the output name + /// and the second element is the derivation path. + pub fn iter_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { + self.iter().filter_map(|elt| { + if let NixContextElement::Single { name, derivation } = elt { + Some((name.as_str(), derivation.as_str())) + } else { + None + } + }) + } + + /// Iterates over any element of the context. + pub fn iter(&self) -> impl Iterator<Item = &NixContextElement> { + self.0.iter() + } + + /// Produces a list of owned references to this current context, + /// no matter its type. + pub fn to_owned_references(self) -> Vec<String> { + self.0 + .into_iter() + .map(|ctx| match ctx { + NixContextElement::Derivation(drv_path) => drv_path, + NixContextElement::Plain(store_path) => store_path, + NixContextElement::Single { derivation, .. } => derivation, + }) + .collect() + } +} + +impl IntoIterator for NixContext { + type Item = NixContextElement; + + type IntoIter = std::collections::hash_set::IntoIter<NixContextElement>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} diff --git a/tvix/eval/src/value/string.rs b/tvix/eval/src/value/string/mod.rs index 0365f5a9be77..5bcb4786b283 100644 --- a/tvix/eval/src/value/string.rs +++ b/tvix/eval/src/value/string/mod.rs @@ -1,181 +1,30 @@ //! This module implements Nix language strings. //! -//! Nix language strings never need to be modified on the language -//! level, allowing us to shave off some memory overhead and only -//! paying the cost when creating new strings. +//! See [`NixString`] for more information about the internals of string values + use bstr::{BStr, BString, ByteSlice, Chars}; +use nohash_hasher::BuildNoHashHasher; use rnix::ast; -use rustc_hash::{FxHashMap, FxHashSet}; +#[cfg(feature = "no_leak")] +use rustc_hash::FxHashSet; +use rustc_hash::FxHasher; use std::alloc::dealloc; use std::alloc::{alloc, handle_alloc_error, Layout}; use std::borrow::{Borrow, Cow}; use std::cell::RefCell; use std::ffi::c_void; use std::fmt::{self, Debug, Display}; -use std::hash::Hash; +use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::ptr::{self, NonNull}; -use std::{mem, slice}; +use std::slice; use serde::de::{Deserializer, Visitor}; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Debug, Serialize, Hash, PartialEq, Eq)] -pub enum NixContextElement { - /// A plain store path (e.g. source files copied to the store) - Plain(String), - - /// Single output of a derivation, represented by its name and its derivation path. - Single { name: String, derivation: String }, - - /// A reference to a complete derivation - /// including its source and its binary closure. - /// It is used for the `drvPath` attribute context. - /// The referred string is the store path to - /// the derivation path. - Derivation(String), -} - -/// Nix context strings representation in Tvix. This tracks a set of different kinds of string -/// dependencies that we can come across during manipulation of our language primitives, mostly -/// strings. There's some simple algebra of context strings and how they propagate w.r.t. primitive -/// operations, e.g. concatenation, interpolation and other string operations. -#[repr(transparent)] -#[derive(Clone, Debug, Serialize, Default)] -pub struct NixContext(FxHashSet<NixContextElement>); - -impl From<NixContextElement> for NixContext { - fn from(value: NixContextElement) -> Self { - let mut set = FxHashSet::default(); - set.insert(value); - Self(set) - } -} - -impl From<FxHashSet<NixContextElement>> for NixContext { - fn from(value: FxHashSet<NixContextElement>) -> Self { - Self(value) - } -} - -impl<const N: usize> From<[NixContextElement; N]> for NixContext { - fn from(value: [NixContextElement; N]) -> Self { - let mut set = FxHashSet::default(); - for elt in value { - set.insert(elt); - } - Self(set) - } -} - -impl NixContext { - /// Creates an empty context that can be populated - /// and passed to form a contextful [NixString], albeit - /// if the context is concretly empty, the resulting [NixString] - /// will be contextless. - pub fn new() -> Self { - Self::default() - } +use serde::Deserialize; - /// For internal consumers, we let people observe - /// if the [NixContext] is actually empty or not - /// to decide whether they want to skip the allocation - /// of a full blown [HashSet]. - pub(crate) fn is_empty(&self) -> bool { - self.0.is_empty() - } +mod context; - /// Consumes a new [NixContextElement] and add it if not already - /// present in this context. - pub fn append(mut self, other: NixContextElement) -> Self { - self.0.insert(other); - self - } - - /// Extends the existing context with more context elements. - pub fn extend<T>(&mut self, iter: T) - where - T: IntoIterator<Item = NixContextElement>, - { - self.0.extend(iter) - } - - /// Copies from another [NixString] its context strings - /// in this context. - pub fn mimic(&mut self, other: &NixString) { - if let Some(context) = other.context() { - self.extend(context.iter().cloned()); - } - } - - /// Iterates over "plain" context elements, e.g. sources imported - /// in the store without more information, i.e. `toFile` or coerced imported paths. - /// It yields paths to the store. - pub fn iter_plain(&self) -> impl Iterator<Item = &str> { - self.iter().filter_map(|elt| { - if let NixContextElement::Plain(s) = elt { - Some(s.as_str()) - } else { - None - } - }) - } - - /// Iterates over "full derivations" context elements, e.g. something - /// referring to their `drvPath`, i.e. their full sources and binary closure. - /// It yields derivation paths. - pub fn iter_derivation(&self) -> impl Iterator<Item = &str> { - self.iter().filter_map(|elt| { - if let NixContextElement::Derivation(s) = elt { - Some(s.as_str()) - } else { - None - } - }) - } - - /// Iterates over "single" context elements, e.g. single derived paths, - /// or also known as the single output of a given derivation. - /// The first element of the tuple is the output name - /// and the second element is the derivation path. - pub fn iter_single_outputs(&self) -> impl Iterator<Item = (&str, &str)> { - self.iter().filter_map(|elt| { - if let NixContextElement::Single { name, derivation } = elt { - Some((name.as_str(), derivation.as_str())) - } else { - None - } - }) - } - - /// Iterates over any element of the context. - pub fn iter(&self) -> impl Iterator<Item = &NixContextElement> { - self.0.iter() - } - - /// Produces a list of owned references to this current context, - /// no matter its type. - pub fn to_owned_references(self) -> Vec<String> { - self.0 - .into_iter() - .map(|ctx| match ctx { - NixContextElement::Derivation(drv_path) => drv_path, - NixContextElement::Plain(store_path) => store_path, - NixContextElement::Single { derivation, .. } => derivation, - }) - .collect() - } -} - -impl IntoIterator for NixContext { - type Item = NixContextElement; - - type IntoIter = std::collections::hash_set::IntoIter<NixContextElement>; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} +pub use context::{NixContext, NixContextElement}; /// This type is never instantiated, but serves to document the memory layout of the actual heap /// allocation for Nix strings. @@ -399,22 +248,33 @@ impl NixStringInner { #[derive(Default)] struct InternerInner { - map: FxHashMap<&'static [u8], NonNull<c_void>>, + #[allow(clippy::disallowed_types)] // Not using the default hasher + map: std::collections::HashMap<u64, NonNull<c_void>, BuildNoHashHasher<u64>>, #[cfg(feature = "no_leak")] + #[allow(clippy::disallowed_types)] // Not using the default hasher interned_strings: FxHashSet<NonNull<c_void>>, } unsafe impl Send for InternerInner {} +fn hash<T>(s: T) -> u64 +where + T: Hash, +{ + let mut hasher = FxHasher::default(); + s.hash(&mut hasher); + hasher.finish() +} + impl InternerInner { pub fn intern(&mut self, s: &[u8]) -> NixString { - if let Some(s) = self.map.get(s) { + let hash = hash(s); + if let Some(s) = self.map.get(&hash) { return NixString(*s); } let string = NixString::new_inner(s, None); - self.map - .insert(unsafe { mem::transmute(string.as_bytes()) }, string.0); + self.map.insert(hash, string.0); #[cfg(feature = "no_leak")] self.interned_strings.insert(string.0); string diff --git a/tvix/eval/src/value/thunk.rs b/tvix/eval/src/value/thunk.rs index 2019e8ab3239..4b915019d47c 100644 --- a/tvix/eval/src/value/thunk.rs +++ b/tvix/eval/src/value/thunk.rs @@ -27,7 +27,7 @@ use std::{ use crate::{ errors::ErrorKind, - opcode::OpCode, + opcode::Op, upvalues::Upvalues, value::Closure, vm::generators::{self, GenCo}, @@ -170,13 +170,15 @@ impl Thunk { // This is basically a recreation of compile_apply(): // We need to push the argument onto the stack and then the function. // The function (not the argument) needs to be forced before calling. - lambda.chunk.push_op(OpCode::OpConstant(arg_idx), span); - lambda.chunk().push_op(OpCode::OpConstant(f_idx), span); - lambda.chunk.push_op(OpCode::OpForce, span); - lambda.chunk.push_op(OpCode::OpCall, span); + lambda.chunk.push_op(Op::Constant, span); + lambda.chunk.push_uvarint(arg_idx.0 as u64); + lambda.chunk.push_op(Op::Constant, span); + lambda.chunk.push_uvarint(f_idx.0 as u64); + lambda.chunk.push_op(Op::Force, span); + lambda.chunk.push_op(Op::Call, span); // Inform the VM that the chunk has ended - lambda.chunk.push_op(OpCode::OpReturn, span); + lambda.chunk.push_op(Op::Return, span); Thunk(Rc::new(RefCell::new(ThunkRepr::Suspended { upvalues: Rc::new(Upvalues::with_capacity(0)), diff --git a/tvix/eval/src/vm/mod.rs b/tvix/eval/src/vm/mod.rs index a6d0941e8d7a..49e9fc5864be 100644 --- a/tvix/eval/src/vm/mod.rs +++ b/tvix/eval/src/vm/mod.rs @@ -28,7 +28,7 @@ use crate::{ lifted_pop, nix_search_path::NixSearchPath, observer::RuntimeObserver, - opcode::{CodeIdx, Count, JumpOffset, OpCode, StackIdx, UpvalueIdx}, + opcode::{CodeIdx, Op, Position, UpvalueIdx}, upvalues::Upvalues, value::{ Builtin, BuiltinResult, Closure, CoercionKind, Lambda, NixAttrs, NixContext, NixList, @@ -146,10 +146,32 @@ impl CallFrame { /// Increment this frame's instruction pointer and return the operation that /// the pointer moved past. - fn inc_ip(&mut self) -> OpCode { - let op = self.chunk()[self.ip]; + fn inc_ip(&mut self) -> Op { + debug_assert!( + self.ip.0 < self.chunk().code.len(), + "out of bounds code at IP {} in {:p}", + self.ip.0, + self.lambda + ); + + let op = self.chunk().code[self.ip.0]; self.ip += 1; - op + op.into() + } + + /// Read a varint-encoded operand and return it. The frame pointer is + /// incremented internally. + fn read_uvarint(&mut self) -> u64 { + let (arg, size) = self.chunk().read_uvarint(self.ip.0); + self.ip += size; + arg + } + + /// Read a fixed-size u16 and increment the frame pointer. + fn read_u16(&mut self) -> u16 { + let arg = self.chunk().read_u16(self.ip.0); + self.ip += 2; + arg } /// Construct an error result from the given ErrorKind and the source span @@ -427,8 +449,8 @@ where /// stack. In this case, the frame is not returned to the frame stack. /// /// 2. The code encounters a generator, in which case the frame in its - /// current state is pushed back on the stack, and the generator is left on - /// top of it for the outer loop to execute. + /// current state is pushed back on the stack, and the generator is left + /// on top of it for the outer loop to execute. /// /// 3. An error is encountered. /// @@ -443,17 +465,25 @@ where self.observer.observe_execute_op(frame.ip, &op, &self.stack); match op { - OpCode::OpThunkSuspended(idx) | OpCode::OpThunkClosure(idx) => { - let blueprint = match &frame.chunk()[idx] { + Op::ThunkSuspended | Op::ThunkClosure => { + let idx = frame.read_uvarint() as usize; + + let blueprint = match &frame.chunk().constants[idx] { Value::Blueprint(lambda) => lambda.clone(), _ => panic!("compiler bug: non-blueprint in blueprint slot"), }; - let upvalue_count = blueprint.upvalue_count; - let thunk = if matches!(op, OpCode::OpThunkClosure(_)) { + let upvalue_count = frame.read_uvarint(); + + debug_assert!( + (upvalue_count >> 1) == blueprint.upvalue_count as u64, + "TODO: new upvalue count not correct", + ); + + let thunk = if op == Op::ThunkClosure { debug_assert!( - upvalue_count > 0, - "OpThunkClosure should not be called for plain lambdas" + (((upvalue_count >> 1) > 0) || (upvalue_count & 0b1 == 1)), + "OpThunkClosure should not be called for plain lambdas", ); Thunk::new_closure(blueprint) } else { @@ -470,7 +500,7 @@ where self.populate_upvalues(&mut frame, upvalue_count, upvalues)?; } - OpCode::OpForce => { + Op::Force => { if let Some(Value::Thunk(_)) = self.stack.last() { let thunk = match self.stack_pop() { Value::Thunk(t) => t, @@ -488,25 +518,35 @@ where } } - OpCode::OpGetUpvalue(upv_idx) => { - let value = frame.upvalue(upv_idx).clone(); + Op::GetUpvalue => { + let idx = UpvalueIdx(frame.read_uvarint() as usize); + let value = frame.upvalue(idx).clone(); self.stack.push(value); } // Discard the current frame. - OpCode::OpReturn => { + Op::Return => { // TODO(amjoseph): I think this should assert `==` rather // than `<=` but it fails with the stricter condition. debug_assert!(self.stack.len() - 1 <= frame.stack_offset); return Ok(true); } - OpCode::OpConstant(idx) => { - let c = frame.chunk()[idx].clone(); + Op::Constant => { + let idx = frame.read_uvarint() as usize; + + debug_assert!( + idx < frame.chunk().constants.len(), + "out of bounds constant at IP {} in {:p}", + frame.ip.0, + frame.lambda + ); + + let c = frame.chunk().constants[idx].clone(); self.stack.push(c); } - OpCode::OpCall => { + Op::Call => { let callable = self.stack_pop(); self.call_value(frame.current_span(), Some((span, frame)), callable)?; @@ -516,7 +556,8 @@ where // Remove the given number of elements from the stack, // but retain the top value. - OpCode::OpCloseScope(Count(count)) => { + Op::CloseScope => { + let count = frame.read_uvarint() as usize; // Immediately move the top value into the right // position. let target_idx = self.stack.len() - 1 - count; @@ -528,15 +569,22 @@ where } } - OpCode::OpClosure(idx) => { - let blueprint = match &frame.chunk()[idx] { + Op::Closure => { + let idx = frame.read_uvarint() as usize; + let blueprint = match &frame.chunk().constants[idx] { Value::Blueprint(lambda) => lambda.clone(), _ => panic!("compiler bug: non-blueprint in blueprint slot"), }; - let upvalue_count = blueprint.upvalue_count; + let upvalue_count = frame.read_uvarint(); + + debug_assert!( + (upvalue_count >> 1) == blueprint.upvalue_count as u64, + "TODO: new upvalue count not correct in closure", + ); + debug_assert!( - upvalue_count > 0, + ((upvalue_count >> 1) > 0 || (upvalue_count & 0b1 == 1)), "OpClosure should not be called for plain lambdas" ); @@ -549,7 +597,7 @@ where )))); } - OpCode::OpAttrsSelect => lifted_pop! { + Op::AttrsSelect => lifted_pop! { self(key, attrs) => { let key = key.to_str().with_span(&frame, self)?; let attrs = attrs.to_attrs().with_span(&frame, self)?; @@ -569,21 +617,24 @@ where } }, - OpCode::OpJumpIfFalse(JumpOffset(offset)) => { + Op::JumpIfFalse => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if !self.stack_peek(0).as_bool().with_span(&frame, self)? { frame.ip += offset; } } - OpCode::OpJumpIfCatchable(JumpOffset(offset)) => { + Op::JumpIfCatchable => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if self.stack_peek(0).is_catchable() { frame.ip += offset; } } - OpCode::OpJumpIfNoFinaliseRequest(JumpOffset(offset)) => { + Op::JumpIfNoFinaliseRequest => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); match self.stack_peek(0) { Value::FinaliseRequest(finalise) => { @@ -595,11 +646,11 @@ where } } - OpCode::OpPop => { + Op::Pop => { self.stack.pop(); } - OpCode::OpAttrsTrySelect => { + Op::AttrsTrySelect => { let key = self.stack_pop().to_str().with_span(&frame, self)?; let value = match self.stack_pop() { Value::Attrs(attrs) => match attrs.select(&key) { @@ -613,12 +664,14 @@ where self.stack.push(value); } - OpCode::OpGetLocal(StackIdx(local_idx)) => { + Op::GetLocal => { + let local_idx = frame.read_uvarint() as usize; let idx = frame.stack_offset + local_idx; self.stack.push(self.stack[idx].clone()); } - OpCode::OpJumpIfNotFound(JumpOffset(offset)) => { + Op::JumpIfNotFound => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if matches!(self.stack_peek(0), Value::AttrNotFound) { self.stack_pop(); @@ -626,12 +679,13 @@ where } } - OpCode::OpJump(JumpOffset(offset)) => { + Op::Jump => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); frame.ip += offset; } - OpCode::OpEqual => lifted_pop! { + Op::Equal => lifted_pop! { self(b, a) => { let gen_span = frame.current_span(); self.push_call_frame(span, frame); @@ -646,7 +700,7 @@ where // top is not of the expected type. This is necessary // to implement some specific behaviours of Nix // exactly. - OpCode::OpAssertBool => { + Op::AssertBool => { let val = self.stack_peek(0); // TODO(edef): propagate this into is_bool, since bottom values *are* values of any type if !val.is_catchable() && !val.is_bool() { @@ -660,7 +714,7 @@ where } } - OpCode::OpAssertAttrs => { + Op::AssertAttrs => { let val = self.stack_peek(0); // TODO(edef): propagate this into is_attrs, since bottom values *are* values of any type if !val.is_catchable() && !val.is_attrs() { @@ -674,9 +728,9 @@ where } } - OpCode::OpAttrs(Count(count)) => self.run_attrset(&frame, count)?, + Op::Attrs => self.run_attrset(frame.read_uvarint() as usize, &frame)?, - OpCode::OpAttrsUpdate => lifted_pop! { + Op::AttrsUpdate => lifted_pop! { self(rhs, lhs) => { let rhs = rhs.to_attrs().with_span(&frame, self)?; let lhs = lhs.to_attrs().with_span(&frame, self)?; @@ -684,28 +738,30 @@ where } }, - OpCode::OpInvert => lifted_pop! { + Op::Invert => lifted_pop! { self(v) => { let v = v.as_bool().with_span(&frame, self)?; self.stack.push(Value::Bool(!v)); } }, - OpCode::OpList(Count(count)) => { + Op::List => { + let count = frame.read_uvarint() as usize; let list = NixList::construct(count, self.stack.split_off(self.stack.len() - count)); self.stack.push(Value::List(list)); } - OpCode::OpJumpIfTrue(JumpOffset(offset)) => { + Op::JumpIfTrue => { + let offset = frame.read_u16() as usize; debug_assert!(offset != 0); if self.stack_peek(0).as_bool().with_span(&frame, self)? { frame.ip += offset; } } - OpCode::OpHasAttr => lifted_pop! { + Op::HasAttr => lifted_pop! { self(key, attrs) => { let key = key.to_str().with_span(&frame, self)?; let result = match attrs { @@ -720,15 +776,16 @@ where } }, - OpCode::OpConcat => lifted_pop! { + Op::Concat => lifted_pop! { self(rhs, lhs) => { let rhs = rhs.to_list().with_span(&frame, self)?.into_inner(); - let lhs = lhs.to_list().with_span(&frame, self)?.into_inner(); - self.stack.push(Value::List(NixList::from(lhs + rhs))) + let mut lhs = lhs.to_list().with_span(&frame, self)?.into_inner(); + lhs.extend(rhs.into_iter()); + self.stack.push(Value::List(lhs.into())) } }, - OpCode::OpResolveWith => { + Op::ResolveWith => { let ident = self.stack_pop().to_str().with_span(&frame, self)?; // Re-enqueue this frame. @@ -755,13 +812,19 @@ where return Ok(false); } - OpCode::OpFinalise(StackIdx(idx)) => match &self.stack[frame.stack_offset + idx] { - Value::Closure(_) => panic!("attempted to finalise a closure"), - Value::Thunk(thunk) => thunk.finalise(&self.stack[frame.stack_offset..]), - _ => panic!("attempted to finalise a non-thunk"), - }, + Op::Finalise => { + let idx = frame.read_uvarint() as usize; + match &self.stack[frame.stack_offset + idx] { + Value::Closure(_) => panic!("attempted to finalise a closure"), + Value::Thunk(thunk) => thunk.finalise(&self.stack[frame.stack_offset..]), + _ => panic!("attempted to finalise a non-thunk"), + } + } + + Op::CoerceToString => { + let kind: CoercionKind = frame.chunk().code[frame.ip.0].into(); + frame.ip.0 += 1; - OpCode::OpCoerceToString(kind) => { let value = self.stack_pop(); let gen_span = frame.current_span(); self.push_call_frame(span, frame); @@ -773,9 +836,9 @@ where return Ok(false); } - OpCode::OpInterpolate(Count(count)) => self.run_interpolate(&frame, count)?, + Op::Interpolate => self.run_interpolate(frame.read_uvarint(), &frame)?, - OpCode::OpValidateClosedFormals => { + Op::ValidateClosedFormals => { let formals = frame.lambda.formals.as_ref().expect( "OpValidateClosedFormals called within the frame of a lambda without formals", ); @@ -799,7 +862,7 @@ where } } - OpCode::OpAdd => lifted_pop! { + Op::Add => lifted_pop! { self(b, a) => { let gen_span = frame.current_span(); self.push_call_frame(span, frame); @@ -812,21 +875,21 @@ where } }, - OpCode::OpSub => lifted_pop! { + Op::Sub => lifted_pop! { self(b, a) => { let result = arithmetic_op!(&a, &b, -).with_span(&frame, self)?; self.stack.push(result); } }, - OpCode::OpMul => lifted_pop! { + Op::Mul => lifted_pop! { self(b, a) => { let result = arithmetic_op!(&a, &b, *).with_span(&frame, self)?; self.stack.push(result); } }, - OpCode::OpDiv => lifted_pop! { + Op::Div => lifted_pop! { self(b, a) => { match b { Value::Integer(0) => return frame.error(self, ErrorKind::DivisionByZero), @@ -841,7 +904,7 @@ where } }, - OpCode::OpNegate => match self.stack_pop() { + Op::Negate => match self.stack_pop() { Value::Integer(i) => self.stack.push(Value::Integer(-i)), Value::Float(f) => self.stack.push(Value::Float(-f)), Value::Catchable(cex) => self.stack.push(Value::Catchable(cex)), @@ -856,12 +919,12 @@ where } }, - OpCode::OpLess => cmp_op!(self, frame, span, <), - OpCode::OpLessOrEq => cmp_op!(self, frame, span, <=), - OpCode::OpMore => cmp_op!(self, frame, span, >), - OpCode::OpMoreOrEq => cmp_op!(self, frame, span, >=), + Op::Less => cmp_op!(self, frame, span, <), + Op::LessOrEq => cmp_op!(self, frame, span, <=), + Op::More => cmp_op!(self, frame, span, >), + Op::MoreOrEq => cmp_op!(self, frame, span, >=), - OpCode::OpFindFile => match self.stack_pop() { + Op::FindFile => match self.stack_pop() { Value::UnresolvedPath(path) => { let resolved = self .nix_search_path @@ -873,7 +936,7 @@ where _ => panic!("tvix compiler bug: OpFindFile called on non-UnresolvedPath"), }, - OpCode::OpResolveHomePath => match self.stack_pop() { + Op::ResolveHomePath => match self.stack_pop() { Value::UnresolvedPath(path) => { match dirs::home_dir() { None => { @@ -896,24 +959,23 @@ where } }, - OpCode::OpPushWith(StackIdx(idx)) => self.with_stack.push(frame.stack_offset + idx), + Op::PushWith => self + .with_stack + .push(frame.stack_offset + frame.read_uvarint() as usize), - OpCode::OpPopWith => { + Op::PopWith => { self.with_stack.pop(); } - OpCode::OpAssertFail => { + Op::AssertFail => { self.stack .push(Value::from(CatchableErrorKind::AssertionFailed)); } - // Data-carrying operands should never be executed, - // that is a critical error in the VM/compiler. - OpCode::DataStackIdx(_) - | OpCode::DataDeferredLocal(_) - | OpCode::DataUpvalueIdx(_) - | OpCode::DataCaptureWith => { - panic!("Tvix bug: attempted to execute data-carrying operand") + // Encountering an invalid opcode is a critical error in the + // VM/compiler. + Op::Invalid => { + panic!("Tvix bug: attempted to execute invalid opcode") } } } @@ -933,7 +995,7 @@ where &self.stack[self.stack.len() - 1 - offset] } - fn run_attrset(&mut self, frame: &CallFrame, count: usize) -> EvalResult<()> { + fn run_attrset(&mut self, count: usize, frame: &CallFrame) -> EvalResult<()> { let attrs = NixAttrs::construct(count, self.stack.split_off(self.stack.len() - count * 2)) .with_span(frame, self)? .map(Value::attrs) @@ -971,7 +1033,7 @@ where /// Interpolate string fragments by popping the specified number of /// fragments of the stack, evaluating them to strings, and pushing /// the concatenated result string back on the stack. - fn run_interpolate(&mut self, frame: &CallFrame, count: usize) -> EvalResult<()> { + fn run_interpolate(&mut self, count: u64, frame: &CallFrame) -> EvalResult<()> { let mut out = BString::default(); // Interpolation propagates the context and union them. let mut context: NixContext = NixContext::new(); @@ -1090,64 +1152,74 @@ where } /// Populate the upvalue fields of a thunk or closure under construction. + /// + /// See the closely tied function `emit_upvalue_data` in the compiler + /// implementation for details on the argument processing. fn populate_upvalues( &mut self, frame: &mut CallFrame, - count: usize, + count: u64, mut upvalues: impl DerefMut<Target = Upvalues>, ) -> EvalResult<()> { - for _ in 0..count { - match frame.inc_ip() { - OpCode::DataStackIdx(StackIdx(stack_idx)) => { - let idx = frame.stack_offset + stack_idx; - - let val = match self.stack.get(idx) { - Some(val) => val.clone(), - None => { - return frame.error( - self, - ErrorKind::TvixBug { - msg: "upvalue to be captured was missing on stack", - metadata: Some(Rc::new(json!({ - "ip": format!("{:#x}", frame.ip.0 - 1), - "stack_idx(relative)": stack_idx, - "stack_idx(absolute)": idx, - }))), - }, - ); - } - }; + // Determine whether to capture the with stack, and then shift the + // actual count of upvalues back. + let capture_with = count & 0b1 == 1; + let count = count >> 1; + if capture_with { + // Start the captured with_stack off of the + // current call frame's captured with_stack, ... + let mut captured_with_stack = frame + .upvalues + .with_stack() + .cloned() + // ... or make an empty one if there isn't one already. + .unwrap_or_else(|| Vec::with_capacity(self.with_stack.len())); + + for idx in &self.with_stack { + captured_with_stack.push(self.stack[*idx].clone()); + } - upvalues.deref_mut().push(val); - } + upvalues.deref_mut().set_with_stack(captured_with_stack); + } - OpCode::DataUpvalueIdx(upv_idx) => { - upvalues.deref_mut().push(frame.upvalue(upv_idx).clone()); - } + for _ in 0..count { + let pos = Position(frame.read_uvarint()); - OpCode::DataDeferredLocal(idx) => { - upvalues.deref_mut().push(Value::DeferredUpvalue(idx)); - } + if let Some(stack_idx) = pos.runtime_stack_index() { + let idx = frame.stack_offset + stack_idx.0; - OpCode::DataCaptureWith => { - // Start the captured with_stack off of the - // current call frame's captured with_stack, ... - let mut captured_with_stack = frame - .upvalues - .with_stack() - .cloned() - // ... or make an empty one if there isn't one already. - .unwrap_or_else(|| Vec::with_capacity(self.with_stack.len())); - - for idx in &self.with_stack { - captured_with_stack.push(self.stack[*idx].clone()); + let val = match self.stack.get(idx) { + Some(val) => val.clone(), + None => { + return frame.error( + self, + ErrorKind::TvixBug { + msg: "upvalue to be captured was missing on stack", + metadata: Some(Rc::new(json!({ + "ip": format!("{:#x}", frame.ip.0 - 1), + "stack_idx(relative)": stack_idx.0, + "stack_idx(absolute)": idx, + }))), + }, + ); } + }; - upvalues.deref_mut().set_with_stack(captured_with_stack); - } + upvalues.deref_mut().push(val); + continue; + } - _ => panic!("compiler error: missing closure operand"), + if let Some(idx) = pos.runtime_deferred_local() { + upvalues.deref_mut().push(Value::DeferredUpvalue(idx)); + continue; } + + if let Some(idx) = pos.runtime_upvalue_index() { + upvalues.deref_mut().push(frame.upvalue(idx).clone()); + continue; + } + + panic!("Tvix bug: invalid capture position emitted") } Ok(()) diff --git a/tvix/glue/Cargo.toml b/tvix/glue/Cargo.toml index 6e9f313aa0a9..bb522dceb902 100644 --- a/tvix/glue/Cargo.toml +++ b/tvix/glue/Cargo.toml @@ -4,47 +4,46 @@ version = "0.1.0" edition = "2021" [dependencies] -async-compression = { version = "0.4.9", features = ["tokio", "gzip", "bzip2", "xz"]} -bstr = "1.6.0" -bytes = "1.4.0" -data-encoding = "2.6.0" -futures = "0.3.30" -magic = "0.16.2" +async-compression = { workspace = true, features = ["tokio", "gzip", "bzip2", "xz"] } +bstr = { workspace = true } +bytes = { workspace = true } +data-encoding = { workspace = true } +futures = { workspace = true } +magic = { workspace = true } nix-compat = { path = "../nix-compat" } -pin-project = "1.1" -reqwest = { version = "0.12.0", features = ["rustls-tls-native-roots"], default-features = false } +pin-project = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots"] } tvix-build = { path = "../build", default-features = false, features = []} tvix-eval = { path = "../eval" } tvix-castore = { path = "../castore" } tvix-store = { path = "../store", default-features = false, features = []} tvix-tracing = { path = "../tracing" } -tracing = "0.1.37" -tracing-indicatif = "0.3.6" -tokio = "1.28.0" -tokio-tar = "0.3.1" -tokio-util = { version = "0.7.9", features = ["io", "io-util", "compat"] } -thiserror = "1.0.38" -serde = "1.0.195" -serde_json = "1.0" -sha2 = "0.10.8" -sha1 = "0.10.6" -md-5 = "0.10.6" -url = "2.4.0" -walkdir = "2.4.0" -clap = { version = "4.4.0", default-features = false } - -[dependencies.wu-manber] -git = "https://github.com/tvlfyi/wu-manber.git" +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +tokio = { workspace = true } +tokio-tar = { workspace = true } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +thiserror = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sha2 = { workspace = true } +sha1 = { workspace = true } +md-5 = { workspace = true } +url = { workspace = true } +walkdir = { workspace = true } +clap = { workspace = true } +wu-manber = { workspace = true } [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } -hex-literal = "0.4.1" -lazy_static = "1.4.0" -mimalloc = "0.1.43" -nix = { version = "0.27.1", features = [ "fs" ] } -pretty_assertions = "1.4.0" -rstest = "0.19.0" -tempfile = "3.8.1" +criterion = { workspace = true, features = ["html_reports"] } +hex-literal = { workspace = true } +lazy_static = { workspace = true } +mimalloc = { workspace = true } +nix = { workspace = true, features = ["fs"] } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tempfile = { workspace = true } +tokio-test = { workspace = true } [features] default = ["nix_tests"] diff --git a/tvix/glue/benches/eval.rs b/tvix/glue/benches/eval.rs index 0a27d9aa26fe..a0823d2e129b 100644 --- a/tvix/glue/benches/eval.rs +++ b/tvix/glue/benches/eval.rs @@ -60,7 +60,7 @@ fn interpret(code: &str) { let eval = eval_builder.build(); let result = eval.evaluate(code, None); - assert!(result.errors.is_empty()); + assert!(result.errors.is_empty(), "{:#?}", result.errors); } fn eval_nixpkgs(c: &mut Criterion) { diff --git a/tvix/glue/default.nix b/tvix/glue/default.nix index e2b36e94b87f..0ead94a504c3 100644 --- a/tvix/glue/default.nix +++ b/tvix/glue/default.nix @@ -7,11 +7,11 @@ ''; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "nix_tests" ]; override.testPreRun = '' export SSL_CERT_FILE=/dev/null ''; - }; + }); }) diff --git a/tvix/glue/src/builtins/derivation.rs b/tvix/glue/src/builtins/derivation.rs index b17b90466965..5bc9dab71283 100644 --- a/tvix/glue/src/builtins/derivation.rs +++ b/tvix/glue/src/builtins/derivation.rs @@ -179,9 +179,7 @@ pub(crate) mod derivation_builtins { use nix_compat::nixhash::CAHash; use nix_compat::store_path::{build_ca_path, hash_placeholder}; use sha2::Sha256; - use tvix_castore::proto as castorepb; - use tvix_castore::proto::node::Node; - use tvix_castore::proto::FileNode; + use tvix_castore::Node; use tvix_eval::generators::Gen; use tvix_eval::{NixContext, NixContextElement, NixString}; use tvix_store::proto::{NarInfo, PathInfo}; @@ -570,7 +568,7 @@ pub(crate) mod derivation_builtins { let blob_digest = blob_writer.close().await?; let ca_hash = CAHash::Text(Sha256::digest(&content).into()); - let store_path = + let store_path: StorePathRef = build_ca_path(name.to_str()?, &ca_hash, content.iter_ctx_plain(), false) .map_err(|_e| { nix_compat::derivation::DerivationError::InvalidOutputName( @@ -579,12 +577,11 @@ pub(crate) mod derivation_builtins { }) .map_err(DerivationError::InvalidDerivation)?; - let root_node = Node::File(FileNode { - name: store_path.to_string().into(), - digest: blob_digest.into(), + let root_node = Node::File { + digest: blob_digest, size: blob_size, executable: false, - }); + }; // calculate the nar hash let (nar_size, nar_sha256) = state @@ -604,9 +601,10 @@ pub(crate) mod derivation_builtins { state .path_info_service .put(PathInfo { - node: Some(castorepb::Node { - node: Some(root_node), - }), + node: Some(tvix_castore::proto::Node::from_name_and_node( + store_path.to_string().into(), + root_node, + )), references: reference_paths .iter() .map(|x| bytes::Bytes::copy_from_slice(x.digest())) diff --git a/tvix/glue/src/builtins/import.rs b/tvix/glue/src/builtins/import.rs index 273be08ef7b6..34ae2778ecdd 100644 --- a/tvix/glue/src/builtins/import.rs +++ b/tvix/glue/src/builtins/import.rs @@ -3,6 +3,7 @@ use crate::builtins::errors::ImportError; use std::path::Path; use tvix_castore::import::ingest_entries; +use tvix_castore::Node; use tvix_eval::{ builtin_macros::builtins, generators::{self, GenCo}, @@ -16,7 +17,7 @@ async fn filtered_ingest( co: GenCo, path: &Path, filter: Option<&Value>, -) -> Result<tvix_castore::proto::node::Node, ErrorKind> { +) -> Result<Node, ErrorKind> { let mut entries: Vec<walkdir::DirEntry> = vec![]; let mut it = walkdir::WalkDir::new(path) .follow_links(false) @@ -111,11 +112,9 @@ mod import_builtins { use crate::tvix_store_io::TvixStoreIO; use nix_compat::nixhash::{CAHash, NixHash}; - use nix_compat::store_path::StorePath; + use nix_compat::store_path::StorePathRef; use sha2::Digest; use tokio::io::AsyncWriteExt; - use tvix_castore::proto::node::Node; - use tvix_castore::proto::FileNode; use tvix_eval::builtins::coerce_value_to_path; use tvix_eval::generators::Gen; use tvix_eval::{generators::GenCo, ErrorKind, Value}; @@ -214,13 +213,11 @@ mod import_builtins { .tokio_handle .block_on(async { blob_writer.close().await })?; - let root_node = Node::File(FileNode { - // The name gets set further down, while constructing the PathInfo. - name: "".into(), - digest: blob_digest.into(), + let root_node = Node::File { + digest: blob_digest, size: blob_size, executable: false, - }); + }; let ca_hash = if recursive_ingestion { let (_nar_size, nar_sha256) = state @@ -380,16 +377,16 @@ mod import_builtins { } })?; - let path_exists = if let Ok((store_path, sub_path)) = StorePath::from_absolute_path_full(p) - { - if !sub_path.as_os_str().is_empty() { - false + let path_exists = + if let Ok((store_path, sub_path)) = StorePathRef::from_absolute_path_full(p) { + if !sub_path.as_os_str().is_empty() { + false + } else { + state.store_path_exists(store_path.as_ref()).await? + } } else { - state.store_path_exists(store_path.as_ref()).await? - } - } else { - false - }; + false + }; if !path_exists { return Err(ImportError::PathNotInStore(p.into()).into()); diff --git a/tvix/glue/src/fetchers/mod.rs b/tvix/glue/src/fetchers/mod.rs index eb035a5a905c..065d011361a7 100644 --- a/tvix/glue/src/fetchers/mod.rs +++ b/tvix/glue/src/fetchers/mod.rs @@ -10,11 +10,7 @@ use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite, AsyncWriteExt, BufReader}; use tokio_util::io::{InspectReader, InspectWriter}; use tracing::{instrument, warn, Span}; use tracing_indicatif::span_ext::IndicatifSpanExt; -use tvix_castore::{ - blobservice::BlobService, - directoryservice::DirectoryService, - proto::{node::Node, FileNode}, -}; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Node}; use tvix_store::{nar::NarCalculationService, pathinfoservice::PathInfoService, proto::PathInfo}; use url::Url; @@ -331,12 +327,11 @@ where // Construct and return the FileNode describing the downloaded contents. Ok(( - Node::File(FileNode { - name: vec![].into(), - digest: blob_writer.close().await?.into(), + Node::File { + digest: blob_writer.close().await?, size: blob_size, executable: false, - }), + }, CAHash::Flat(actual_hash), blob_size, )) @@ -531,12 +526,11 @@ where // Construct and return the FileNode describing the downloaded contents, // make it executable. - let root_node = Node::File(FileNode { - name: vec![].into(), - digest: blob_digest.into(), + let root_node = Node::File { + digest: blob_digest, size: file_size, executable: true, - }); + }; Ok((root_node, CAHash::Nar(actual_hash), file_size)) } @@ -560,9 +554,6 @@ where // Calculate the store path to return, by calculating from ca_hash. let store_path = build_ca_path(name, &ca_hash, Vec::<String>::new(), false)?; - // Rename the node name to match the Store Path. - let node = node.rename(store_path.to_string().into()); - // If the resulting hash is not a CAHash::Nar, we also need to invoke // `calculate_nar` to calculate this representation, as it's required in // the [PathInfo]. @@ -580,7 +571,10 @@ where // Construct the PathInfo and persist it. let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { node: Some(node) }), + node: Some(tvix_castore::proto::Node::from_name_and_node( + store_path.to_string().into(), + node.clone(), + )), references: vec![], narinfo: Some(tvix_store::proto::NarInfo { nar_size, @@ -592,13 +586,12 @@ where }), }; - let path_info = self - .path_info_service + self.path_info_service .put(path_info) .await .map_err(|e| FetcherError::Io(e.into()))?; - Ok((store_path, path_info.node.unwrap().node.unwrap())) + Ok((store_path, node)) } } diff --git a/tvix/glue/src/known_paths.rs b/tvix/glue/src/known_paths.rs index edc57c38f247..239acca9829a 100644 --- a/tvix/glue/src/known_paths.rs +++ b/tvix/glue/src/known_paths.rs @@ -25,27 +25,27 @@ pub struct KnownPaths { /// /// Keys are derivation paths, values are a tuple of the "hash derivation /// modulo" and the Derivation struct itself. - derivations: HashMap<StorePath, ([u8; 32], Derivation)>, + derivations: HashMap<StorePath<String>, ([u8; 32], Derivation)>, /// A map from output path to (one) drv path. /// Note that in the case of FODs, multiple drvs can produce the same output /// path. We use one of them. - outputs_to_drvpath: HashMap<StorePath, StorePath>, + outputs_to_drvpath: HashMap<StorePath<String>, StorePath<String>>, /// A map from output path to fetches (and their names). - outputs_to_fetches: HashMap<StorePath, (String, Fetch)>, + outputs_to_fetches: HashMap<StorePath<String>, (String, Fetch)>, } impl KnownPaths { /// Fetch the opaque "hash derivation modulo" for a given derivation path. - pub fn get_hash_derivation_modulo(&self, drv_path: &StorePath) -> Option<&[u8; 32]> { + pub fn get_hash_derivation_modulo(&self, drv_path: &StorePath<String>) -> Option<&[u8; 32]> { self.derivations .get(drv_path) .map(|(hash_derivation_modulo, _derivation)| hash_derivation_modulo) } /// Return a reference to the Derivation for a given drv path. - pub fn get_drv_by_drvpath(&self, drv_path: &StorePath) -> Option<&Derivation> { + pub fn get_drv_by_drvpath(&self, drv_path: &StorePath<String>) -> Option<&Derivation> { self.derivations .get(drv_path) .map(|(_hash_derivation_modulo, derivation)| derivation) @@ -54,7 +54,10 @@ impl KnownPaths { /// Return the drv path of the derivation producing the passed output path. /// Note there can be multiple Derivations producing the same output path in /// flight; this function will only return one of them. - pub fn get_drv_path_for_output_path(&self, output_path: &StorePath) -> Option<&StorePath> { + pub fn get_drv_path_for_output_path( + &self, + output_path: &StorePath<String>, + ) -> Option<&StorePath<String>> { self.outputs_to_drvpath.get(output_path) } @@ -63,7 +66,7 @@ impl KnownPaths { /// be fully calculated. /// All input derivations this refers to must also be inserted to this /// struct. - pub fn add_derivation(&mut self, drv_path: StorePath, drv: Derivation) { + pub fn add_derivation(&mut self, drv_path: StorePath<String>, drv: Derivation) { // check input derivations to have been inserted. #[cfg(debug_assertions)] { @@ -124,11 +127,19 @@ impl KnownPaths { /// Return the name and fetch producing the passed output path. /// Note there can also be (multiple) Derivations producing the same output path. - pub fn get_fetch_for_output_path(&self, output_path: &StorePath) -> Option<(String, Fetch)> { + pub fn get_fetch_for_output_path( + &self, + output_path: &StorePath<String>, + ) -> Option<(String, Fetch)> { self.outputs_to_fetches .get(output_path) .map(|(name, fetch)| (name.to_owned(), fetch.to_owned())) } + + /// Returns an iterator over all known derivations and their store path. + pub fn get_derivations(&self) -> impl Iterator<Item = (&StorePath<String>, &Derivation)> { + self.derivations.iter().map(|(k, v)| (k, &v.1)) + } } #[cfg(test)] @@ -151,26 +162,26 @@ mod tests { "tests/ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv" )) .expect("must parse"); - static ref BAR_DRV_PATH: StorePath = + static ref BAR_DRV_PATH: StorePath<String> = StorePath::from_bytes(b"ss2p4wmxijn652haqyd7dckxwl4c7hxx-bar.drv").expect("must parse"); - static ref FOO_DRV_PATH: StorePath = + static ref FOO_DRV_PATH: StorePath<String> = StorePath::from_bytes(b"ch49594n9avinrf8ip0aslidkc4lxkqv-foo.drv").expect("must parse"); - static ref BAR_OUT_PATH: StorePath = + static ref BAR_OUT_PATH: StorePath<String> = StorePath::from_bytes(b"mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar").expect("must parse"); - static ref FOO_OUT_PATH: StorePath = + static ref FOO_OUT_PATH: StorePath<String> = StorePath::from_bytes(b"fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo").expect("must parse"); static ref FETCH_URL : Fetch = Fetch::URL{ url: Url::parse("https://raw.githubusercontent.com/aaptel/notmuch-extract-patch/f732a53e12a7c91a06755ebfab2007adc9b3063b/notmuch-extract-patch").unwrap(), exp_hash: Some(nixhash::from_sri_str("sha256-Xa1Jbl2Eq5+L0ww+Ph1osA3Z/Dxe/RkN1/dITQCdXFk=").unwrap()) }; - static ref FETCH_URL_OUT_PATH: StorePath = StorePath::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap(); + static ref FETCH_URL_OUT_PATH: StorePath<String> = StorePath::from_bytes(b"06qi00hylriyfm0nl827crgjvbax84mz-notmuch-extract-patch").unwrap(); static ref FETCH_TARBALL : Fetch = Fetch::Tarball{ url: Url::parse("https://github.com/NixOS/nixpkgs/archive/91050ea1e57e50388fa87a3302ba12d188ef723a.tar.gz").unwrap(), exp_nar_sha256: Some(nixbase32::decode_fixed("1hf6cgaci1n186kkkjq106ryf8mmlq9vnwgfwh625wa8hfgdn4dm").unwrap()) }; - static ref FETCH_TARBALL_OUT_PATH: StorePath = StorePath::from_bytes(b"7adgvk5zdfq4pwrhsm3n9lzypb12gw0g-source").unwrap(); + static ref FETCH_TARBALL_OUT_PATH: StorePath<String> = StorePath::from_bytes(b"7adgvk5zdfq4pwrhsm3n9lzypb12gw0g-source").unwrap(); } /// ensure we don't allow acdding a Derivation that depends on another, @@ -269,5 +280,21 @@ mod tests { ); } + #[test] + fn get_derivations_working() { + let mut known_paths = KnownPaths::default(); + + // Add BAR_DRV + known_paths.add_derivation(BAR_DRV_PATH.clone(), BAR_DRV.clone()); + + // We should be able to find BAR_DRV_PATH and BAR_DRV as a pair in get_derivations. + assert_eq!( + Some((&BAR_DRV_PATH.clone(), &BAR_DRV.clone())), + known_paths + .get_derivations() + .find(|(s, d)| (*s, *d) == (&BAR_DRV_PATH, &BAR_DRV)) + ); + } + // TODO: add test panicking about missing digest } diff --git a/tvix/glue/src/refscan.rs b/tvix/glue/src/refscan.rs index 0e0bb6c77828..80a126349746 100644 --- a/tvix/glue/src/refscan.rs +++ b/tvix/glue/src/refscan.rs @@ -6,62 +6,250 @@ //! //! The scanner itself is using the Wu-Manber string-matching algorithm, using //! our fork of the `wu-mamber` crate. - +use pin_project::pin_project; use std::collections::BTreeSet; +use std::pin::Pin; +use std::sync::Arc; +use std::task::{ready, Poll}; +use tokio::io::{AsyncBufRead, AsyncRead, ReadBuf}; use wu_manber::TwoByteWM; -pub const STORE_PATH_LEN: usize = "/nix/store/00000000000000000000000000000000".len(); - -/// Represents a "primed" reference scanner with an automaton that knows the set -/// of store paths to scan for. -pub struct ReferenceScanner<P: Ord + AsRef<[u8]>> { +/// A searcher that incapsulates the candidates and the Wu-Manber searcher. +/// This is separate from the scanner because we need to look for the same +/// pattern in multiple outputs and don't want to pay the price of constructing +/// the searcher for each build output. +pub struct ReferencePatternInner<P> { candidates: Vec<P>, + longest_candidate: usize, + // FUTUREWORK: Support overlapping patterns to be compatible with cpp Nix searcher: Option<TwoByteWM>, - matches: Vec<usize>, } -impl<P: Clone + Ord + AsRef<[u8]>> ReferenceScanner<P> { - /// Construct a new `ReferenceScanner` that knows how to scan for the given - /// candidate store paths. +#[derive(Clone)] +pub struct ReferencePattern<P> { + inner: Arc<ReferencePatternInner<P>>, +} + +impl<P> ReferencePattern<P> { + pub fn candidates(&self) -> &[P] { + &self.inner.candidates + } + + pub fn longest_candidate(&self) -> usize { + self.inner.longest_candidate + } +} + +impl<P: AsRef<[u8]>> ReferencePattern<P> { + /// Construct a new `ReferencePattern` that knows how to scan for the given + /// candidates. pub fn new(candidates: Vec<P>) -> Self { let searcher = if candidates.is_empty() { None } else { Some(TwoByteWM::new(&candidates)) }; + let longest_candidate = candidates.iter().fold(0, |v, c| v.max(c.as_ref().len())); - ReferenceScanner { - searcher, - candidates, - matches: Default::default(), + ReferencePattern { + inner: Arc::new(ReferencePatternInner { + searcher, + candidates, + longest_candidate, + }), } } +} + +impl<P> From<Vec<P>> for ReferencePattern<P> +where + P: AsRef<[u8]>, +{ + fn from(candidates: Vec<P>) -> Self { + Self::new(candidates) + } +} + +/// Represents a "primed" reference scanner with an automaton that knows the set +/// of bytes patterns to scan for. +pub struct ReferenceScanner<P> { + pattern: ReferencePattern<P>, + matches: Vec<bool>, +} + +impl<P: AsRef<[u8]>> ReferenceScanner<P> { + /// Construct a new `ReferenceScanner` that knows how to scan for the given + /// candidate bytes patterns. + pub fn new<IP: Into<ReferencePattern<P>>>(pattern: IP) -> Self { + let pattern = pattern.into(); + let matches = vec![false; pattern.candidates().len()]; + ReferenceScanner { pattern, matches } + } - /// Scan the given str for all non-overlapping matches and collect them + /// Scan the given buffer for all non-overlapping matches and collect them /// in the scanner. pub fn scan<S: AsRef<[u8]>>(&mut self, haystack: S) { - if haystack.as_ref().len() < STORE_PATH_LEN { + if haystack.as_ref().len() < self.pattern.longest_candidate() { return; } - if let Some(searcher) = &self.searcher { + if let Some(searcher) = &self.pattern.inner.searcher { for m in searcher.find(haystack) { - self.matches.push(m.pat_idx); + self.matches[m.pat_idx] = true; } } } + pub fn pattern(&self) -> &ReferencePattern<P> { + &self.pattern + } + + pub fn matches(&self) -> &[bool] { + &self.matches + } + + pub fn candidate_matches(&self) -> impl Iterator<Item = &P> { + let candidates = self.pattern.candidates(); + self.matches.iter().enumerate().filter_map(|(idx, found)| { + if *found { + Some(&candidates[idx]) + } else { + None + } + }) + } +} + +impl<P: Clone + Ord + AsRef<[u8]>> ReferenceScanner<P> { /// Finalise the reference scanner and return the resulting matches. pub fn finalise(self) -> BTreeSet<P> { - self.matches - .into_iter() - .map(|idx| self.candidates[idx].clone()) - .collect() + self.candidate_matches().cloned().collect() + } +} + +const DEFAULT_BUF_SIZE: usize = 8 * 1024; + +#[pin_project] +pub struct ReferenceReader<P, R> { + scanner: ReferenceScanner<P>, + buffer: Vec<u8>, + consumed: usize, + #[pin] + reader: R, +} + +impl<P, R> ReferenceReader<P, R> +where + P: AsRef<[u8]>, +{ + pub fn new(pattern: ReferencePattern<P>, reader: R) -> ReferenceReader<P, R> { + Self::with_capacity(DEFAULT_BUF_SIZE, pattern, reader) + } + + pub fn with_capacity( + capacity: usize, + pattern: ReferencePattern<P>, + reader: R, + ) -> ReferenceReader<P, R> { + // If capacity is not at least as long as longest_candidate we can't do a scan + let capacity = capacity.max(pattern.longest_candidate()); + ReferenceReader { + scanner: ReferenceScanner::new(pattern), + buffer: Vec::with_capacity(capacity), + consumed: 0, + reader, + } + } + + pub fn scanner(&self) -> &ReferenceScanner<P> { + &self.scanner + } +} + +impl<P, R> ReferenceReader<P, R> +where + P: Clone + Ord + AsRef<[u8]>, +{ + pub fn finalise(self) -> BTreeSet<P> { + self.scanner.finalise() + } +} + +impl<P, R> AsyncRead for ReferenceReader<P, R> +where + R: AsyncRead, + P: AsRef<[u8]>, +{ + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll<std::io::Result<()>> { + let internal_buf = ready!(self.as_mut().poll_fill_buf(cx))?; + let amt = buf.remaining().min(internal_buf.len()); + buf.put_slice(&internal_buf[..amt]); + self.consume(amt); + Poll::Ready(Ok(())) + } +} + +impl<P, R> AsyncBufRead for ReferenceReader<P, R> +where + R: AsyncRead, + P: AsRef<[u8]>, +{ + fn poll_fill_buf( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> Poll<std::io::Result<&[u8]>> { + let overlap = self.scanner.pattern.longest_candidate() - 1; + let mut this = self.project(); + // Still data in buffer + if *this.consumed < this.buffer.len() { + return Poll::Ready(Ok(&this.buffer[*this.consumed..])); + } + // We need to copy last `overlap` bytes to front to deal with references that overlap reads + if *this.consumed > overlap { + let start = this.buffer.len() - overlap; + this.buffer.copy_within(start.., 0); + this.buffer.truncate(overlap); + *this.consumed = overlap; + } + // Read at least until self.buffer.len() > overlap so we can do one scan + loop { + let filled = { + let mut buf = ReadBuf::uninit(this.buffer.spare_capacity_mut()); + ready!(this.reader.as_mut().poll_read(cx, &mut buf))?; + buf.filled().len() + }; + // SAFETY: We just read `filled` amount of data above + unsafe { + this.buffer.set_len(filled + this.buffer.len()); + } + if filled == 0 || this.buffer.len() > overlap { + break; + } + } + + #[allow(clippy::needless_borrows_for_generic_args)] // misfiring lint (breaks code below) + this.scanner.scan(&this.buffer); + + Poll::Ready(Ok(&this.buffer[*this.consumed..])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + debug_assert!(self.consumed + amt <= self.buffer.len()); + let this = self.project(); + *this.consumed += amt; } } #[cfg(test)] mod tests { + use rstest::rstest; + use tokio::io::AsyncReadExt as _; + use tokio_test::io::Builder; + use super::*; // The actual derivation of `nixpkgs.hello`. @@ -112,4 +300,40 @@ mod tests { assert!(result.contains(c)); } } + + #[rstest] + #[case::normal(8096, 8096)] + #[case::small_capacity(8096, 1)] + #[case::small_read(1, 8096)] + #[case::all_small(1, 1)] + #[tokio::test] + async fn test_reference_reader(#[case] chunk_size: usize, #[case] capacity: usize) { + let candidates = vec![ + // these exist in the drv: + "33l4p0pn0mybmqzaxfkpppyh7vx1c74p", + "pf80kikyxr63wrw56k00i1kw6ba76qik", + "cp65c8nk29qq5cl1wyy5qyw103cwmax7", + // this doesn't: + "fn7zvafq26f0c8b17brs7s95s10ibfzs", + ]; + let pattern = ReferencePattern::new(candidates.clone()); + let mut mock = Builder::new(); + for c in HELLO_DRV.as_bytes().chunks(chunk_size) { + mock.read(c); + } + let mock = mock.build(); + let mut reader = ReferenceReader::with_capacity(capacity, pattern, mock); + let mut s = String::new(); + reader.read_to_string(&mut s).await.unwrap(); + assert_eq!(s, HELLO_DRV); + + let result = reader.finalise(); + assert_eq!(result.len(), 3); + + for c in candidates[..3].iter() { + assert!(result.contains(c)); + } + } + + // FUTUREWORK: Test with large file } diff --git a/tvix/glue/src/tvix_build.rs b/tvix/glue/src/tvix_build.rs index e9eb1725ef3e..ae01351503f2 100644 --- a/tvix/glue/src/tvix_build.rs +++ b/tvix/glue/src/tvix_build.rs @@ -1,7 +1,7 @@ //! This module contains glue code translating from //! [nix_compat::derivation::Derivation] to [tvix_build::proto::BuildRequest]. -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::BTreeMap; use bytes::Bytes; use nix_compat::{derivation::Derivation, nixbase32}; @@ -10,7 +10,7 @@ use tvix_build::proto::{ build_request::{AdditionalFile, BuildConstraints, EnvVar}, BuildRequest, }; -use tvix_castore::proto::{self, node::Node}; +use tvix_castore::Node; /// These are the environment variables that Nix sets in its sandbox for every /// build. @@ -36,10 +36,9 @@ const NIX_ENVIRONMENT_VARS: [(&str, &str); 12] = [ /// (`fn_input_sources_to_node`) /// - one translating a tuple of drv path and (a subset of their) output names to /// castore nodes of the selected outpus (`fn_input_drvs_to_output_nodes`). -#[allow(clippy::mutable_key_type)] pub(crate) fn derivation_to_build_request( derivation: &Derivation, - inputs: BTreeSet<Node>, + inputs: BTreeMap<bytes::Bytes, Node>, ) -> std::io::Result<BuildRequest> { debug_assert!(derivation.validate(true).is_ok(), "drv must validate"); @@ -111,7 +110,7 @@ pub(crate) fn derivation_to_build_request( .collect(), inputs: inputs .into_iter() - .map(|n| proto::Node { node: Some(n) }) + .map(|(name, node)| tvix_castore::proto::Node::from_name_and_node(name, node)) .collect(), inputs_dir: nix_compat::store_path::STORE_DIR[1..].into(), constraints, @@ -192,18 +191,15 @@ fn calculate_pass_as_file_env(k: &str) -> (String, String) { #[cfg(test)] mod test { - use std::collections::BTreeSet; - use bytes::Bytes; use nix_compat::derivation::Derivation; + use std::collections::BTreeMap; use tvix_build::proto::{ build_request::{AdditionalFile, BuildConstraints, EnvVar}, BuildRequest, }; - use tvix_castore::{ - fixtures::DUMMY_DIGEST, - proto::{self, node::Node, DirectoryNode}, - }; + use tvix_castore::fixtures::DUMMY_DIGEST; + use tvix_castore::Node; use crate::tvix_build::NIX_ENVIRONMENT_VARS; @@ -211,11 +207,11 @@ mod test { use lazy_static::lazy_static; lazy_static! { - static ref INPUT_NODE_FOO: Node = Node::Directory(DirectoryNode { - name: Bytes::from("mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar"), - digest: DUMMY_DIGEST.clone().into(), - size: 42, - }); + static ref INPUT_NODE_FOO_NAME: Bytes = "mp57d33657rf34lzvlbpfa1gjfv5gmpg-bar".into(); + static ref INPUT_NODE_FOO: Node = Node::Directory { + digest: DUMMY_DIGEST.clone(), + size: 42 + }; } #[test] @@ -224,9 +220,11 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); - let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([INPUT_NODE_FOO.clone()])) - .expect("must succeed"); + let build_request = derivation_to_build_request( + &derivation, + BTreeMap::from([(INPUT_NODE_FOO_NAME.clone(), INPUT_NODE_FOO.clone())]), + ) + .expect("must succeed"); let mut expected_environment_vars = vec![ EnvVar { @@ -263,9 +261,10 @@ mod test { command_args: vec![":".into()], outputs: vec!["nix/store/fhaj6gmwns62s6ypkcldbaj2ybvkhx3p-foo".into()], environment_vars: expected_environment_vars, - inputs: vec![proto::Node { - node: Some(INPUT_NODE_FOO.clone()) - }], + inputs: vec![tvix_castore::proto::Node::from_name_and_node( + INPUT_NODE_FOO_NAME.clone(), + INPUT_NODE_FOO.clone() + )], inputs_dir: "nix/store".into(), constraints: Some(BuildConstraints { system: derivation.system.clone(), @@ -289,7 +288,7 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([])).expect("must succeed"); + derivation_to_build_request(&derivation, BTreeMap::from([])).expect("must succeed"); let mut expected_environment_vars = vec![ EnvVar { @@ -359,7 +358,7 @@ mod test { let derivation = Derivation::from_aterm_bytes(aterm_bytes).expect("must parse"); let build_request = - derivation_to_build_request(&derivation, BTreeSet::from([])).expect("must succeed"); + derivation_to_build_request(&derivation, BTreeMap::from([])).expect("must succeed"); let mut expected_environment_vars = vec![ // Note how bar and baz are not present in the env anymore, diff --git a/tvix/glue/src/tvix_io.rs b/tvix/glue/src/tvix_io.rs index db0c2cef77aa..323fa8d20ccb 100644 --- a/tvix/glue/src/tvix_io.rs +++ b/tvix/glue/src/tvix_io.rs @@ -1,12 +1,10 @@ //! This module implements a wrapper around tvix-eval's [EvalIO] type, //! adding functionality which is required by tvix-cli: //! -//! 1. Marking plain paths known to the reference scanner. -//! 2. Handling the C++ Nix `__corepkgs__`-hack for nixpkgs bootstrapping. +//! 1. Handling the C++ Nix `__corepkgs__`-hack for nixpkgs bootstrapping. //! //! All uses of [EvalIO] in tvix-cli must make use of this wrapper, -//! otherwise fundamental features like nixpkgs bootstrapping and hash -//! calculation will not work. +//! otherwise nixpkgs bootstrapping will not work. use std::io::{self, Cursor}; use std::path::{Path, PathBuf}; diff --git a/tvix/glue/src/tvix_store_io.rs b/tvix/glue/src/tvix_store_io.rs index c25194d50fda..93675b438f25 100644 --- a/tvix/glue/src/tvix_store_io.rs +++ b/tvix/glue/src/tvix_store_io.rs @@ -4,9 +4,9 @@ use futures::{StreamExt, TryStreamExt}; use nix_compat::nixhash::NixHash; use nix_compat::store_path::StorePathRef; use nix_compat::{nixhash::CAHash, store_path::StorePath}; +use std::collections::BTreeMap; use std::{ cell::RefCell, - collections::BTreeSet, io, path::{Path, PathBuf}, sync::Arc, @@ -15,15 +15,13 @@ use tokio_util::io::SyncIoBridge; use tracing::{error, instrument, warn, Level, Span}; use tracing_indicatif::span_ext::IndicatifSpanExt; use tvix_build::buildservice::BuildService; -use tvix_castore::proto::node::Node; use tvix_eval::{EvalIO, FileType, StdIO}; use tvix_store::nar::NarCalculationService; use tvix_castore::{ blobservice::BlobService, directoryservice::{self, DirectoryService}, - proto::NamedNode, - B3Digest, + Node, }; use tvix_store::{pathinfoservice::PathInfoService, proto::PathInfo}; @@ -67,7 +65,7 @@ pub struct TvixStoreIO { >, // Paths known how to produce, by building or fetching. - pub(crate) known_paths: RefCell<KnownPaths>, + pub known_paths: RefCell<KnownPaths>, } impl TvixStoreIO { @@ -107,7 +105,7 @@ impl TvixStoreIO { #[instrument(skip(self, store_path), fields(store_path=%store_path, indicatif.pb_show=1), ret(level = Level::TRACE), err)] async fn store_path_to_node( &self, - store_path: &StorePath, + store_path: &StorePath<String>, sub_path: &Path, ) -> io::Result<Option<Node>> { // Find the root node for the store_path. @@ -122,7 +120,22 @@ impl TvixStoreIO { .await? { // if we have a PathInfo, we know there will be a root_node (due to validation) - Some(path_info) => path_info.node.expect("no node").node.expect("no node"), + // TODO: use stricter typed BuildRequest here. + Some(path_info) => { + let (name, node) = path_info + .node + .expect("no node") + .into_name_and_node() + .expect("invalid node"); + + assert_eq!( + store_path.to_string().as_bytes(), + name.as_ref(), + "returned node basename must match requested store path" + ); + + node + } // If there's no PathInfo found, this normally means we have to // trigger the build (and insert into PathInfoService, after // reference scanning). @@ -185,8 +198,7 @@ impl TvixStoreIO { // derivation_to_build_request needs castore nodes for all inputs. // Provide them, which means, here is where we recursively build // all dependencies. - #[allow(clippy::mutable_key_type)] - let mut input_nodes: BTreeSet<Node> = + let mut inputs: BTreeMap<Bytes, Node> = futures::stream::iter(drv.input_derivations.iter()) .map(|(input_drv_path, output_names)| { // look up the derivation object @@ -201,7 +213,7 @@ impl TvixStoreIO { }; // convert output names to actual paths - let output_paths: Vec<StorePath> = output_names + let output_paths: Vec<StorePath<String>> = output_names .iter() .map(|output_name| { input_drv @@ -214,6 +226,7 @@ impl TvixStoreIO { .clone() }) .collect(); + // For each output, ask for the castore node. // We're in a per-derivation context, so if they're // not built yet they'll all get built together. @@ -228,7 +241,7 @@ impl TvixStoreIO { .await?; if let Some(node) = node { - Ok(node) + Ok((output_path.to_string().into(), node)) } else { Err(io::Error::other("no node produced")) } @@ -242,26 +255,29 @@ impl TvixStoreIO { .try_collect() .await?; - // add input sources // FUTUREWORK: merge these who things together - #[allow(clippy::mutable_key_type)] - let input_nodes_input_sources: BTreeSet<Node> = + // add input sources + let input_sources: BTreeMap<_, _> = futures::stream::iter(drv.input_sources.iter()) .then(|input_source| { - Box::pin(async { - let node = self - .store_path_to_node(input_source, Path::new("")) - .await?; - if let Some(node) = node { - Ok(node) - } else { - Err(io::Error::other("no node produced")) + Box::pin({ + let input_source = input_source.clone(); + async move { + let node = self + .store_path_to_node(&input_source, Path::new("")) + .await?; + if let Some(node) = node { + Ok((input_source.to_string().into(), node)) + } else { + Err(io::Error::other("no node produced")) + } } }) }) .try_collect() .await?; - input_nodes.extend(input_nodes_input_sources); + + inputs.extend(input_sources); span.pb_set_message(&format!("🔨Building {}", &store_path)); @@ -270,7 +286,7 @@ impl TvixStoreIO { // operations, so dealt with in the Some(…) match arm // synthesize the build request. - let build_request = derivation_to_build_request(&drv, input_nodes)?; + let build_request = derivation_to_build_request(&drv, inputs)?; // create a build let build_result = self @@ -284,19 +300,21 @@ impl TvixStoreIO { // For each output, insert a PathInfo. for output in &build_result.outputs { - let root_node = output.node.as_ref().expect("invalid root node"); + let (output_name, output_node) = + output.clone().into_name_and_node().expect("invalid node"); // calculate the nar representation let (nar_size, nar_sha256) = self .nar_calculation_service - .calculate_nar(root_node) + .calculate_nar(&output_node) .await?; // assemble the PathInfo to persist let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node.clone()), - }), + node: Some(tvix_castore::proto::Node::from_name_and_node( + output_name.into(), + output_node, + )), references: vec![], // TODO: refscan narinfo: Some(tvix_store::proto::NarInfo { nar_size, @@ -329,16 +347,17 @@ impl TvixStoreIO { } // find the output for the store path requested + let s = store_path.to_string(); + build_result .outputs .into_iter() - .find(|output_node| { - output_node.node.as_ref().expect("invalid node").get_name() - == store_path.to_string().as_bytes() + .map(|e| e.into_name_and_node().expect("invalid node")) + .find(|(output_name, _output_node)| { + output_name.as_ref() == s.as_bytes() }) .expect("build didn't produce the store path") - .node - .expect("invalid node") + .1 } } } @@ -353,13 +372,13 @@ impl TvixStoreIO { .map_err(|e| std::io::Error::new(io::ErrorKind::Other, e)) } - pub(crate) async fn node_to_path_info( + pub(crate) async fn node_to_path_info<'a>( &self, - name: &str, + name: &'a str, path: &Path, ca: &CAHash, root_node: Node, - ) -> io::Result<(PathInfo, NixHash, StorePath)> { + ) -> io::Result<(PathInfo, NixHash, StorePathRef<'a>)> { // Ask the PathInfoService for the NAR size and sha256 // We always need it no matter what is the actual hash mode // because the path info construct a narinfo which *always* @@ -381,27 +400,27 @@ impl TvixStoreIO { }, )?; - // assemble a new root_node with a name that is derived from the nar hash. - let root_node = root_node.rename(output_path.to_string().into_bytes().into()); - tvix_store::import::log_node(&root_node, path); + tvix_store::import::log_node(name.as_bytes(), &root_node, path); - let path_info = - tvix_store::import::derive_nar_ca_path_info(nar_size, nar_sha256, Some(ca), root_node); + // construct a PathInfo + let path_info = tvix_store::import::derive_nar_ca_path_info( + nar_size, + nar_sha256, + Some(ca), + output_path.to_string().into(), + root_node, + ); - Ok(( - path_info, - NixHash::Sha256(nar_sha256), - output_path.to_owned(), - )) + Ok((path_info, NixHash::Sha256(nar_sha256), output_path)) } - pub(crate) async fn register_node_in_path_info_service( + pub(crate) async fn register_node_in_path_info_service<'a>( &self, - name: &str, + name: &'a str, path: &Path, ca: &CAHash, root_node: Node, - ) -> io::Result<StorePath> { + ) -> io::Result<StorePathRef<'a>> { let (path_info, _, output_path) = self.node_to_path_info(name, path, ca, root_node).await?; let _path_info = self.path_info_service.as_ref().put(path_info).await?; @@ -426,7 +445,7 @@ impl EvalIO for TvixStoreIO { { if self .tokio_handle - .block_on(self.store_path_to_node(&store_path, &sub_path))? + .block_on(self.store_path_to_node(&store_path, sub_path))? .is_some() { Ok(true) @@ -448,30 +467,18 @@ impl EvalIO for TvixStoreIO { { if let Some(node) = self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? { // depending on the node type, treat open differently match node { - Node::Directory(_) => { + Node::Directory { .. } => { // This would normally be a io::ErrorKind::IsADirectory (still unstable) Err(io::Error::new( io::ErrorKind::Unsupported, format!("tried to open directory at {:?}", path), )) } - Node::File(file_node) => { - let digest: B3Digest = - file_node.digest.clone().try_into().map_err(|_e| { - error!( - file_node = ?file_node, - "invalid digest" - ); - io::Error::new( - io::ErrorKind::InvalidData, - format!("invalid digest length in file node: {:?}", file_node), - ) - })?; - + Node::File { digest, .. } => { self.tokio_handle.block_on(async { let resp = self.blob_service.as_ref().open_read(&digest).await?; match resp { @@ -493,7 +500,7 @@ impl EvalIO for TvixStoreIO { } }) } - Node::Symlink(_symlink_node) => Err(io::Error::new( + Node::Symlink { .. } => Err(io::Error::new( io::ErrorKind::Unsupported, "open for symlinks is unsupported", ))?, @@ -516,12 +523,12 @@ impl EvalIO for TvixStoreIO { { if let Some(node) = self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? { match node { - Node::Directory(_) => Ok(FileType::Directory), - Node::File(_) => Ok(FileType::Regular), - Node::Symlink(_) => Ok(FileType::Symlink), + Node::Directory { .. } => Ok(FileType::Directory), + Node::File { .. } => Ok(FileType::Regular), + Node::Symlink { .. } => Ok(FileType::Symlink), } } else { self.std_io.file_type(path) @@ -538,31 +545,21 @@ impl EvalIO for TvixStoreIO { { if let Some(node) = self .tokio_handle - .block_on(async { self.store_path_to_node(&store_path, &sub_path).await })? + .block_on(async { self.store_path_to_node(&store_path, sub_path).await })? { match node { - Node::Directory(directory_node) => { + Node::Directory { digest, .. } => { // fetch the Directory itself. - let digest: B3Digest = - directory_node.digest.clone().try_into().map_err(|_e| { - io::Error::new( - io::ErrorKind::InvalidData, - format!( - "invalid digest length in directory node: {:?}", - directory_node - ), - ) - })?; - - if let Some(directory) = self.tokio_handle.block_on(async { - self.directory_service.as_ref().get(&digest).await + if let Some(directory) = self.tokio_handle.block_on({ + let digest = digest.clone(); + async move { self.directory_service.as_ref().get(&digest).await } })? { let mut children: Vec<(bytes::Bytes, FileType)> = Vec::new(); - for node in directory.nodes() { + for (name, node) in directory.into_nodes() { children.push(match node { - Node::Directory(e) => (e.name, FileType::Directory), - Node::File(e) => (e.name, FileType::Regular), - Node::Symlink(e) => (e.name, FileType::Symlink), + Node::Directory { .. } => (name.into(), FileType::Directory), + Node::File { .. } => (name.clone().into(), FileType::Regular), + Node::Symlink { .. } => (name.into(), FileType::Symlink), }) } Ok(children) @@ -579,14 +576,14 @@ impl EvalIO for TvixStoreIO { ))? } } - Node::File(_file_node) => { + Node::File { .. } => { // This would normally be a io::ErrorKind::NotADirectory (still unstable) Err(io::Error::new( io::ErrorKind::Unsupported, "tried to readdir path {:?}, which is a file", ))? } - Node::Symlink(_symlink_node) => Err(io::Error::new( + Node::Symlink { .. } => Err(io::Error::new( io::ErrorKind::Unsupported, "read_dir for symlinks is unsupported", ))?, diff --git a/tvix/nar-bridge/Cargo.toml b/tvix/nar-bridge/Cargo.toml index ba5f21ee6021..6ca0479a9a81 100644 --- a/tvix/nar-bridge/Cargo.toml +++ b/tvix/nar-bridge/Cargo.toml @@ -4,43 +4,43 @@ version = "0.1.0" edition = "2021" [dependencies] -axum = { version = "0.7.5", features = ["http2"] } -tower = "0.4.13" -tower-http = { version = "0.5", features = ["trace"] } -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -data-encoding = "2.3.3" -futures = "0.3.30" -itertools = "0.12.0" -prost = "0.13.1" +axum = { workspace = true, features = ["http2"] } +tower = { workspace = true } +tower-http = { workspace = true, features = ["trace"] } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +data-encoding = { workspace = true } +futures = { workspace = true } +itertools = { workspace = true } +prost = { workspace = true } nix-compat = { path = "../nix-compat", features = ["async"] } -thiserror = "1.0.56" -tokio = { version = "1.32.0" } -tokio-listener = { version = "0.4.2", features = [ "axum07", "clap", "multi-listener", "sd_listen" ] } -tokio-util = { version = "0.7.9", features = ["io", "io-util", "compat"] } -tonic = { version = "0.12.0", features = ["tls", "tls-roots"] } +thiserror = { workspace = true } +tokio = { workspace = true } +tokio-listener = { workspace = true, features = ["axum07", "clap", "multi-listener", "sd_listen"] } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } tvix-castore = { path = "../castore" } tvix-store = { path = "../store" } tvix-tracing = { path = "../tracing", features = ["tonic", "axum"] } -tracing = "0.1.37" -tracing-subscriber = "0.3.16" -url = "2.4.0" -serde = { version = "1.0.204", features = ["derive"] } -lru = "0.12.3" -parking_lot = "0.12.3" -mimalloc = "0.1.43" +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +url = { workspace = true } +serde = { workspace = true, features = ["derive"] } +lru = { workspace = true } +parking_lot = { workspace = true } +mimalloc = { workspace = true } [build-dependencies] -prost-build = "0.13.1" -tonic-build = "0.12.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [features] default = ["otlp"] otlp = ["tvix-tracing/otlp"] [dev-dependencies] -hex-literal = "0.4.1" -rstest = "0.19.0" +hex-literal = { workspace = true } +rstest = { workspace = true } [lints] workspace = true diff --git a/tvix/nar-bridge/default.nix b/tvix/nar-bridge/default.nix index 3e116a1fc02b..2f1384e8211f 100644 --- a/tvix/nar-bridge/default.nix +++ b/tvix/nar-bridge/default.nix @@ -4,7 +4,7 @@ runTests = true; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = (depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "otlp" ]; }); diff --git a/tvix/nar-bridge/src/lib.rs b/tvix/nar-bridge/src/lib.rs index 2f3dd82439b1..79f9b7372245 100644 --- a/tvix/nar-bridge/src/lib.rs +++ b/tvix/nar-bridge/src/lib.rs @@ -1,13 +1,15 @@ use axum::http::StatusCode; +use axum::response::IntoResponse; use axum::routing::{head, put}; use axum::{routing::get, Router}; use lru::LruCache; +use nix_compat::nix_http; use parking_lot::RwLock; use std::num::NonZeroUsize; use std::sync::Arc; use tvix_castore::blobservice::BlobService; use tvix_castore::directoryservice::DirectoryService; -use tvix_castore::proto::node::Node; +use tvix_castore::Node; use tvix_store::pathinfoservice::PathInfoService; mod nar; @@ -71,9 +73,12 @@ async fn four_o_four() -> Result<(), StatusCode> { Err(StatusCode::NOT_FOUND) } -async fn nix_cache_info(priority: u64) -> String { - format!( - "StoreDir: /nix/store\nWantMassQuery: 1\nPriority: {}\n", - priority +async fn nix_cache_info(priority: u64) -> impl IntoResponse { + ( + [("Content-Type", nix_http::MIME_TYPE_CACHE_INFO)], + format!( + "StoreDir: /nix/store\nWantMassQuery: 1\nPriority: {}\n", + priority + ), ) } diff --git a/tvix/nar-bridge/src/nar.rs b/tvix/nar-bridge/src/nar.rs index 9ee27c7df5ca..70d9d644c26c 100644 --- a/tvix/nar-bridge/src/nar.rs +++ b/tvix/nar-bridge/src/nar.rs @@ -5,7 +5,7 @@ use axum::response::Response; use bytes::Bytes; use data_encoding::BASE64URL_NOPAD; use futures::TryStreamExt; -use nix_compat::nixbase32; +use nix_compat::{nix_http, nixbase32}; use serde::Deserialize; use std::io; use tokio_util::io::ReaderStream; @@ -46,25 +46,21 @@ pub async fn get( } // parse the proto - let mut root_node: tvix_castore::proto::Node = Message::decode(Bytes::from(root_node_proto)) + let root_node: tvix_castore::proto::Node = Message::decode(Bytes::from(root_node_proto)) .map_err(|e| { warn!(err=%e, "unable to decode root node proto"); StatusCode::NOT_FOUND })?; - // validate the node, but add a dummy node name, as we only send unnamed - // nodes - if let Some(rn) = root_node.node { - root_node.node = Some(rn.rename("00000000000000000000000000000000-dummy".into())) - } + let (root_name, root_node) = root_node.into_name_and_node().map_err(|e| { + warn!(err=%e, "root node validation failed"); + StatusCode::BAD_REQUEST + })?; - let root_node = root_node - .validate() - .map_err(|e| { - warn!(err=%e, "root node validation failed"); - StatusCode::BAD_REQUEST - })? - .to_owned(); + if !root_name.as_ref().is_empty() { + warn!("root node has name, which it shouldn't"); + return Err(StatusCode::BAD_REQUEST); + } let (w, r) = tokio::io::duplex(1024 * 8); @@ -81,6 +77,7 @@ pub async fn get( .status(StatusCode::OK) .header("cache-control", "max-age=31536000, immutable") .header("content-length", nar_size) + .header("content-type", nix_http::MIME_TYPE_NAR) .body(Body::from_stream(ReaderStream::new(r))) .unwrap()) } @@ -96,7 +93,14 @@ pub async fn put( }): axum::extract::State<AppState>, request: axum::extract::Request, ) -> Result<&'static str, StatusCode> { - let nar_hash_expected = parse_nar_str(&nar_str)?; + let (nar_hash_expected, compression_suffix) = + nix_http::parse_nar_str(&nar_str).ok_or(StatusCode::UNAUTHORIZED)?; + + // No paths with compression suffix are supported. + if !compression_suffix.is_empty() { + warn!(%compression_suffix, "invalid compression suffix requested"); + return Err(StatusCode::UNAUTHORIZED); + } let s = request.into_body().into_data_stream(); @@ -137,54 +141,3 @@ pub async fn put( // FUTUREWORK: maybe head by narhash. Though not too critical, as we do // implement HEAD for .narinfo. - -/// Parses a `14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar` -/// string and returns the nixbase32-decoded digest. -/// No compression is supported. -fn parse_nar_str(s: &str) -> Result<[u8; 32], StatusCode> { - if !s.is_char_boundary(52) { - warn!("invalid string, no char boundary at 32"); - return Err(StatusCode::NOT_FOUND); - } - - Ok(match s.split_at(52) { - (hash_str, ".nar") => { - // we know this is 52 bytes - let hash_str_fixed: [u8; 52] = hash_str.as_bytes().try_into().unwrap(); - nixbase32::decode_fixed(hash_str_fixed).map_err(|e| { - warn!(err=%e, "invalid digest"); - StatusCode::NOT_FOUND - })? - } - _ => { - warn!("invalid string"); - return Err(StatusCode::BAD_REQUEST); - } - }) -} - -#[cfg(test)] -mod test { - use super::parse_nar_str; - use hex_literal::hex; - - #[test] - fn success() { - assert_eq!( - hex!("13a8cf7ca57f68a9f1752acee36a72a55187d3a954443c112818926f26109d91"), - parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar").unwrap() - ) - } - - #[test] - fn failure() { - assert!( - parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar.x").is_err() - ); - assert!( - parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar.xz").is_err() - ); - assert!(parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0").is_err()); - assert!(parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0🦊.nar").is_err()) - } -} diff --git a/tvix/nar-bridge/src/narinfo.rs b/tvix/nar-bridge/src/narinfo.rs index 4706be64d5b4..fc90f0b86629 100644 --- a/tvix/nar-bridge/src/narinfo.rs +++ b/tvix/nar-bridge/src/narinfo.rs @@ -1,8 +1,9 @@ -use axum::http::StatusCode; +use axum::{http::StatusCode, response::IntoResponse}; use bytes::Bytes; -use nix_compat::{narinfo::NarInfo, nixbase32}; +use nix_compat::{narinfo::NarInfo, nix_http, nixbase32}; +use prost::Message; use tracing::{instrument, warn, Span}; -use tvix_castore::proto::{self as castorepb, node::Node}; +use tvix_castore::proto::{self as castorepb}; use tvix_store::proto::PathInfo; use crate::AppState; @@ -16,8 +17,8 @@ pub async fn head( axum::extract::State(AppState { path_info_service, .. }): axum::extract::State<AppState>, -) -> Result<&'static str, StatusCode> { - let digest = parse_narinfo_str(&narinfo_str)?; +) -> Result<impl IntoResponse, StatusCode> { + let digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::NOT_FOUND)?; Span::current().record("path_info.digest", &narinfo_str[0..32]); if path_info_service @@ -29,7 +30,7 @@ pub async fn head( })? .is_some() { - Ok("") + Ok(([("content-type", nix_http::MIME_TYPE_NARINFO)], "")) } else { warn!("PathInfo not found"); Err(StatusCode::NOT_FOUND) @@ -42,8 +43,8 @@ pub async fn get( axum::extract::State(AppState { path_info_service, .. }): axum::extract::State<AppState>, -) -> Result<String, StatusCode> { - let digest = parse_narinfo_str(&narinfo_str)?; +) -> Result<impl IntoResponse, StatusCode> { + let digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::NOT_FOUND)?; Span::current().record("path_info.digest", &narinfo_str[0..32]); // fetch the PathInfo @@ -61,32 +62,36 @@ pub async fn get( StatusCode::INTERNAL_SERVER_ERROR })?; - let mut narinfo = path_info.to_narinfo(store_path).ok_or_else(|| { + let mut narinfo = path_info.to_narinfo(store_path.as_ref()).ok_or_else(|| { warn!(path_info=?path_info, "PathInfo contained no NAR data"); StatusCode::INTERNAL_SERVER_ERROR })?; // encode the (unnamed) root node in the NAR url itself. - let root_node = path_info + // We strip the name from the proto node before sending it out. + // It's not needed to render the NAR, it'll make the URL shorter, and it + // will make caching these requests easier. + let (_, root_node) = path_info .node .as_ref() - .and_then(|n| n.node.as_ref()) - .expect("root node must not be none") - .clone() - .rename("".into()); - - let mut buf = Vec::new(); - Node::encode(&root_node, &mut buf); + .expect("invalid pathinfo") + .to_owned() + .into_name_and_node() + .expect("invalid pathinfo"); let url = format!( "nar/tvix-castore/{}?narsize={}", - data_encoding::BASE64URL_NOPAD.encode(&buf), + data_encoding::BASE64URL_NOPAD + .encode(&castorepb::Node::from_name_and_node("".into(), root_node).encode_to_vec()), narinfo.nar_size, ); narinfo.url = &url; - Ok(narinfo.to_string()) + Ok(( + [("content-type", nix_http::MIME_TYPE_NARINFO)], + narinfo.to_string(), + )) } #[instrument(skip(path_info_service, root_nodes, request))] @@ -99,7 +104,7 @@ pub async fn put( }): axum::extract::State<AppState>, request: axum::extract::Request, ) -> Result<&'static str, StatusCode> { - let _narinfo_digest = parse_narinfo_str(&narinfo_str)?; + let _narinfo_digest = nix_http::parse_narinfo_str(&narinfo_str).ok_or(StatusCode::UNAUTHORIZED); Span::current().record("path_info.digest", &narinfo_str[0..32]); let narinfo_bytes: Bytes = axum::body::to_bytes(request.into_body(), NARINFO_LIMIT) @@ -128,19 +133,18 @@ pub async fn put( // Lookup root node with peek, as we don't want to update the LRU list. // We need to be careful to not hold the RwLock across the await point. - let maybe_root_node = root_nodes - .read() - .peek(&narinfo.nar_hash) - .map(|v| v.to_owned()); + let maybe_root_node: Option<tvix_castore::Node> = + root_nodes.read().peek(&narinfo.nar_hash).cloned(); match maybe_root_node { Some(root_node) => { // Set the root node from the lookup. // We need to rename the node to the narinfo storepath basename, as // that's where it's stored in PathInfo. - pathinfo.node = Some(castorepb::Node { - node: Some(root_node.rename(narinfo.store_path.to_string().into())), - }); + pathinfo.node = Some(castorepb::Node::from_name_and_node( + narinfo.store_path.to_string().into(), + root_node, + )); // Persist the PathInfo. path_info_service.put(pathinfo).await.map_err(|e| { @@ -156,49 +160,3 @@ pub async fn put( } } } - -/// Parses a `3mzh8lvgbynm9daj7c82k2sfsfhrsfsy.narinfo` string and returns the -/// nixbase32-decoded digest. -fn parse_narinfo_str(s: &str) -> Result<[u8; 20], StatusCode> { - if !s.is_char_boundary(32) { - warn!("invalid string, no char boundary at 32"); - return Err(StatusCode::NOT_FOUND); - } - - Ok(match s.split_at(32) { - (hash_str, ".narinfo") => { - // we know this is 32 bytes - let hash_str_fixed: [u8; 32] = hash_str.as_bytes().try_into().unwrap(); - nixbase32::decode_fixed(hash_str_fixed).map_err(|e| { - warn!(err=%e, "invalid digest"); - StatusCode::NOT_FOUND - })? - } - _ => { - warn!("invalid string"); - return Err(StatusCode::NOT_FOUND); - } - }) -} - -#[cfg(test)] -mod test { - use super::parse_narinfo_str; - use hex_literal::hex; - - #[test] - fn success() { - assert_eq!( - hex!("8a12321522fd91efbd60ebb2481af88580f61600"), - parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la.narinfo").unwrap() - ); - } - - #[test] - fn failure() { - assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la").is_err()); - assert!(parse_narinfo_str("/00bgd045z0d4icpbc2yyz4gx48ak44la").is_err()); - assert!(parse_narinfo_str("000000").is_err()); - assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44l🦊.narinfo").is_err()); - } -} diff --git a/tvix/nix-compat-derive-tests/Cargo.toml b/tvix/nix-compat-derive-tests/Cargo.toml new file mode 100644 index 000000000000..e69cb10e4fea --- /dev/null +++ b/tvix/nix-compat-derive-tests/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nix-compat-derive-tests" +version = "0.1.0" +edition = "2021" + +[features] +compile-tests = [] + +[dev-dependencies] +hex-literal = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tokio-test = { workspace = true } +trybuild = { workspace = true } +tokio = { workspace = true, features = ["io-util", "macros"] } + +[dev-dependencies.nix-compat] +version = "0.1.0" +path = "../nix-compat" +features = ["test", "wire"] + +[dev-dependencies.nix-compat-derive] +version = "0.1.0" +path = "../nix-compat-derive" diff --git a/tvix/nix-compat-derive-tests/default.nix b/tvix/nix-compat-derive-tests/default.nix new file mode 100644 index 000000000000..cabe9ad13780 --- /dev/null +++ b/tvix/nix-compat-derive-tests/default.nix @@ -0,0 +1,5 @@ +{ depot, ... }: + +depot.tvix.crates.workspaceMembers.nix-compat-derive-tests.build.override { + runTests = true; +} diff --git a/tvix/nix-compat-derive-tests/tests/read_derive.rs b/tvix/nix-compat-derive-tests/tests/read_derive.rs new file mode 100644 index 000000000000..055d70cf046e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/read_derive.rs @@ -0,0 +1,417 @@ +use std::str::FromStr; + +use nix_compat::nix_daemon::de::mock::{Builder, Error}; +use nix_compat::nix_daemon::de::NixRead; +use nix_compat_derive::NixDeserialize; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct UnitTest; + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct EmptyTupleTest(); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructTest { + first: u64, + second: String, +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleTest(u64, String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct StructVersionTest { + test: u64, + #[nix(version = "20..")] + hello: String, +} + +fn default_test() -> StructVersionTest { + StructVersionTest { + test: 89, + hello: String::from("klomp"), + } +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionTest(u64, #[nix(version = "25..")] String); + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +pub struct TupleVersionDefaultTest( + u64, + #[nix(version = "..25", default = "default_test")] StructVersionTest, +); + +#[tokio::test] +async fn read_unit() { + let mut mock = Builder::new().build(); + let v: UnitTest = mock.read_value().await.unwrap(); + assert_eq!(UnitTest, v); +} + +#[tokio::test] +async fn read_empty_tuple() { + let mut mock = Builder::new().build(); + let v: EmptyTupleTest = mock.read_value().await.unwrap(); + assert_eq!(EmptyTupleTest(), v); +} + +#[tokio::test] +async fn read_struct() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: StructTest = mock.read_value().await.unwrap(); + assert_eq!( + StructTest { + first: 89, + second: String::from("klomp"), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple() { + let mut mock = Builder::new().read_number(89).read_slice(b"klomp").build(); + let v: TupleTest = mock.read_value().await.unwrap(); + assert_eq!(TupleTest(89, String::from("klomp")), v); +} + +#[tokio::test] +async fn read_struct_version() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!(default_test(), v); +} + +#[tokio::test] +async fn read_struct_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: StructVersionTest = mock.read_value().await.unwrap(); + assert_eq!( + StructVersionTest { + test: 89, + hello: String::new(), + }, + v + ); +} + +#[tokio::test] +async fn read_tuple_version() { + let mut mock = Builder::new() + .version((1, 26)) + .read_number(89) + .read_slice(b"klomp") + .build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, "klomp".into()), v); +} + +#[tokio::test] +async fn read_tuple_without_version() { + let mut mock = Builder::new().version((1, 19)).read_number(89).build(); + let v: TupleVersionTest = mock.read_value().await.unwrap(); + assert_eq!(TupleVersionTest(89, String::new()), v); +} + +#[tokio::test] +async fn read_complex_1() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number(999) + .read_number(666) + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::new() + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_2() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(999) + .read_number(666) + .read_slice(b"The quick brown \xF0\x9F\xA6\x8A jumps over 13 lazy \xF0\x9F\x90\xB6.") + .build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 666, + hello: String::from("The quick brown 🦊 jumps over 13 lazy 🐶.") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_3() { + let mut mock = Builder::new().version((1, 25)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_complex_4() { + let mut mock = Builder::new().version((1, 26)).read_number(999).build(); + let v: TupleVersionDefaultTest = mock.read_value().await.unwrap(); + assert_eq!( + TupleVersionDefaultTest( + 999, + StructVersionTest { + test: 89, + hello: String::from("klomp") + } + ), + v + ); +} + +#[tokio::test] +async fn read_field_invalid_data() { + let mut mock = Builder::new() + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_field_missing_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_no_data() { + let mut mock = Builder::new().build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::MissingData("unexpected end-of-file".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_first() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_field_reader_error_later() { + let mut mock = Builder::new() + .read_number(999) + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<StructTest>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from_str)] +struct TestFromStr; + +impl FromStr for TestFromStr { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(TestFromStr) + } else { + Err(s.into()) + } + } +} + +#[tokio::test] +async fn read_from_str() { + let mut mock = Builder::new().read_slice(b"test").build(); + let value = mock.read_value::<TestFromStr>().await.unwrap(); + assert_eq!(TestFromStr, value); +} + +#[tokio::test] +async fn read_from_str_invalid_data() { + let mut mock = Builder::new().read_slice(b"wrong string").build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("wrong string".into()), err); +} + +#[tokio::test] +async fn read_from_str_invalid_string() { + let mut mock = Builder::new() + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} + +#[tokio::test] +async fn read_from_str_reader_error() { + let mut mock = Builder::new() + .read_bytes_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromStr>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(try_from = "u64")] +struct TestTryFromU64; + +impl TryFrom<u64> for TestTryFromU64 { + type Error = u64; + + fn try_from(value: u64) -> Result<TestTryFromU64, Self::Error> { + if value == 42 { + Ok(TestTryFromU64) + } else { + Err(value) + } + } +} + +#[tokio::test] +async fn read_try_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestTryFromU64>().await.unwrap(); + assert_eq!(TestTryFromU64, value); +} + +#[tokio::test] +async fn read_try_from_u64_invalid_data() { + let mut mock = Builder::new().read_number(666).build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_try_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestTryFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +#[nix(from = "u64")] +struct TestFromU64; + +impl From<u64> for TestFromU64 { + fn from(_value: u64) -> TestFromU64 { + TestFromU64 + } +} + +#[tokio::test] +async fn read_from_u64() { + let mut mock = Builder::new().read_number(42).build(); + let value = mock.read_value::<TestFromU64>().await.unwrap(); + assert_eq!(TestFromU64, value); +} + +#[tokio::test] +async fn read_from_u64_reader_error() { + let mut mock = Builder::new() + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestFromU64>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[derive(Debug, PartialEq, Eq, NixDeserialize)] +enum TestEnum { + #[nix(version = "..=19")] + Pre20(TestTryFromU64), + #[nix(version = "20..")] + Post20(StructVersionTest), +} + +#[tokio::test] +async fn read_enum_19() { + let mut mock = Builder::new().version((1, 19)).read_number(42).build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!(TestEnum::Pre20(TestTryFromU64), value); +} + +#[tokio::test] +async fn read_enum_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(42) + .read_slice(b"klomp") + .build(); + let value = mock.read_value::<TestEnum>().await.unwrap(); + assert_eq!( + TestEnum::Post20(StructVersionTest { + test: 42, + hello: "klomp".into(), + }), + value + ); +} + +#[tokio::test] +async fn read_enum_reader_error() { + let mut mock = Builder::new() + .version((1, 19)) + .read_number_error(Error::InvalidData("Bad reader".into())) + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("Bad reader".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_19() { + let mut mock = Builder::new().version((1, 19)).read_number(666).build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!(Error::InvalidData("666".into()), err); +} + +#[tokio::test] +async fn read_enum_invalid_data_20() { + let mut mock = Builder::new() + .version((1, 20)) + .read_number(666) + .read_slice(b"The quick brown \xED\xA0\x80 jumped.") + .build(); + let err = mock.read_value::<TestEnum>().await.unwrap_err(); + assert_eq!( + Error::InvalidData("invalid utf-8 sequence of 1 bytes from index 16".into()), + err + ); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui.rs b/tvix/nix-compat-derive-tests/tests/ui.rs new file mode 100644 index 000000000000..6a7bffeaf832 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui.rs @@ -0,0 +1,6 @@ +#[cfg(feature = "compile-tests")] +#[test] +fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs new file mode 100644 index 000000000000..f77469679999 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.rs @@ -0,0 +1,10 @@ +use nix_compat_derive::NixDeserialize; + +pub struct BadType; + +#[derive(NixDeserialize)] +pub struct Test { + version: BadType, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr new file mode 100644 index 000000000000..12ffdc83c726 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_bad_type.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `BadType: NixDeserialize` is not satisfied + --> tests/ui/deserialize_bad_type.rs:7:14 + | +7 | version: BadType, + | ^^^^^^^ the trait `NixDeserialize` is not implemented for `BadType` + | + = help: the following other types implement trait `NixDeserialize`: + BTreeMap<K, V> + String + Test + Vec<T> + bool + bytes::bytes::Bytes + i64 + u64 + usize +note: required by a bound in `try_read_value` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn try_read_value<V: NixDeserialize>( + | ^^^^^^^^^^^^^^ required by this bound in `NixRead::try_read_value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs new file mode 100644 index 000000000000..ab559f2b81c8 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.rs @@ -0,0 +1,13 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub enum Test { + #[nix(version = "..=10")] + Old, + #[nix(version = "15..=17")] + Legacy, + #[nix(version = "50..")] + NewWay, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr new file mode 100644 index 000000000000..8a46d9439e35 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_enum_non_exaustive.stderr @@ -0,0 +1,8 @@ +error[E0004]: non-exhaustive patterns: `11_u8..=14_u8` and `18_u8..=49_u8` not covered + --> tests/ui/deserialize_enum_non_exaustive.rs:3:10 + | +3 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ patterns `11_u8..=14_u8` and `18_u8..=49_u8` not covered + | + = note: the matched value is of type `u8` + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs new file mode 100644 index 000000000000..913b7c4f7e59 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr new file mode 100644 index 000000000000..0124010cf10c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_missing.stderr @@ -0,0 +1,5 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_from_missing.rs:4:14 + | +4 | #[nix(from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs new file mode 100644 index 000000000000..36cd4b153740 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.rs @@ -0,0 +1,20 @@ +use std::str::FromStr; + +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +impl FromStr for Test { + type Err = (); + fn from_str(s: &str) -> Result<Self, Self::Err> { + if s == "test" { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr new file mode 100644 index 000000000000..8283ed5340f3 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_from_str_error_not_display.rs:6:7 + | +6 | #[nix(from_str)] + | ^^^^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs new file mode 100644 index 000000000000..a959db57e640 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(from_str)] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr new file mode 100644 index 000000000000..f68f588011fc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_from_str_missing.stderr @@ -0,0 +1,16 @@ +error[E0277]: the trait bound `Test: FromStr` is not satisfied + --> tests/ui/deserialize_from_str_missing.rs:4:7 + | +4 | #[nix(from_str)] + | ^^^^^^^^ the trait `FromStr` is not implemented for `Test` + | + = help: the following other types implement trait `FromStr`: + IpAddr + Ipv4Addr + Ipv6Addr + NonZero<i128> + NonZero<i16> + NonZero<i32> + NonZero<i64> + NonZero<i8> + and $N others diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs new file mode 100644 index 000000000000..e9df62845518 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr new file mode 100644 index 000000000000..5cc2f5974e4c --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `Value: Default` is not satisfied + --> tests/ui/deserialize_missing_default.rs:6:10 + | +6 | #[derive(NixDeserialize)] + | ^^^^^^^^^^^^^^ the trait `Default` is not implemented for `Value` + | + = note: this error originates in the derive macro `NixDeserialize` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `Value` with `#[derive(Default)]` + | +4 + #[derive(Default)] +5 | pub struct Value(String); + | diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs new file mode 100644 index 000000000000..4f319c069dca --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.rs @@ -0,0 +1,12 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Value(String); + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = "20..", default = "Value::make_default")] + version: Value, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr new file mode 100644 index 000000000000..bb9af749128d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_missing_default_path.stderr @@ -0,0 +1,8 @@ +error[E0599]: no function or associated item named `make_default` found for struct `Value` in the current scope + --> tests/ui/deserialize_missing_default_path.rs:8:39 + | +4 | pub struct Value(String); + | ---------------- function or associated item `make_default` not found for this struct +... +8 | #[nix(version = "20..", default = "Value::make_default")] + | ^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `Value` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs new file mode 100644 index 000000000000..cc2ab5bfbc11 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.rs @@ -0,0 +1,15 @@ +use nix_compat_derive::nix_deserialize_remote; + +pub struct Value(String); +impl From<String> for Value { + fn from(s: String) -> Value { + Value(s) + } +} + +nix_deserialize_remote!( + #[nix()] + Value +); + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr new file mode 100644 index 000000000000..a1c18adc6e48 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_remote_missing_attr.stderr @@ -0,0 +1,5 @@ +error: Missing from_str, from or try_from attribute + --> tests/ui/deserialize_remote_missing_attr.rs:10:25 + | +10 | nix_deserialize_remote!(#[nix()] Value); + | ^^^^^^^^^^^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs new file mode 100644 index 000000000000..7f8ad6bbfc4e --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.rs @@ -0,0 +1,19 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +impl TryFrom<u64> for Test { + type Error = (); + + fn try_from(value: u64) -> Result<Test, Self::Error> { + if value == 42 { + Ok(Test) + } else { + Err(()) + } + } +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr new file mode 100644 index 000000000000..8e55a3c56189 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_error_not_display.stderr @@ -0,0 +1,13 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> tests/ui/deserialize_try_from_error_not_display.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `invalid_data` + --> $WORKSPACE/nix-compat/src/nix_daemon/de/mod.rs + | + | fn invalid_data<T: fmt::Display>(msg: T) -> Self { + | ^^^^^^^^^^^^ required by this bound in `Error::invalid_data` diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs new file mode 100644 index 000000000000..899095ae3542 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.rs @@ -0,0 +1,7 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +#[nix(try_from = "u64")] +pub struct Test; + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr new file mode 100644 index 000000000000..9605d1f3378f --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/deserialize_try_from_missing.stderr @@ -0,0 +1,8 @@ +error[E0277]: the trait bound `Test: From<u64>` is not satisfied + --> tests/ui/deserialize_try_from_missing.rs:4:18 + | +4 | #[nix(try_from = "u64")] + | ^^^^^ the trait `From<u64>` is not implemented for `Test`, which is required by `Test: TryFrom<u64>` + | + = note: required for `u64` to implement `Into<Test>` + = note: required for `Test` to implement `TryFrom<u64>` diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs new file mode 100644 index 000000000000..d87831cecf51 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr new file mode 100644 index 000000000000..acb1bc2a47bc --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute default to be string + --> tests/ui/parse_bad_default.rs:5:21 + | +5 | #[nix(default = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs new file mode 100644 index 000000000000..fbde8ffbc2b0 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(default = "12")] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr new file mode 100644 index 000000000000..7628d4c83bea --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_default_path.stderr @@ -0,0 +1,5 @@ +error: expected identifier + --> tests/ui/parse_bad_default_path.rs:5:21 + | +5 | #[nix(default = "12")] + | ^^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs new file mode 100644 index 000000000000..690e76a20fe6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr new file mode 100644 index 000000000000..da3d2d9aab47 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_nix.stderr @@ -0,0 +1,5 @@ +error: expected attribute arguments in parentheses: #[nix(...)] + --> tests/ui/parse_bad_nix.rs:5:7 + | +5 | #[nix] + | ^^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs new file mode 100644 index 000000000000..35b3b05c23e1 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version = 12)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr new file mode 100644 index 000000000000..48cc817fac9d --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_bad_version.stderr @@ -0,0 +1,5 @@ +error: expected nix attribute version to be string + --> tests/ui/parse_bad_version.rs:5:21 + | +5 | #[nix(version = 12)] + | ^^ diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs new file mode 100644 index 000000000000..9eaa743ed2b6 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.rs @@ -0,0 +1,9 @@ +use nix_compat_derive::NixDeserialize; + +#[derive(NixDeserialize)] +pub struct Test { + #[nix(version)] + version: u8, +} + +fn main() {} diff --git a/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr new file mode 100644 index 000000000000..79f048e11198 --- /dev/null +++ b/tvix/nix-compat-derive-tests/tests/ui/parse_mising_version.stderr @@ -0,0 +1,5 @@ +error: expected `=` + --> tests/ui/parse_mising_version.rs:5:18 + | +5 | #[nix(version)] + | ^ diff --git a/tvix/nix-compat-derive/Cargo.toml b/tvix/nix-compat-derive/Cargo.toml new file mode 100644 index 000000000000..da6d6744e650 --- /dev/null +++ b/tvix/nix-compat-derive/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "nix-compat-derive" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = { workspace = true, features = ["proc-macro"] } +quote = { workspace = true, features = ["proc-macro"] } +syn = { version = "2.0.76", features = ["full", "extra-traits"] } + +[dev-dependencies] +hex-literal = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +tokio-test = { workspace = true } +tokio = { workspace = true, features = ["io-util", "macros"] } + +[dev-dependencies.nix-compat] +path = "../nix-compat" +default-features = false +features = ["async", "wire", "test"] diff --git a/tvix/nix-compat-derive/default.nix b/tvix/nix-compat-derive/default.nix new file mode 100644 index 000000000000..e6636e7f2510 --- /dev/null +++ b/tvix/nix-compat-derive/default.nix @@ -0,0 +1,5 @@ +{ depot, lib, ... }: + +depot.tvix.crates.workspaceMembers.nix-compat-derive.build.override { + runTests = true; +} diff --git a/tvix/nix-compat-derive/src/de.rs b/tvix/nix-compat-derive/src/de.rs new file mode 100644 index 000000000000..ee79ea9d1012 --- /dev/null +++ b/tvix/nix-compat-derive/src/de.rs @@ -0,0 +1,272 @@ +use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned, ToTokens}; +use syn::spanned::Spanned; +use syn::{DeriveInput, Generics, Path, Type}; + +use crate::internal::attrs::Default; +use crate::internal::inputs::RemoteInput; +use crate::internal::{attrs, Container, Context, Data, Field, Remote, Style, Variant}; + +pub fn expand_nix_deserialize(nnixrs: Path, input: &mut DeriveInput) -> syn::Result<TokenStream> { + let cx = Context::new(); + let cont = Container::from_ast(&cx, nnixrs, input); + cx.check()?; + let cont = cont.unwrap(); + + let ty = cont.ident_type(); + let body = nix_deserialize_body(&cont); + let crate_path = cont.crate_path(); + + Ok(nix_deserialize_impl( + crate_path, + &ty, + &cont.original.generics, + body, + )) +} + +pub fn expand_nix_deserialize_remote( + crate_path: Path, + input: &RemoteInput, +) -> syn::Result<TokenStream> { + let cx = Context::new(); + let remote = Remote::from_ast(&cx, crate_path, input); + cx.check()?; + let remote = remote.unwrap(); + + let crate_path = remote.crate_path(); + let body = nix_deserialize_body_from(crate_path, &remote.attrs).expect("From tokenstream"); + let generics = Generics::default(); + Ok(nix_deserialize_impl(crate_path, remote.ty, &generics, body)) +} + +fn nix_deserialize_impl( + crate_path: &Path, + ty: &Type, + generics: &Generics, + body: TokenStream, +) -> TokenStream { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[automatically_derived] + impl #impl_generics #crate_path::nix_daemon::de::NixDeserialize for #ty #ty_generics + #where_clause + { + #[allow(clippy::manual_async_fn)] + fn try_deserialize<R>(reader: &mut R) -> impl ::std::future::Future<Output=Result<Option<Self>, R::Error>> + Send + '_ + where R: ?Sized + #crate_path::nix_daemon::de::NixRead + Send, + { + #body + } + } + } +} + +fn nix_deserialize_body_from( + crate_path: &syn::Path, + attrs: &attrs::Container, +) -> Option<TokenStream> { + if let Some(span) = attrs.from_str.as_ref() { + Some(nix_deserialize_from_str(crate_path, span.span())) + } else if let Some(type_from) = attrs.type_from.as_ref() { + Some(nix_deserialize_from(type_from)) + } else { + attrs + .type_try_from + .as_ref() + .map(|type_try_from| nix_deserialize_try_from(crate_path, type_try_from)) + } +} + +fn nix_deserialize_body(cont: &Container) -> TokenStream { + if let Some(tokens) = nix_deserialize_body_from(cont.crate_path(), &cont.attrs) { + tokens + } else { + match &cont.data { + Data::Struct(style, fields) => nix_deserialize_struct(*style, fields), + Data::Enum(variants) => nix_deserialize_enum(variants), + } + } +} + +fn nix_deserialize_struct(style: Style, fields: &[Field<'_>]) -> TokenStream { + let read_fields = fields.iter().map(|f| { + let field = f.var_ident(); + let ty = f.ty; + let read_value = quote_spanned! { + ty.span()=> if first__ { + first__ = false; + if let Some(v) = reader.try_read_value::<#ty>().await? { + v + } else { + return Ok(None); + } + } else { + reader.read_value::<#ty>().await? + } + }; + if let Some(version) = f.attrs.version.as_ref() { + let default = match &f.attrs.default { + Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), + Default::Path(path) => path.to_token_stream(), + _ => panic!("No default for versioned field"), + }; + quote! { + let #field : #ty = if (#version).contains(&reader.version().minor()) { + #read_value + } else { + #default() + }; + } + } else { + quote! { + let #field : #ty = #read_value; + } + } + }); + + let field_names = fields.iter().map(|f| f.var_ident()); + let construct = match style { + Style::Struct => { + quote! { + Self { #(#field_names),* } + } + } + Style::Tuple => { + quote! { + Self(#(#field_names),*) + } + } + Style::Unit => quote!(Self), + }; + quote! { + #[allow(unused_assignments)] + async move { + let mut first__ = true; + #(#read_fields)* + Ok(Some(#construct)) + } + } +} + +fn nix_deserialize_variant(variant: &Variant<'_>) -> TokenStream { + let ident = variant.ident; + let read_fields = variant.fields.iter().map(|f| { + let field = f.var_ident(); + let ty = f.ty; + let read_value = quote_spanned! { + ty.span()=> if first__ { + first__ = false; + if let Some(v) = reader.try_read_value::<#ty>().await? { + v + } else { + return Ok(None); + } + } else { + reader.read_value::<#ty>().await? + } + }; + if let Some(version) = f.attrs.version.as_ref() { + let default = match &f.attrs.default { + Default::Default => quote_spanned!(ty.span()=>::std::default::Default::default), + Default::Path(path) => path.to_token_stream(), + _ => panic!("No default for versioned field"), + }; + quote! { + let #field : #ty = if (#version).contains(&reader.version().minor()) { + #read_value + } else { + #default() + }; + } + } else { + quote! { + let #field : #ty = #read_value; + } + } + }); + let field_names = variant.fields.iter().map(|f| f.var_ident()); + let construct = match variant.style { + Style::Struct => { + quote! { + Self::#ident { #(#field_names),* } + } + } + Style::Tuple => { + quote! { + Self::#ident(#(#field_names),*) + } + } + Style::Unit => quote!(Self::#ident), + }; + let version = &variant.attrs.version; + quote! { + #version => { + #(#read_fields)* + Ok(Some(#construct)) + } + } +} + +fn nix_deserialize_enum(variants: &[Variant<'_>]) -> TokenStream { + let match_variant = variants + .iter() + .map(|variant| nix_deserialize_variant(variant)); + quote! { + #[allow(unused_assignments)] + async move { + let mut first__ = true; + match reader.version().minor() { + #(#match_variant)* + } + } + } +} + +fn nix_deserialize_from(ty: &Type) -> TokenStream { + quote_spanned! { + ty.span() => + async move { + if let Some(value) = reader.try_read_value::<#ty>().await? { + Ok(Some(<Self as ::std::convert::From<#ty>>::from(value))) + } else { + Ok(None) + } + } + } +} + +fn nix_deserialize_try_from(crate_path: &Path, ty: &Type) -> TokenStream { + quote_spanned! { + ty.span() => + async move { + use #crate_path::nix_daemon::de::Error; + if let Some(item) = reader.try_read_value::<#ty>().await? { + <Self as ::std::convert::TryFrom<#ty>>::try_from(item) + .map_err(Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } + } +} + +fn nix_deserialize_from_str(crate_path: &Path, span: Span) -> TokenStream { + quote_spanned! { + span => + async move { + use #crate_path::nix_daemon::de::Error; + if let Some(buf) = reader.try_read_bytes().await? { + let s = ::std::str::from_utf8(&buf) + .map_err(Error::invalid_data)?; + <Self as ::std::str::FromStr>::from_str(s) + .map_err(Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } + } +} diff --git a/tvix/nix-compat-derive/src/internal/attrs.rs b/tvix/nix-compat-derive/src/internal/attrs.rs new file mode 100644 index 000000000000..dbc959d1e917 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/attrs.rs @@ -0,0 +1,358 @@ +use quote::ToTokens; +use syn::meta::ParseNestedMeta; +use syn::parse::Parse; +use syn::{parse_quote, Attribute, Expr, ExprLit, ExprPath, Lit, Token}; + +use super::symbol::{Symbol, CRATE, DEFAULT, FROM, FROM_STR, NIX, TRY_FROM, VERSION}; +use super::Context; + +#[derive(Debug, PartialEq, Eq)] +pub enum Default { + None, + #[allow(clippy::enum_variant_names)] + Default, + Path(ExprPath), +} + +impl Default { + pub fn is_none(&self) -> bool { + matches!(self, Default::None) + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Field { + pub default: Default, + pub version: Option<syn::ExprRange>, +} + +impl Field { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Field { + let mut version = None; + let mut default = Default::None; + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == VERSION { + version = parse_lit(ctx, &meta, VERSION)?; + } else if meta.path == DEFAULT { + if meta.input.peek(Token![=]) { + if let Some(path) = parse_lit(ctx, &meta, DEFAULT)? { + default = Default::Path(path); + } + } else { + default = Default::Default; + } + } else { + let path = meta.path.to_token_stream().to_string(); + return Err(meta.error(format_args!("unknown nix field attribute '{}'", path))); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + if version.is_some() && default.is_none() { + default = Default::Default; + } + + Field { default, version } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Variant { + pub version: syn::ExprRange, +} + +impl Variant { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Variant { + let mut version = parse_quote!(..); + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == VERSION { + if let Some(v) = parse_lit(ctx, &meta, VERSION)? { + version = v; + } + } else { + let path = meta.path.to_token_stream().to_string(); + return Err( + meta.error(format_args!("unknown nix variant attribute '{}'", path)) + ); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + + Variant { version } + } +} + +#[derive(Debug, PartialEq, Eq)] +pub struct Container { + pub from_str: Option<syn::Path>, + pub type_from: Option<syn::Type>, + pub type_try_from: Option<syn::Type>, + pub crate_path: Option<syn::Path>, +} + +impl Container { + pub fn from_ast(ctx: &Context, attrs: &Vec<Attribute>) -> Container { + let mut type_from = None; + let mut type_try_from = None; + let mut crate_path = None; + let mut from_str = None; + + for attr in attrs { + if attr.path() != NIX { + continue; + } + if let Err(err) = attr.parse_nested_meta(|meta| { + if meta.path == FROM { + type_from = parse_lit(ctx, &meta, FROM)?; + } else if meta.path == TRY_FROM { + type_try_from = parse_lit(ctx, &meta, TRY_FROM)?; + } else if meta.path == FROM_STR { + from_str = Some(meta.path); + } else if meta.path == CRATE { + crate_path = parse_lit(ctx, &meta, CRATE)?; + } else { + let path = meta.path.to_token_stream().to_string(); + return Err( + meta.error(format_args!("unknown nix variant attribute '{}'", path)) + ); + } + Ok(()) + }) { + eprintln!("{:?}", err.span().source_text()); + ctx.syn_error(err); + } + } + + Container { + from_str, + type_from, + type_try_from, + crate_path, + } + } +} + +pub fn get_lit_str( + ctx: &Context, + meta: &ParseNestedMeta, + attr: Symbol, +) -> syn::Result<Option<syn::LitStr>> { + let expr: Expr = meta.value()?.parse()?; + let mut value = &expr; + while let Expr::Group(e) = value { + value = &e.expr; + } + if let Expr::Lit(ExprLit { + lit: Lit::Str(s), .. + }) = value + { + Ok(Some(s.clone())) + } else { + ctx.error_spanned( + expr, + format_args!("expected nix attribute {} to be string", attr), + ); + Ok(None) + } +} + +pub fn parse_lit<T: Parse>( + ctx: &Context, + meta: &ParseNestedMeta, + attr: Symbol, +) -> syn::Result<Option<T>> { + match get_lit_str(ctx, meta, attr)? { + Some(lit) => Ok(Some(lit.parse()?)), + None => Ok(None), + } +} + +#[cfg(test)] +mod test { + use syn::{parse_quote, Attribute}; + + use crate::internal::Context; + + use super::*; + + #[test] + fn parse_field_version() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(version="..34")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Default, + version: Some(parse_quote!(..34)), + } + ); + } + + #[test] + fn parse_field_default() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(default)])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Default, + version: None, + } + ); + } + + #[test] + fn parse_field_default_path() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(default="Default::default")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: None, + } + ); + } + + #[test] + fn parse_field_both() { + let attrs: Vec<Attribute> = + vec![parse_quote!(#[nix(version="..", default="Default::default")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: Some(parse_quote!(..)), + } + ); + } + + #[test] + fn parse_field_both_rev() { + let attrs: Vec<Attribute> = + vec![parse_quote!(#[nix(default="Default::default", version="..")])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::Path(parse_quote!(Default::default)), + version: Some(parse_quote!(..)), + } + ); + } + + #[test] + fn parse_field_no_attr() { + let attrs: Vec<Attribute> = vec![]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::None, + version: None, + } + ); + } + + #[test] + fn parse_field_no_subattrs() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix()])]; + let ctx = Context::new(); + let field = Field::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + field, + Field { + default: Default::None, + version: None, + } + ); + } + + #[test] + fn parse_variant_version() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(version="..34")])]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..34), + } + ); + } + + #[test] + fn parse_variant_no_attr() { + let attrs: Vec<Attribute> = vec![]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..), + } + ); + } + + #[test] + fn parse_variant_no_subattrs() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix()])]; + let ctx = Context::new(); + let variant = Variant::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + variant, + Variant { + version: parse_quote!(..), + } + ); + } + + #[test] + fn parse_container_try_from() { + let attrs: Vec<Attribute> = vec![parse_quote!(#[nix(try_from="u64")])]; + let ctx = Context::new(); + let container = Container::from_ast(&ctx, &attrs); + ctx.check().unwrap(); + assert_eq!( + container, + Container { + from_str: None, + type_from: None, + type_try_from: Some(parse_quote!(u64)), + crate_path: None, + } + ); + } +} diff --git a/tvix/nix-compat-derive/src/internal/ctx.rs b/tvix/nix-compat-derive/src/internal/ctx.rs new file mode 100644 index 000000000000..ba770e044bc2 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/ctx.rs @@ -0,0 +1,50 @@ +use std::cell::RefCell; +use std::fmt; +use std::thread::panicking; + +use quote::ToTokens; + +pub struct Context { + errors: RefCell<Option<Vec<syn::Error>>>, +} + +impl Context { + pub fn new() -> Context { + Context { + errors: RefCell::new(Some(Vec::new())), + } + } + + pub fn syn_error(&self, error: syn::Error) { + self.errors + .borrow_mut() + .as_mut() + .take() + .unwrap() + .push(error); + } + + pub fn error_spanned<T: ToTokens, D: fmt::Display>(&self, tokens: T, message: D) { + self.syn_error(syn::Error::new_spanned(tokens, message)); + } + + pub fn check(&self) -> syn::Result<()> { + let mut iter = self.errors.borrow_mut().take().unwrap().into_iter(); + let mut err = match iter.next() { + None => return Ok(()), + Some(err) => err, + }; + for next_err in iter { + err.combine(next_err); + } + Err(err) + } +} + +impl Drop for Context { + fn drop(&mut self) { + if self.errors.borrow().is_some() && !panicking() { + panic!("Context dropped without checking errors"); + } + } +} diff --git a/tvix/nix-compat-derive/src/internal/inputs.rs b/tvix/nix-compat-derive/src/internal/inputs.rs new file mode 100644 index 000000000000..097a141a5d7c --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/inputs.rs @@ -0,0 +1,110 @@ +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RemoteInput { + pub attrs: Vec<syn::Attribute>, + pub ident: syn::Type, +} + +impl syn::parse::Parse for RemoteInput { + fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { + let attrs = input.call(syn::Attribute::parse_outer)?; + + let ident = input.parse::<syn::Type>()?; + Ok(RemoteInput { attrs, ident }) + } +} + +impl quote::ToTokens for RemoteInput { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + fn is_outer(attr: &&syn::Attribute) -> bool { + match attr.style { + syn::AttrStyle::Outer => true, + syn::AttrStyle::Inner(_) => false, + } + } + for attr in self.attrs.iter().filter(is_outer) { + attr.to_tokens(tokens); + } + self.ident.to_tokens(tokens); + } +} + +#[cfg(test)] +mod test { + use syn::parse_quote; + //use syn::parse::Parse; + + use super::*; + + #[test] + fn test_input() { + let p: RemoteInput = parse_quote!(u64); + assert_eq!( + p, + RemoteInput { + attrs: vec![], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr() { + let p: RemoteInput = parse_quote!( + #[nix] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix])], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr_multiple() { + let p: RemoteInput = parse_quote!( + #[nix] + #[hello] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix]), parse_quote!(#[hello])], + ident: parse_quote!(u64), + } + ); + } + + #[test] + fn test_input_attr_full() { + let p: RemoteInput = parse_quote!( + #[nix(try_from = "u64")] + usize + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[nix(try_from="u64")])], + ident: parse_quote!(usize), + } + ); + } + + #[test] + fn test_input_attr_other() { + let p: RemoteInput = parse_quote!( + #[muh] + u64 + ); + assert_eq!( + p, + RemoteInput { + attrs: vec![parse_quote!(#[muh])], + ident: parse_quote!(u64), + } + ); + } +} diff --git a/tvix/nix-compat-derive/src/internal/mod.rs b/tvix/nix-compat-derive/src/internal/mod.rs new file mode 100644 index 000000000000..20b243221619 --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/mod.rs @@ -0,0 +1,183 @@ +use syn::punctuated::Punctuated; +use syn::spanned::Spanned; +use syn::Token; + +pub mod attrs; +mod ctx; +pub mod inputs; +mod symbol; + +pub use ctx::Context; + +pub struct Field<'a> { + pub member: syn::Member, + pub ty: &'a syn::Type, + pub attrs: attrs::Field, + pub original: &'a syn::Field, +} + +impl<'a> Field<'a> { + pub fn from_ast(ctx: &Context, idx: usize, field: &'a syn::Field) -> Field<'a> { + let attrs = attrs::Field::from_ast(ctx, &field.attrs); + let member = match &field.ident { + Some(id) => syn::Member::Named(id.clone()), + None => syn::Member::Unnamed(idx.into()), + }; + Field { + member, + attrs, + ty: &field.ty, + original: field, + } + } + + pub fn var_ident(&self) -> syn::Ident { + match &self.member { + syn::Member::Named(name) => name.clone(), + syn::Member::Unnamed(idx) => { + syn::Ident::new(&format!("field{}", idx.index), self.original.span()) + } + } + } +} + +pub struct Variant<'a> { + pub ident: &'a syn::Ident, + pub attrs: attrs::Variant, + pub style: Style, + pub fields: Vec<Field<'a>>, + //pub original: &'a syn::Variant, +} + +impl<'a> Variant<'a> { + pub fn from_ast(ctx: &Context, variant: &'a syn::Variant) -> Self { + let attrs = attrs::Variant::from_ast(ctx, &variant.attrs); + let (style, fields) = match &variant.fields { + syn::Fields::Named(fields) => (Style::Struct, fields_ast(ctx, &fields.named)), + syn::Fields::Unnamed(fields) => (Style::Tuple, fields_ast(ctx, &fields.unnamed)), + syn::Fields::Unit => (Style::Unit, Vec::new()), + }; + Variant { + ident: &variant.ident, + attrs, + style, + fields, + //original: variant, + } + } +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +pub enum Style { + Struct, + Tuple, + Unit, +} + +pub enum Data<'a> { + Enum(Vec<Variant<'a>>), + Struct(Style, Vec<Field<'a>>), +} + +pub struct Container<'a> { + pub ident: &'a syn::Ident, + pub attrs: attrs::Container, + pub data: Data<'a>, + pub crate_path: syn::Path, + pub original: &'a syn::DeriveInput, +} + +impl<'a> Container<'a> { + pub fn from_ast( + ctx: &Context, + crate_path: syn::Path, + input: &'a mut syn::DeriveInput, + ) -> Option<Container<'a>> { + let attrs = attrs::Container::from_ast(ctx, &input.attrs); + let data = match &input.data { + syn::Data::Struct(s) => match &s.fields { + syn::Fields::Named(fields) => { + Data::Struct(Style::Struct, fields_ast(ctx, &fields.named)) + } + syn::Fields::Unnamed(fields) => { + Data::Struct(Style::Tuple, fields_ast(ctx, &fields.unnamed)) + } + syn::Fields::Unit => Data::Struct(Style::Unit, Vec::new()), + }, + syn::Data::Enum(e) => { + let variants = e + .variants + .iter() + .map(|variant| Variant::from_ast(ctx, variant)) + .collect(); + Data::Enum(variants) + } + syn::Data::Union(u) => { + ctx.error_spanned(u.union_token, "Union not supported by nixrs"); + return None; + } + }; + Some(Container { + ident: &input.ident, + attrs, + data, + crate_path, + original: input, + }) + } + + pub fn crate_path(&self) -> &syn::Path { + if let Some(crate_path) = self.attrs.crate_path.as_ref() { + crate_path + } else { + &self.crate_path + } + } + + pub fn ident_type(&self) -> syn::Type { + let path: syn::Path = self.ident.clone().into(); + let tp = syn::TypePath { qself: None, path }; + tp.into() + } +} + +pub struct Remote<'a> { + pub attrs: attrs::Container, + pub ty: &'a syn::Type, + pub crate_path: syn::Path, +} + +impl<'a> Remote<'a> { + pub fn from_ast( + ctx: &Context, + crate_path: syn::Path, + input: &'a inputs::RemoteInput, + ) -> Option<Remote<'a>> { + let attrs = attrs::Container::from_ast(ctx, &input.attrs); + if attrs.from_str.is_none() && attrs.type_from.is_none() && attrs.type_try_from.is_none() { + ctx.error_spanned(input, "Missing from_str, from or try_from attribute"); + return None; + } + Some(Remote { + ty: &input.ident, + attrs, + crate_path, + }) + } + + pub fn crate_path(&self) -> &syn::Path { + if let Some(crate_path) = self.attrs.crate_path.as_ref() { + crate_path + } else { + &self.crate_path + } + } +} + +fn fields_ast<'a>(ctx: &Context, fields: &'a Punctuated<syn::Field, Token![,]>) -> Vec<Field<'a>> { + fields + .iter() + .enumerate() + .map(|(idx, field)| Field::from_ast(ctx, idx, field)) + .collect() +} diff --git a/tvix/nix-compat-derive/src/internal/symbol.rs b/tvix/nix-compat-derive/src/internal/symbol.rs new file mode 100644 index 000000000000..ed3fe304eb5d --- /dev/null +++ b/tvix/nix-compat-derive/src/internal/symbol.rs @@ -0,0 +1,32 @@ +use std::fmt; + +use syn::Path; + +#[derive(Copy, Clone)] +pub struct Symbol(&'static str); + +pub const NIX: Symbol = Symbol("nix"); +pub const VERSION: Symbol = Symbol("version"); +pub const DEFAULT: Symbol = Symbol("default"); +pub const FROM: Symbol = Symbol("from"); +pub const TRY_FROM: Symbol = Symbol("try_from"); +pub const FROM_STR: Symbol = Symbol("from_str"); +pub const CRATE: Symbol = Symbol("crate"); + +impl PartialEq<Symbol> for Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl<'a> PartialEq<Symbol> for &'a Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl fmt::Display for Symbol { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.0) + } +} diff --git a/tvix/nix-compat-derive/src/lib.rs b/tvix/nix-compat-derive/src/lib.rs new file mode 100644 index 000000000000..e3faed02ebab --- /dev/null +++ b/tvix/nix-compat-derive/src/lib.rs @@ -0,0 +1,303 @@ +//! # Using derive +//! +//! 1. [Overview](#overview) +//! 3. [Attributes](#attributes) +//! 1. [Container attributes](#container-attributes) +//! 1. [`#[nix(from_str)]`](#nixfrom_str) +//! 2. [`#[nix(from = "FromType")]`](#nixfrom--fromtype) +//! 3. [`#[nix(try_from = "FromType")]`](#nixtry_from--fromtype) +//! 4. [`#[nix(crate = "...")]`](#nixcrate--) +//! 2. [Variant attributes](#variant-attributes) +//! 1. [`#[nix(version = "range")]`](#nixversion--range) +//! 3. [Field attributes](#field-attributes) +//! 1. [`#[nix(version = "range")]`](#nixversion--range-1) +//! 2. [`#[nix(default)]`](#nixdefault) +//! 3. [`#[nix(default = "path")]`](#nixdefault--path) +//! +//! ## Overview +//! +//! This crate contains derive macros and function-like macros for implementing +//! `NixDeserialize` with less boilerplate. +//! +//! ### Examples +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Unnamed(u64, String); +//! ``` +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Fields { +//! number: u64, +//! message: String, +//! }; +//! ``` +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Ignored; +//! ``` +//! +//! ## Attributes +//! +//! To customize the derived trait implementations you can add +//! [attributes](https://doc.rust-lang.org/reference/attributes.html) +//! to containers, fields and variants. +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(crate="nix_compat")] // <-- This is a container attribute +//! struct Fields { +//! number: u64, +//! #[nix(version="..20")] // <-- This is a field attribute +//! message: String, +//! }; +//! +//! #[derive(NixDeserialize)] +//! #[nix(crate="nix_compat")] // <-- This is also a container attribute +//! enum E { +//! #[nix(version="..=9")] // <-- This is a variant attribute +//! A(u64), +//! #[nix(version="10..")] // <-- This is also a variant attribute +//! B(String), +//! } +//! ``` +//! +//! ### Container attributes +//! +//! ##### `#[nix(from_str)]` +//! +//! When `from_str` is specified the fields are all ignored and instead a +//! `String` is first deserialized and then `FromStr::from_str` is used +//! to convert this `String` to the container type. +//! +//! This means that the container must implement `FromStr` and the error +//! returned from the `from_str` must implement `Display`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(from_str)] +//! struct MyString(String); +//! impl std::str::FromStr for MyString { +//! type Err = String; +//! fn from_str(s: &str) -> Result<Self, Self::Err> { +//! if s != "bad string" { +//! Ok(MyString(s.to_string())) +//! } else { +//! Err("Got a bad string".to_string()) +//! } +//! } +//! } +//! ``` +//! +//! ##### `#[nix(from = "FromType")]` +//! +//! When `from` is specified the fields are all ignored and instead a +//! value of `FromType` is first deserialized and then `From::from` is +//! used to convert from this value to the container type. +//! +//! This means that the container must implement `From<FromType>` and +//! `FromType` must implement `NixDeserialize`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(from="usize")] +//! struct MyValue(usize); +//! impl From<usize> for MyValue { +//! fn from(val: usize) -> Self { +//! MyValue(val) +//! } +//! } +//! ``` +//! +//! ##### `#[nix(try_from = "FromType")]` +//! +//! With `try_from` a value of `FromType` is first deserialized and then +//! `TryFrom::try_from` is used to convert from this value to the container +//! type. +//! +//! This means that the container must implement `TryFrom<FromType>` and +//! `FromType` must implement `NixDeserialize`. +//! The error returned from `try_from` also needs to implement `Display`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! #[nix(try_from="usize")] +//! struct WrongAnswer(usize); +//! impl TryFrom<usize> for WrongAnswer { +//! type Error = String; +//! fn try_from(val: usize) -> Result<Self, Self::Error> { +//! if val != 42 { +//! Ok(WrongAnswer(val)) +//! } else { +//! Err("Got the answer to life the universe and everything".to_string()) +//! } +//! } +//! } +//! ``` +//! +//! ##### `#[nix(crate = "...")]` +//! +//! Specify the path to the `nix-compat` crate instance to use when referring +//! to the API in the generated code. This is usually not needed. +//! +//! ### Variant attributes +//! +//! ##### `#[nix(version = "range")]` +//! +//! Specifies the protocol version range where this variant is used. +//! When deriving an enum the `version` attribute is used to select which +//! variant of the enum to deserialize. The range is for minor version and +//! the version ranges of all variants combined must cover all versions +//! without any overlap or the first variant that matches is selected. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! #[derive(NixDeserialize)] +//! enum Testing { +//! #[nix(version="..=18")] +//! OldVersion(u64), +//! #[nix(version="19..")] +//! NewVersion(String), +//! } +//! ``` +//! +//! ### Field attributes +//! +//! ##### `#[nix(version = "range")]` +//! +//! Specifies the protocol version range where this field is included. +//! The range is for minor version. For example `version = "..20"` +//! includes the field in protocol versions `1.0` to `1.19` and skips +//! it in version `1.20` and above. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20")] +//! messsage: String, +//! } +//! ``` +//! +//! ##### `#[nix(default)]` +//! +//! When a field is skipped because the active protocol version falls +//! outside the range specified in [`#[nix(version = "range")]`](#nixversion--range-1) +//! this attribute indicates that `Default::default()` should be used +//! to get a value for the field. This is also the default +//! when you only specify [`#[nix(version = "range")]`](#nixversion--range-1). +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20", default)] +//! messsage: String, +//! } +//! ``` +//! +//! ##### `#[nix(default = "path")]` +//! +//! When a field is skipped because the active protocol version falls +//! outside the range specified in [`#[nix(version = "range")]`](#nixversion--range-1) +//! this attribute indicates that the function in `path` should be called to +//! get a default value for the field. The given function must be callable +//! as `fn() -> T`. +//! For example `default = "my_value"` would call `my_value()` and `default = +//! "AType::empty"` would call `AType::empty()`. +//! +//! ###### Example +//! +//! ```rust +//! # use nix_compat_derive::NixDeserialize; +//! # +//! #[derive(NixDeserialize)] +//! struct Field { +//! number: u64, +//! #[nix(version="..20", default="missing_string")] +//! messsage: String, +//! } +//! +//! fn missing_string() -> String { +//! "missing string".to_string() +//! } +//! ``` + +use internal::inputs::RemoteInput; +use proc_macro::TokenStream; +use syn::{parse_quote, DeriveInput}; + +mod de; +mod internal; + +#[proc_macro_derive(NixDeserialize, attributes(nix))] +pub fn derive_nix_deserialize(item: TokenStream) -> TokenStream { + let mut input = syn::parse_macro_input!(item as DeriveInput); + let nnixrs: syn::Path = parse_quote!(::nix_compat); + de::expand_nix_deserialize(nnixrs, &mut input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +/// Macro to implement `NixDeserialize` on a type. +/// Sometimes you can't use the deriver to implement `NixDeserialize` +/// (like when dealing with types in Rust standard library) but don't want +/// to implement it yourself. So this macro can be used for those situations +/// where you would derive using `#[nix(from_str)]`, +/// `#[nix(from = "FromType")]` or `#[nix(try_from = "FromType")]` if you +/// could. +/// +/// #### Example +/// +/// ```rust +/// # use nix_compat_derive::nix_deserialize_remote; +/// # +/// struct MyU64(u64); +/// +/// impl From<u64> for MyU64 { +/// fn from(value: u64) -> Self { +/// Self(value) +/// } +/// } +/// +/// nix_deserialize_remote!(#[nix(from="u64")] MyU64); +/// ``` +#[proc_macro] +pub fn nix_deserialize_remote(item: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(item as RemoteInput); + let crate_path = parse_quote!(::nix_compat); + de::expand_nix_deserialize_remote(crate_path, &input) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} diff --git a/tvix/nix-compat/Cargo.toml b/tvix/nix-compat/Cargo.toml index dc77c5cf0ad1..58137e4de2e1 100644 --- a/tvix/nix-compat/Cargo.toml +++ b/tvix/nix-compat/Cargo.toml @@ -7,47 +7,48 @@ edition = "2021" # async NAR writer. Also needs the `wire` feature. async = ["tokio"] # code emitting low-level packets used in the daemon protocol. -wire = ["tokio", "pin-project-lite"] +wire = ["tokio", "pin-project-lite", "bytes"] +test = [] # Enable all features by default. -default = ["async", "wire"] +default = ["async", "wire", "nix-compat-derive"] [dependencies] -bitflags = "2.4.1" -bstr = { version = "1.6.0", features = ["alloc", "unicode", "serde"] } -data-encoding = "2.6.0" -ed25519 = "2.2.3" -ed25519-dalek = "2.1.0" -enum-primitive-derive = "0.3.0" -glob = "0.3.0" -mimalloc = "0.1.43" -nom = "7.1.3" -num-traits = "0.2.18" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -sha2 = "0.10.6" -thiserror = "1.0.38" - -[dependencies.tokio] -optional = true -version = "1.32.0" -features = ["io-util", "macros"] - -[dependencies.pin-project-lite] +bitflags = { workspace = true } +bstr = { workspace = true, features = ["alloc", "unicode", "serde"] } +data-encoding = { workspace = true } +ed25519 = { workspace = true } +ed25519-dalek = { workspace = true } +enum-primitive-derive = { workspace = true } +glob = { workspace = true } +mimalloc = { workspace = true } +nom = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +sha2 = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } +bytes = { workspace = true, optional = true } +tokio = { workspace = true, features = ["io-util", "macros"], optional = true } +pin-project-lite = { workspace = true, optional = true } + +[dependencies.nix-compat-derive] +path = "../nix-compat-derive" optional = true -version = "0.2.13" [dev-dependencies] -criterion = { version = "0.5", features = ["html_reports"] } -futures = { version = "0.3.30", default-features = false, features = ["executor"] } -hex-literal = "0.4.1" -lazy_static = "1.4.0" -mimalloc = "0.1.43" -pretty_assertions = "1.4.0" -rstest = "0.19.0" -serde_json = "1.0" -tokio-test = "0.4.3" -zstd = "^0.13.0" +criterion = { workspace = true, features = ["html_reports"] } +futures = { workspace = true } +hex-literal = { workspace = true } +lazy_static = { workspace = true } +mimalloc = { workspace = true } +pretty_assertions = { workspace = true } +rstest = { workspace = true } +serde_json = { workspace = true } +smol_str = { workspace = true } +tokio-test = { workspace = true } +zstd = { workspace = true } [[bench]] name = "derivation_parse_aterm" diff --git a/tvix/nix-compat/default.nix b/tvix/nix-compat/default.nix index 08b053b77dd1..34938e3d6428 100644 --- a/tvix/nix-compat/default.nix +++ b/tvix/nix-compat/default.nix @@ -4,8 +4,8 @@ runTests = true; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "async" "wire" ]; - }; + }); }) diff --git a/tvix/nix-compat/src/aterm/mod.rs b/tvix/nix-compat/src/aterm/mod.rs index 8806b6caf2e5..bb3b77bc7399 100644 --- a/tvix/nix-compat/src/aterm/mod.rs +++ b/tvix/nix-compat/src/aterm/mod.rs @@ -2,6 +2,6 @@ mod escape; mod parser; pub(crate) use escape::escape_bytes; -pub(crate) use parser::parse_bstr_field; -pub(crate) use parser::parse_str_list; +pub(crate) use parser::parse_bytes_field; pub(crate) use parser::parse_string_field; +pub(crate) use parser::parse_string_list; diff --git a/tvix/nix-compat/src/aterm/parser.rs b/tvix/nix-compat/src/aterm/parser.rs index a30cb40ab08d..a570573a8700 100644 --- a/tvix/nix-compat/src/aterm/parser.rs +++ b/tvix/nix-compat/src/aterm/parser.rs @@ -11,8 +11,10 @@ use nom::multi::separated_list0; use nom::sequence::delimited; use nom::IResult; -/// Parse a bstr and undo any escaping. -fn parse_escaped_bstr(i: &[u8]) -> IResult<&[u8], BString> { +/// Parse a bstr and undo any escaping (which is why this needs to allocate). +// FUTUREWORK: have a version for fields that are known to not need escaping +// (like store paths), and use &str. +fn parse_escaped_bytes(i: &[u8]) -> IResult<&[u8], BString> { escaped_transform( is_not("\"\\"), '\\', @@ -29,14 +31,14 @@ fn parse_escaped_bstr(i: &[u8]) -> IResult<&[u8], BString> { /// Parse a field in double quotes, undo any escaping, and return the unquoted /// and decoded `Vec<u8>`. -pub(crate) fn parse_bstr_field(i: &[u8]) -> IResult<&[u8], BString> { +pub(crate) fn parse_bytes_field(i: &[u8]) -> IResult<&[u8], BString> { // inside double quotes… delimited( nomchar('\"'), // There is alt(( // …either is a bstr after unescaping - parse_escaped_bstr, + parse_escaped_bytes, // …or an empty string. map(tag(b""), |_| BString::default()), )), @@ -45,8 +47,8 @@ pub(crate) fn parse_bstr_field(i: &[u8]) -> IResult<&[u8], BString> { } /// Parse a field in double quotes, undo any escaping, and return the unquoted -/// and decoded string, if it's a valid string. Or fail parsing if the bytes are -/// no valid UTF-8. +/// and decoded [String], if it's valid UTF-8. +/// Or fail parsing if the bytes are no valid UTF-8. pub(crate) fn parse_string_field(i: &[u8]) -> IResult<&[u8], String> { // inside double quotes… delimited( @@ -54,18 +56,18 @@ pub(crate) fn parse_string_field(i: &[u8]) -> IResult<&[u8], String> { // There is alt(( // either is a String after unescaping - nom::combinator::map_opt(parse_escaped_bstr, |escaped_bstr| { - String::from_utf8(escaped_bstr.into()).ok() + nom::combinator::map_opt(parse_escaped_bytes, |escaped_bytes| { + String::from_utf8(escaped_bytes.into()).ok() }), // or an empty string. - map(tag(b""), |_| String::new()), + map(tag(b""), |_| "".to_string()), )), nomchar('\"'), )(i) } -/// Parse a list of of string fields (enclosed in brackets) -pub(crate) fn parse_str_list(i: &[u8]) -> IResult<&[u8], Vec<String>> { +/// Parse a list of string fields (enclosed in brackets) +pub(crate) fn parse_string_list(i: &[u8]) -> IResult<&[u8], Vec<String>> { // inside brackets delimited( nomchar('['), @@ -89,7 +91,7 @@ mod tests { #[case] expected: &[u8], #[case] exp_rest: &[u8], ) { - let (rest, parsed) = super::parse_bstr_field(input).expect("must parse"); + let (rest, parsed) = super::parse_bytes_field(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(expected, parsed); } @@ -118,7 +120,7 @@ mod tests { #[case::empty_list(b"[]", vec![], b"")] #[case::empty_list_with_rest(b"[]blub", vec![], b"blub")] fn parse_list(#[case] input: &[u8], #[case] expected: Vec<String>, #[case] exp_rest: &[u8]) { - let (rest, parsed) = super::parse_str_list(input).expect("must parse"); + let (rest, parsed) = super::parse_string_list(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(expected, parsed); } diff --git a/tvix/nix-compat/src/derivation/mod.rs b/tvix/nix-compat/src/derivation/mod.rs index 6e12e3ea86e6..6baeaba38299 100644 --- a/tvix/nix-compat/src/derivation/mod.rs +++ b/tvix/nix-compat/src/derivation/mod.rs @@ -36,11 +36,11 @@ pub struct Derivation { /// Map from drv path to output names used from this derivation. #[serde(rename = "inputDrvs")] - pub input_derivations: BTreeMap<StorePath, BTreeSet<String>>, + pub input_derivations: BTreeMap<StorePath<String>, BTreeSet<String>>, /// Plain store paths of additional inputs. #[serde(rename = "inputSrcs")] - pub input_sources: BTreeSet<StorePath>, + pub input_sources: BTreeSet<StorePath<String>>, /// Maps output names to Output. pub outputs: BTreeMap<String, Output>, @@ -127,7 +127,10 @@ impl Derivation { /// the `name` with a `.drv` suffix as name, all [Derivation::input_sources] and /// keys of [Derivation::input_derivations] as references, and the ATerm string of /// the [Derivation] as content. - pub fn calculate_derivation_path(&self, name: &str) -> Result<StorePath, DerivationError> { + pub fn calculate_derivation_path( + &self, + name: &str, + ) -> Result<StorePath<String>, DerivationError> { // append .drv to the name let name = &format!("{}.drv", name); @@ -141,7 +144,6 @@ impl Derivation { .collect(); build_text_path(name, self.to_aterm_bytes(), references) - .map(|s| s.to_owned()) .map_err(|_e| DerivationError::InvalidOutputName(name.to_string())) } @@ -210,7 +212,7 @@ impl Derivation { self.input_derivations .iter() .map(|(drv_path, output_names)| { - let hash = fn_lookup_hash_derivation_modulo(&drv_path.into()); + let hash = fn_lookup_hash_derivation_modulo(&drv_path.as_ref()); (hash, output_names.to_owned()) }), diff --git a/tvix/nix-compat/src/derivation/output.rs b/tvix/nix-compat/src/derivation/output.rs index 266617f587f8..0b81ef3c3155 100644 --- a/tvix/nix-compat/src/derivation/output.rs +++ b/tvix/nix-compat/src/derivation/output.rs @@ -1,5 +1,4 @@ use crate::nixhash::CAHash; -use crate::store_path::StorePathRef; use crate::{derivation::OutputError, store_path::StorePath}; use serde::de::Unexpected; use serde::{Deserialize, Serialize}; @@ -10,7 +9,7 @@ use std::borrow::Cow; #[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] pub struct Output { /// Store path of build result. - pub path: Option<StorePath>, + pub path: Option<StorePath<String>>, #[serde(flatten)] pub ca_hash: Option<CAHash>, // we can only represent a subset here. @@ -33,10 +32,10 @@ impl<'de> Deserialize<'de> for Output { &"a string", ))?; - let path = StorePathRef::from_absolute_path(path.as_bytes()) + let path = StorePath::from_absolute_path(path.as_bytes()) .map_err(|_| serde::de::Error::invalid_value(Unexpected::Str(path), &"StorePath"))?; Ok(Self { - path: Some(path.to_owned()), + path: Some(path), ca_hash: CAHash::from_map::<D>(&fields)?, }) } diff --git a/tvix/nix-compat/src/derivation/parse_error.rs b/tvix/nix-compat/src/derivation/parse_error.rs index fc97f1a9883b..f625d9aeb724 100644 --- a/tvix/nix-compat/src/derivation/parse_error.rs +++ b/tvix/nix-compat/src/derivation/parse_error.rs @@ -20,7 +20,7 @@ pub enum ErrorKind { DuplicateInputDerivationOutputName(String, String), #[error("duplicate input source: {0}")] - DuplicateInputSource(StorePath), + DuplicateInputSource(StorePath<String>), #[error("nix hash error: {0}")] NixHashError(nixhash::Error), diff --git a/tvix/nix-compat/src/derivation/parser.rs b/tvix/nix-compat/src/derivation/parser.rs index 2775294960fe..4fff7181ba40 100644 --- a/tvix/nix-compat/src/derivation/parser.rs +++ b/tvix/nix-compat/src/derivation/parser.rs @@ -3,7 +3,6 @@ //! //! [ATerm]: http://program-transformation.org/Tools/ATermFormat.html -use bstr::BString; use nom::bytes::complete::tag; use nom::character::complete::char as nomchar; use nom::combinator::{all_consuming, map_res}; @@ -14,7 +13,7 @@ use thiserror; use crate::derivation::parse_error::{into_nomerror, ErrorKind, NomError, NomResult}; use crate::derivation::{write, CAHash, Derivation, Output}; -use crate::store_path::{self, StorePath, StorePathRef}; +use crate::store_path::{self, StorePath}; use crate::{aterm, nixhash}; #[derive(Debug, thiserror::Error)] @@ -73,7 +72,7 @@ fn parse_output(i: &[u8]) -> NomResult<&[u8], (String, Output)> { terminated(aterm::parse_string_field, nomchar(',')), terminated(aterm::parse_string_field, nomchar(',')), terminated(aterm::parse_string_field, nomchar(',')), - aterm::parse_bstr_field, + aterm::parse_bytes_field, ))(i) .map_err(into_nomerror) }, @@ -102,7 +101,7 @@ fn parse_output(i: &[u8]) -> NomResult<&[u8], (String, Output)> { path: if output_path.is_empty() { None } else { - Some(string_to_store_path(i, output_path)?) + Some(string_to_store_path(i, &output_path)?) }, ca_hash: hash_with_mode, }, @@ -132,12 +131,12 @@ fn parse_outputs(i: &[u8]) -> NomResult<&[u8], BTreeMap<String, Output>> { match res { Ok((rst, outputs_lst)) => { - let mut outputs: BTreeMap<String, Output> = BTreeMap::default(); + let mut outputs = BTreeMap::default(); for (output_name, output) in outputs_lst.into_iter() { if outputs.contains_key(&output_name) { return Err(nom::Err::Failure(NomError { input: i, - code: ErrorKind::DuplicateMapKey(output_name), + code: ErrorKind::DuplicateMapKey(output_name.to_string()), })); } outputs.insert(output_name, output); @@ -149,11 +148,13 @@ fn parse_outputs(i: &[u8]) -> NomResult<&[u8], BTreeMap<String, Output>> { } } -fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTreeSet<String>>> { - let (i, input_derivations_list) = parse_kv::<Vec<String>, _>(aterm::parse_str_list)(i)?; +fn parse_input_derivations( + i: &[u8], +) -> NomResult<&[u8], BTreeMap<StorePath<String>, BTreeSet<String>>> { + let (i, input_derivations_list) = parse_kv(aterm::parse_string_list)(i)?; // This is a HashMap of drv paths to a list of output names. - let mut input_derivations: BTreeMap<StorePath, BTreeSet<String>> = BTreeMap::new(); + let mut input_derivations: BTreeMap<StorePath<String>, BTreeSet<_>> = BTreeMap::new(); for (input_derivation, output_names) in input_derivations_list { let mut new_output_names = BTreeSet::new(); @@ -170,7 +171,7 @@ fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTr new_output_names.insert(output_name); } - let input_derivation: StorePath = string_to_store_path(i, input_derivation)?; + let input_derivation = string_to_store_path(i, input_derivation.as_str())?; input_derivations.insert(input_derivation, new_output_names); } @@ -178,16 +179,16 @@ fn parse_input_derivations(i: &[u8]) -> NomResult<&[u8], BTreeMap<StorePath, BTr Ok((i, input_derivations)) } -fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath>> { - let (i, input_sources_lst) = aterm::parse_str_list(i).map_err(into_nomerror)?; +fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath<String>>> { + let (i, input_sources_lst) = aterm::parse_string_list(i).map_err(into_nomerror)?; let mut input_sources: BTreeSet<_> = BTreeSet::new(); for input_source in input_sources_lst.into_iter() { - let input_source: StorePath = string_to_store_path(i, input_source)?; + let input_source = string_to_store_path(i, input_source.as_str())?; if input_sources.contains(&input_source) { return Err(nom::Err::Failure(NomError { input: i, - code: ErrorKind::DuplicateInputSource(input_source), + code: ErrorKind::DuplicateInputSource(input_source.to_owned()), })); } else { input_sources.insert(input_source); @@ -197,24 +198,27 @@ fn parse_input_sources(i: &[u8]) -> NomResult<&[u8], BTreeSet<StorePath>> { Ok((i, input_sources)) } -fn string_to_store_path( - i: &[u8], - path_str: String, -) -> Result<StorePath, nom::Err<NomError<&[u8]>>> { - #[cfg(debug_assertions)] - let path_str2 = path_str.clone(); - - let path: StorePath = StorePathRef::from_absolute_path(path_str.as_bytes()) - .map_err(|e: store_path::Error| { +fn string_to_store_path<'a, 'i, S>( + i: &'i [u8], + path_str: &'a str, +) -> Result<StorePath<S>, nom::Err<NomError<&'i [u8]>>> +where + S: std::cmp::Eq + + std::fmt::Display + + std::clone::Clone + + std::ops::Deref<Target = str> + + std::convert::From<&'a str>, +{ + let path = + StorePath::from_absolute_path(path_str.as_bytes()).map_err(|e: store_path::Error| { nom::Err::Failure(NomError { input: i, code: e.into(), }) - })? - .to_owned(); + })?; #[cfg(debug_assertions)] - assert_eq!(path_str2, path.to_absolute_path()); + assert_eq!(path_str, path.to_absolute_path()); Ok(path) } @@ -240,9 +244,9 @@ pub fn parse_derivation(i: &[u8]) -> NomResult<&[u8], Derivation> { // // parse builder |i| terminated(aterm::parse_string_field, nomchar(','))(i).map_err(into_nomerror), // // parse arguments - |i| terminated(aterm::parse_str_list, nomchar(','))(i).map_err(into_nomerror), + |i| terminated(aterm::parse_string_list, nomchar(','))(i).map_err(into_nomerror), // parse environment - parse_kv::<BString, _>(aterm::parse_bstr_field), + parse_kv(aterm::parse_bytes_field), )), nomchar(')'), ) @@ -376,11 +380,11 @@ mod tests { }; static ref EXP_AB_MAP: BTreeMap<String, BString> = { let mut b = BTreeMap::new(); - b.insert("a".to_string(), b"1".as_bstr().to_owned()); - b.insert("b".to_string(), b"2".as_bstr().to_owned()); + b.insert("a".to_string(), b"1".into()); + b.insert("b".to_string(), b"2".into()); b }; - static ref EXP_INPUT_DERIVATIONS_SIMPLE: BTreeMap<StorePath, BTreeSet<String>> = { + static ref EXP_INPUT_DERIVATIONS_SIMPLE: BTreeMap<StorePath<String>, BTreeSet<String>> = { let mut b = BTreeMap::new(); b.insert( StorePath::from_bytes(b"8bjm87p310sb7r2r0sg4xrynlvg86j8k-hello-2.12.1.tar.gz.drv") @@ -427,8 +431,8 @@ mod tests { #[case] expected: &BTreeMap<String, BString>, #[case] exp_rest: &[u8], ) { - let (rest, parsed) = super::parse_kv::<BString, _>(crate::aterm::parse_bstr_field)(input) - .expect("must parse"); + let (rest, parsed) = + super::parse_kv(crate::aterm::parse_bytes_field)(input).expect("must parse"); assert_eq!(exp_rest, rest, "expected remainder"); assert_eq!(*expected, parsed); } @@ -437,8 +441,7 @@ mod tests { #[test] fn parse_kv_fail_dup_keys() { let input: &'static [u8] = b"[(\"a\",\"1\"),(\"a\",\"2\")]"; - let e = super::parse_kv::<BString, _>(crate::aterm::parse_bstr_field)(input) - .expect_err("must fail"); + let e = super::parse_kv(crate::aterm::parse_bytes_field)(input).expect_err("must fail"); match e { nom::Err::Failure(e) => { @@ -454,7 +457,7 @@ mod tests { #[case::simple(EXP_INPUT_DERIVATIONS_SIMPLE_ATERM.as_bytes(), &EXP_INPUT_DERIVATIONS_SIMPLE)] fn parse_input_derivations( #[case] input: &'static [u8], - #[case] expected: &BTreeMap<StorePath, BTreeSet<String>>, + #[case] expected: &BTreeMap<StorePath<String>, BTreeSet<String>>, ) { let (rest, parsed) = super::parse_input_derivations(input).expect("must parse"); diff --git a/tvix/nix-compat/src/derivation/write.rs b/tvix/nix-compat/src/derivation/write.rs index 2ff68b6edba8..42dadcd76064 100644 --- a/tvix/nix-compat/src/derivation/write.rs +++ b/tvix/nix-compat/src/derivation/write.rs @@ -6,7 +6,7 @@ use crate::aterm::escape_bytes; use crate::derivation::{ca_kind_prefix, output::Output}; use crate::nixbase32; -use crate::store_path::{StorePath, StorePathRef, STORE_DIR_WITH_SLASH}; +use crate::store_path::{StorePath, STORE_DIR_WITH_SLASH}; use bstr::BString; use data_encoding::HEXLOWER; @@ -34,7 +34,10 @@ pub(crate) trait AtermWriteable { fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()>; } -impl AtermWriteable for StorePathRef<'_> { +impl<S> AtermWriteable for StorePath<S> +where + S: std::cmp::Eq + std::ops::Deref<Target = str>, +{ fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { write_char(writer, QUOTE)?; writer.write_all(STORE_DIR_WITH_SLASH.as_bytes())?; @@ -46,13 +49,6 @@ impl AtermWriteable for StorePathRef<'_> { } } -impl AtermWriteable for StorePath { - fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { - let r: StorePathRef = self.into(); - r.aterm_write(writer) - } -} - impl AtermWriteable for String { fn aterm_write(&self, writer: &mut impl Write) -> std::io::Result<()> { write_field(writer, self, true) @@ -179,7 +175,7 @@ pub(crate) fn write_input_derivations( pub(crate) fn write_input_sources( writer: &mut impl Write, - input_sources: &BTreeSet<StorePath>, + input_sources: &BTreeSet<StorePath<String>>, ) -> Result<(), io::Error> { write_char(writer, BRACKET_OPEN)?; write_array_elements( diff --git a/tvix/nix-compat/src/lib.rs b/tvix/nix-compat/src/lib.rs index cc1ee082be38..f30c557889a8 100644 --- a/tvix/nix-compat/src/lib.rs +++ b/tvix/nix-compat/src/lib.rs @@ -1,7 +1,10 @@ +extern crate self as nix_compat; + pub(crate) mod aterm; pub mod derivation; pub mod nar; pub mod narinfo; +pub mod nix_http; pub mod nixbase32; pub mod nixcpp; pub mod nixhash; @@ -12,7 +15,7 @@ pub mod store_path; pub mod wire; #[cfg(feature = "wire")] -mod nix_daemon; +pub mod nix_daemon; #[cfg(feature = "wire")] pub use nix_daemon::worker_protocol; #[cfg(feature = "wire")] diff --git a/tvix/nix-compat/src/nar/listing/mod.rs b/tvix/nix-compat/src/nar/listing/mod.rs new file mode 100644 index 000000000000..5a9a3b4d3613 --- /dev/null +++ b/tvix/nix-compat/src/nar/listing/mod.rs @@ -0,0 +1,128 @@ +//! Parser for the Nix archive listing format, aka .ls. +//! +//! LS files are produced by the C++ Nix implementation via `write-nar-listing=1` query parameter +//! passed to a store implementation when transferring store paths. +//! +//! Listing files contains metadata about a file and its offset in the corresponding NAR. +//! +//! NOTE: LS entries does not offer any integrity field to validate the retrieved file at the provided +//! offset. Validating the contents is the caller's responsibility. + +use std::{ + collections::HashMap, + path::{Component, Path}, +}; + +use serde::Deserialize; + +#[cfg(test)] +mod test; + +#[derive(Debug, thiserror::Error)] +pub enum ListingError { + // TODO: add an enum of what component was problematic + // reusing `std::path::Component` is not possible as it contains a lifetime. + /// An unsupported path component can be: + /// - either a Windows prefix (`C:\\`, `\\share\\`) + /// - either a parent directory (`..`) + /// - either a root directory (`/`) + #[error("unsupported path component")] + UnsupportedPathComponent, + #[error("invalid encoding for entry component")] + InvalidEncoding, +} + +#[derive(Debug, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum ListingEntry { + Regular { + size: u64, + #[serde(default)] + executable: bool, + #[serde(rename = "narOffset")] + nar_offset: u64, + }, + Directory { + // It's tempting to think that the key should be a `Vec<u8>` + // but Nix does not support that and will fail to emit a listing version 1 for any non-UTF8 + // encodeable string. + entries: HashMap<String, ListingEntry>, + }, + Symlink { + target: String, + }, +} + +impl ListingEntry { + /// Given a relative path without `..` component, this will locate, relative to this entry, a + /// deeper entry. + /// + /// If the path is invalid, a listing error [`ListingError`] will be returned. + /// If the entry cannot be found, `None` will be returned. + pub fn locate<P: AsRef<Path>>(&self, path: P) -> Result<Option<&ListingEntry>, ListingError> { + // We perform a simple DFS on the components of the path + // while rejecting dangerous components, e.g. `..` or `/` + // Files and symlinks are *leaves*, i.e. we return them + let mut cur = self; + for component in path.as_ref().components() { + match component { + Component::CurDir => continue, + Component::RootDir | Component::Prefix(_) | Component::ParentDir => { + return Err(ListingError::UnsupportedPathComponent) + } + Component::Normal(file_or_dir_name) => { + if let Self::Directory { entries } = cur { + // As Nix cannot encode non-UTF8 components in the listing (see comment on + // the `Directory` enum variant), invalid encodings path components are + // errors. + let entry_name = file_or_dir_name + .to_str() + .ok_or(ListingError::InvalidEncoding)?; + + if let Some(new_entry) = entries.get(entry_name) { + cur = new_entry; + } else { + return Ok(None); + } + } else { + return Ok(None); + } + } + } + } + + // By construction, we found the node that corresponds to the path traversal. + Ok(Some(cur)) + } +} + +#[derive(Debug)] +pub struct ListingVersion<const V: u8>; + +#[derive(Debug, thiserror::Error)] +#[error("Invalid version: {0}")] +struct ListingVersionError(u8); + +impl<'de, const V: u8> Deserialize<'de> for ListingVersion<V> { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: serde::Deserializer<'de>, + { + let value = u8::deserialize(deserializer)?; + if value == V { + Ok(ListingVersion::<V>) + } else { + Err(serde::de::Error::custom(ListingVersionError(value))) + } + } +} + +#[derive(Debug, Deserialize)] +#[serde(untagged)] +#[non_exhaustive] +pub enum Listing { + V1 { + root: ListingEntry, + version: ListingVersion<1>, + }, +} diff --git a/tvix/nix-compat/src/nar/listing/test.rs b/tvix/nix-compat/src/nar/listing/test.rs new file mode 100644 index 000000000000..5b2ac3f166fe --- /dev/null +++ b/tvix/nix-compat/src/nar/listing/test.rs @@ -0,0 +1,59 @@ +use std::{collections::HashMap, path::PathBuf, str::FromStr}; + +use crate::nar; + +#[test] +fn weird_paths() { + let root = nar::listing::ListingEntry::Directory { + entries: HashMap::new(), + }; + + root.locate("../../../../etc/passwd") + .expect_err("Failed to reject `../` fragment in a path during traversal"); + + // Gated on Windows as C:\\ is parsed as `Component::Normal(_)` on Linux. + #[cfg(target_os = "windows")] + root.locate("C:\\\\Windows\\System32") + .expect_err("Failed to reject Windows-style prefixes"); + + root.locate("/etc/passwd") + .expect_err("Failed to reject absolute UNIX paths"); +} + +#[test] +fn nixos_release() { + let listing_bytes = include_bytes!("../tests/nixos-release.ls"); + let listing: nar::listing::Listing = serde_json::from_slice(listing_bytes).unwrap(); + + let nar::listing::Listing::V1 { root, .. } = listing; + assert!(matches!(root, nar::listing::ListingEntry::Directory { .. })); + + let build_products = root + .locate(PathBuf::from_str("nix-support/hydra-build-products").unwrap()) + .expect("Failed to locate a known file in a directory") + .expect("File was unexpectedly not found in the listing"); + + assert!(matches!( + build_products, + nar::listing::ListingEntry::Regular { .. } + )); + + let nonexisting_file = root + .locate(PathBuf::from_str("nix-support/does-not-exist").unwrap()) + .expect("Failed to locate an unknown file in a directory"); + + assert!( + nonexisting_file.is_none(), + "Non-existing file was unexpectedly found in the listing" + ); + + let existing_dir = root + .locate(PathBuf::from_str("nix-support").unwrap()) + .expect("Failed to locate a known directory in a directory") + .expect("Directory was expectedly found in the listing"); + + assert!(matches!( + existing_dir, + nar::listing::ListingEntry::Directory { .. } + )); +} diff --git a/tvix/nix-compat/src/nar/mod.rs b/tvix/nix-compat/src/nar/mod.rs index c678d26ffb38..d0e8ee8a412f 100644 --- a/tvix/nix-compat/src/nar/mod.rs +++ b/tvix/nix-compat/src/nar/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod wire; +pub mod listing; pub mod reader; pub mod writer; diff --git a/tvix/nix-compat/src/nar/reader/mod.rs b/tvix/nix-compat/src/nar/reader/mod.rs index 7e9143c8f35f..eef3b10f3c28 100644 --- a/tvix/nix-compat/src/nar/reader/mod.rs +++ b/tvix/nix-compat/src/nar/reader/mod.rs @@ -29,9 +29,11 @@ struct ArchiveReader<'a, 'r> { inner: &'a mut Reader<'r>, /// In debug mode, also track when we need to abandon this archive reader. + /// /// The archive reader must be abandoned when: /// * An error is encountered at any point /// * A file or directory reader is dropped before being read entirely. + /// /// All of these checks vanish in release mode. status: ArchiveReaderStatus<'a>, } diff --git a/tvix/nix-compat/src/nar/tests/nixos-release.ls b/tvix/nix-compat/src/nar/tests/nixos-release.ls new file mode 100644 index 000000000000..9dd350b7cf86 --- /dev/null +++ b/tvix/nix-compat/src/nar/tests/nixos-release.ls @@ -0,0 +1 @@ +{"root":{"entries":{"iso":{"entries":{"nixos-minimal-new-kernel-no-zfs-24.11pre660688.bee6b69aad74-x86_64-linux.iso":{"narOffset":440,"size":1051721728,"type":"regular"}},"type":"directory"},"nix-support":{"entries":{"hydra-build-products":{"narOffset":1051722544,"size":211,"type":"regular"},"system":{"narOffset":1051722944,"size":13,"type":"regular"}},"type":"directory"}},"type":"directory"},"version":1} \ No newline at end of file diff --git a/tvix/nix-compat/src/nar/writer/sync.rs b/tvix/nix-compat/src/nar/writer/sync.rs index 6270129028fa..584b5a7192e5 100644 --- a/tvix/nix-compat/src/nar/writer/sync.rs +++ b/tvix/nix-compat/src/nar/writer/sync.rs @@ -35,11 +35,8 @@ use std::io::{ Write, }; -/// Convenience type alias for types implementing [`Write`]. -pub type Writer<'a> = dyn Write + Send + 'a; - /// Create a new NAR, writing the output to the specified writer. -pub fn open<'a, 'w: 'a>(writer: &'a mut Writer<'w>) -> io::Result<Node<'a, 'w>> { +pub fn open<W: Write>(writer: &mut W) -> io::Result<Node<W>> { let mut node = Node { writer }; node.write(&wire::TOK_NAR)?; Ok(node) @@ -49,11 +46,11 @@ pub fn open<'a, 'w: 'a>(writer: &'a mut Writer<'w>) -> io::Result<Node<'a, 'w>> /// /// A NAR can be thought of as a tree of nodes represented by this type. Each /// node can be a file, a symlink or a directory containing other nodes. -pub struct Node<'a, 'w: 'a> { - writer: &'a mut Writer<'w>, +pub struct Node<'a, W: Write> { + writer: &'a mut W, } -impl<'a, 'w> Node<'a, 'w> { +impl<'a, W: Write> Node<'a, W> { fn write(&mut self, data: &[u8]) -> io::Result<()> { self.writer.write_all(data) } @@ -128,7 +125,7 @@ impl<'a, 'w> Node<'a, 'w> { /// /// It is the caller's responsibility to invoke [`Directory::close`], /// or invalid archives will be produced silently. - pub fn directory(mut self) -> io::Result<Directory<'a, 'w>> { + pub fn directory(mut self) -> io::Result<Directory<'a, W>> { self.write(&wire::TOK_DIR)?; Ok(Directory::new(self)) } @@ -145,13 +142,13 @@ fn into_name(_name: &[u8]) -> Name { } /// Content of a NAR node that represents a directory. -pub struct Directory<'a, 'w> { - node: Node<'a, 'w>, +pub struct Directory<'a, W: Write> { + node: Node<'a, W>, prev_name: Option<Name>, } -impl<'a, 'w> Directory<'a, 'w> { - fn new(node: Node<'a, 'w>) -> Self { +impl<'a, W: Write> Directory<'a, W> { + fn new(node: Node<'a, W>) -> Self { Self { node, prev_name: None, @@ -166,7 +163,7 @@ impl<'a, 'w> Directory<'a, 'w> { /// It is the caller's responsibility to ensure that directory entries are /// written in order of ascending name. If this is not ensured, this method /// may panic or silently produce invalid archives. - pub fn entry(&mut self, name: &[u8]) -> io::Result<Node<'_, 'w>> { + pub fn entry(&mut self, name: &[u8]) -> io::Result<Node<'_, W>> { debug_assert!( name.len() <= wire::MAX_NAME_LEN, "name.len() > {}", diff --git a/tvix/nix-compat/src/narinfo/mod.rs b/tvix/nix-compat/src/narinfo/mod.rs index a77eba200f8d..21aecf80b5a2 100644 --- a/tvix/nix-compat/src/narinfo/mod.rs +++ b/tvix/nix-compat/src/narinfo/mod.rs @@ -32,7 +32,7 @@ mod signing_keys; mod verifying_keys; pub use fingerprint::fingerprint; -pub use signature::{Error as SignatureError, Signature}; +pub use signature::{Error as SignatureError, Signature, SignatureRef}; pub use signing_keys::parse_keypair; pub use signing_keys::{Error as SigningKeyError, SigningKey}; pub use verifying_keys::{Error as VerifyingKeyError, VerifyingKey}; @@ -51,7 +51,7 @@ pub struct NarInfo<'a> { pub references: Vec<StorePathRef<'a>>, // authenticity /// Ed25519 signature over the path fingerprint - pub signatures: Vec<Signature<'a>>, + pub signatures: Vec<SignatureRef<'a>>, /// Content address (for content-defined paths) pub ca: Option<CAHash>, // derivation metadata @@ -246,7 +246,7 @@ impl<'a> NarInfo<'a> { }; } "Sig" => { - let val = Signature::parse(val) + let val = SignatureRef::parse(val) .map_err(|e| Error::UnableToParseSignature(signatures.len(), e))?; signatures.push(val); @@ -578,7 +578,7 @@ CA: fixed:r:sha1:1ak1ymbmsfx7z8kh09jzkr3a4dvkrfjw // ensure the signature is added let new_sig = narinfo.signatures.last().unwrap(); - assert_eq!(signing_key.name(), new_sig.name()); + assert_eq!(signing_key.name(), *new_sig.name()); // verify the new signature against the verifying key let verifying_key = super::VerifyingKey::parse(super::DUMMY_VERIFYING_KEY) diff --git a/tvix/nix-compat/src/narinfo/signature.rs b/tvix/nix-compat/src/narinfo/signature.rs index fd197e771d98..33c49128c2d5 100644 --- a/tvix/nix-compat/src/narinfo/signature.rs +++ b/tvix/nix-compat/src/narinfo/signature.rs @@ -1,21 +1,44 @@ -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + ops::Deref, +}; use data_encoding::BASE64; -use ed25519_dalek::SIGNATURE_LENGTH; use serde::{Deserialize, Serialize}; +const SIGNATURE_LENGTH: usize = std::mem::size_of::<ed25519::SignatureBytes>(); + #[derive(Clone, Debug, Eq, PartialEq)] -pub struct Signature<'a> { - name: &'a str, - bytes: [u8; SIGNATURE_LENGTH], +pub struct Signature<S> { + name: S, + bytes: ed25519::SignatureBytes, } -impl<'a> Signature<'a> { - pub fn new(name: &'a str, bytes: [u8; SIGNATURE_LENGTH]) -> Self { +/// Type alias of a [Signature] using a `&str` as `name` field. +pub type SignatureRef<'a> = Signature<&'a str>; + +/// Represents the signatures that Nix emits. +/// It consists of a name (an identifier for a public key), and an ed25519 +/// signature (64 bytes). +/// It is generic over the string type that's used for the name, and there's +/// [SignatureRef] as a type alias for one containing &str. +impl<S> Signature<S> +where + S: Deref<Target = str>, +{ + /// Constructs a new [Signature] from a name and public key. + pub fn new(name: S, bytes: ed25519::SignatureBytes) -> Self { Self { name, bytes } } - pub fn parse(input: &'a str) -> Result<Self, Error> { + /// Parses a [Signature] from a string containing the name, a colon, and 64 + /// base64-encoded bytes (plus padding). + /// These strings are commonly seen in the `Signature:` field of a NARInfo + /// file. + pub fn parse<'a>(input: &'a str) -> Result<Self, Error> + where + S: From<&'a str>, + { let (name, bytes64) = input.split_once(':').ok_or(Error::MissingSeparator)?; if name.is_empty() @@ -39,14 +62,19 @@ impl<'a> Signature<'a> { Err(_) => return Err(Error::DecodeError(input.to_string())), } - Ok(Signature { name, bytes }) + Ok(Self { + name: name.into(), + bytes, + }) } - pub fn name(&self) -> &'a str { - self.name + /// Returns the name field of the signature. + pub fn name(&self) -> &S { + &self.name } - pub fn bytes(&self) -> &[u8; SIGNATURE_LENGTH] { + /// Returns the 64 bytes of signatures. + pub fn bytes(&self) -> &ed25519::SignatureBytes { &self.bytes } @@ -56,9 +84,21 @@ impl<'a> Signature<'a> { verifying_key.verify_strict(fingerprint, &signature).is_ok() } + + /// Constructs a [SignatureRef] from this signature. + pub fn as_ref(&self) -> SignatureRef<'_> { + SignatureRef { + name: self.name.deref(), + bytes: self.bytes, + } + } } -impl<'de: 'a, 'a> Deserialize<'de> for Signature<'a> { +impl<'a, 'de, S> Deserialize<'de> for Signature<S> +where + S: Deref<Target = str> + From<&'a str>, + 'de: 'a, +{ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>, @@ -70,10 +110,13 @@ impl<'de: 'a, 'a> Deserialize<'de> for Signature<'a> { } } -impl<'a> Serialize for Signature<'a> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> +impl<S: Display> Serialize for Signature<S> +where + S: Deref<Target = str>, +{ + fn serialize<SR>(&self, serializer: SR) -> Result<SR::Ok, SR::Error> where - S: serde::Serializer, + SR: serde::Serializer, { let string: String = self.to_string(); @@ -81,6 +124,15 @@ impl<'a> Serialize for Signature<'a> { } } +impl<S> Display for Signature<S> +where + S: Display, +{ + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + write!(w, "{}:{}", self.name, BASE64.encode(&self.bytes)) + } +} + #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Invalid name: {0}")] @@ -93,12 +145,6 @@ pub enum Error { DecodeError(String), } -impl Display for Signature<'_> { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - write!(w, "{}:{}", self.name, BASE64.encode(&self.bytes)) - } -} - #[cfg(test)] mod test { use data_encoding::BASE64; @@ -143,7 +189,7 @@ mod test { #[case] fp: &str, #[case] expect_valid: bool, ) { - let sig = Signature::parse(sig_str).expect("must parse"); + let sig = Signature::<&str>::parse(sig_str).expect("must parse"); assert_eq!(expect_valid, sig.verify(fp.as_bytes(), verifying_key)); } @@ -158,7 +204,7 @@ mod test { "u01BybwQhyI5H1bW1EIWXssMDhDDIvXOG5uh8Qzgdyjz6U1qg6DHhMAvXZOUStIj6X5t4/ufFgR8i3fjf0bMAw==" )] fn parse_fail(#[case] input: &'static str) { - Signature::parse(input).expect_err("must fail"); + Signature::<&str>::parse(input).expect_err("must fail"); } #[test] @@ -177,8 +223,29 @@ mod test { let serialized = serde_json::to_string(&signature_actual).expect("must serialize"); assert_eq!(signature_str_json, &serialized); - let deserialized: Signature<'_> = + let deserialized: Signature<&str> = serde_json::from_str(signature_str_json).expect("must deserialize"); assert_eq!(&signature_actual, &deserialized); } + + /// Construct a [Signature], using different String types for the name field. + #[test] + fn signature_owned() { + let signature1 = Signature::<String>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + let signature2 = Signature::<smol_str::SmolStr>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + let signature3 = Signature::<&str>::parse("cache.nixos.org-1:TsTTb3WGTZKphvYdBHXwo6weVILmTytUjLB+vcX89fOjjRicCHmKA4RCPMVLkj6TMJ4GMX3HPVWRdD1hkeKZBQ==").expect("must parse"); + + assert!( + signature1.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + assert!( + signature2.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + assert!( + signature3.verify(FINGERPRINT.as_bytes(), &PUB_CACHE_NIXOS_ORG_1), + "must verify" + ); + } } diff --git a/tvix/nix-compat/src/narinfo/signing_keys.rs b/tvix/nix-compat/src/narinfo/signing_keys.rs index e33687bc88f8..cf513b7ba475 100644 --- a/tvix/nix-compat/src/narinfo/signing_keys.rs +++ b/tvix/nix-compat/src/narinfo/signing_keys.rs @@ -7,7 +7,7 @@ use data_encoding::BASE64; use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH}; -use super::{Signature, VerifyingKey}; +use super::{SignatureRef, VerifyingKey}; pub struct SigningKey<S> { name: String, @@ -23,9 +23,9 @@ where Self { name, signing_key } } - /// Signs a fingerprint using the internal signing key, returns the [Signature] - pub(crate) fn sign<'a>(&'a self, fp: &[u8]) -> Signature<'a> { - Signature::new(&self.name, self.signing_key.sign(fp).to_bytes()) + /// Signs a fingerprint using the internal signing key, returns the [SignatureRef] + pub(crate) fn sign<'a>(&'a self, fp: &[u8]) -> SignatureRef<'a> { + SignatureRef::new(&self.name, self.signing_key.sign(fp).to_bytes()) } pub fn name(&self) -> &str { diff --git a/tvix/nix-compat/src/narinfo/verifying_keys.rs b/tvix/nix-compat/src/narinfo/verifying_keys.rs index b8ed2b9531c1..67ef2e3a459c 100644 --- a/tvix/nix-compat/src/narinfo/verifying_keys.rs +++ b/tvix/nix-compat/src/narinfo/verifying_keys.rs @@ -6,7 +6,7 @@ use std::fmt::Display; use data_encoding::BASE64; use ed25519_dalek::PUBLIC_KEY_LENGTH; -use super::Signature; +use super::SignatureRef; /// This represents a ed25519 public key and "name". /// These are normally passed in the `trusted-public-keys` Nix config option, @@ -69,8 +69,8 @@ impl VerifyingKey { /// which means the name in the signature has to match, /// and the signature bytes themselves need to be a valid signature made by /// the signing key identified by [Self::verifying key]. - pub fn verify(&self, fingerprint: &str, signature: &Signature) -> bool { - if self.name() != signature.name() { + pub fn verify(&self, fingerprint: &str, signature: &SignatureRef<'_>) -> bool { + if self.name() != *signature.name() { return false; } @@ -109,7 +109,7 @@ mod test { use ed25519_dalek::PUBLIC_KEY_LENGTH; use rstest::rstest; - use crate::narinfo::Signature; + use crate::narinfo::SignatureRef; use super::VerifyingKey; const FINGERPRINT: &str = "1;/nix/store/syd87l2rxw8cbsxmxl853h0r6pdwhwjr-curl-7.82.0-bin;sha256:1b4sb93wp679q4zx9k1ignby1yna3z7c4c2ri3wphylbc2dwsys0;196040;/nix/store/0jqd0rlxzra1rs38rdxl43yh6rxchgc6-curl-7.82.0,/nix/store/6w8g7njm4mck5dmjxws0z1xnrxvl81xa-glibc-2.34-115,/nix/store/j5jxw3iy7bbz4a57fh9g2xm2gxmyal8h-zlib-1.2.12,/nix/store/yxvjs9drzsphm9pcf42a4byzj1kb9m7k-openssl-1.1.1n"; @@ -146,7 +146,7 @@ mod test { #[case] expected: bool, ) { let pubkey = VerifyingKey::parse(pubkey_str).expect("must parse"); - let signature = Signature::parse(signature_str).expect("must parse"); + let signature = SignatureRef::parse(signature_str).expect("must parse"); assert_eq!(expected, pubkey.verify(fingerprint, &signature)); } diff --git a/tvix/nix-compat/src/nix_daemon/de/bytes.rs b/tvix/nix-compat/src/nix_daemon/de/bytes.rs new file mode 100644 index 000000000000..7daced54eef7 --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/bytes.rs @@ -0,0 +1,70 @@ +use bytes::Bytes; + +use super::{Error, NixDeserialize, NixRead}; + +impl NixDeserialize for Bytes { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + reader.try_read_bytes().await + } +} + +impl NixDeserialize for String { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + if let Some(buf) = reader.try_read_bytes().await? { + String::from_utf8(buf.to_vec()) + .map_err(R::Error::invalid_data) + .map(Some) + } else { + Ok(None) + } + } +} + +#[cfg(test)] +mod test { + use std::io; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixRead, NixReader}; + + #[rstest] + #[case::empty("", &hex!("0000 0000 0000 0000"))] + #[case::one(")", &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two("it", &hex!("0200 0000 0000 0000 6974 0000 0000 0000"))] + #[case::three("tea", &hex!("0300 0000 0000 0000 7465 6100 0000 0000"))] + #[case::four("were", &hex!("0400 0000 0000 0000 7765 7265 0000 0000"))] + #[case::five("where", &hex!("0500 0000 0000 0000 7768 6572 6500 0000"))] + #[case::six("unwrap", &hex!("0600 0000 0000 0000 756E 7772 6170 0000"))] + #[case::seven("where's", &hex!("0700 0000 0000 0000 7768 6572 6527 7300"))] + #[case::aligned("read_tea", &hex!("0800 0000 0000 0000 7265 6164 5F74 6561"))] + #[case::more_bytes("read_tess", &hex!("0900 0000 0000 0000 7265 6164 5F74 6573 7300 0000 0000 0000"))] + #[case::utf8("The quick brown 🦊 jumps over 13 lazy 🐶.", &hex!("2D00 0000 0000 0000 5468 6520 7175 6963 6b20 6272 6f77 6e20 f09f a68a 206a 756d 7073 206f 7665 7220 3133 206c 617a 7920 f09f 90b6 2e00 0000"))] + #[tokio::test] + async fn test_read_string(#[case] expected: &str, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: String = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[tokio::test] + async fn test_read_string_invalid() { + let mock = Builder::new() + .read(&hex!("0300 0000 0000 0000 EDA0 8000 0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_value::<String>().await.unwrap_err().kind() + ); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/collections.rs b/tvix/nix-compat/src/nix_daemon/de/collections.rs new file mode 100644 index 000000000000..cf79f584506a --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/collections.rs @@ -0,0 +1,105 @@ +use std::{collections::BTreeMap, future::Future}; + +use super::{NixDeserialize, NixRead}; + +#[allow(clippy::manual_async_fn)] +impl<T> NixDeserialize for Vec<T> +where + T: NixDeserialize + Send, +{ + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + if let Some(len) = reader.try_read_value::<usize>().await? { + let mut ret = Vec::with_capacity(len); + for _ in 0..len { + ret.push(reader.read_value().await?); + } + Ok(Some(ret)) + } else { + Ok(None) + } + } + } +} + +#[allow(clippy::manual_async_fn)] +impl<K, V> NixDeserialize for BTreeMap<K, V> +where + K: NixDeserialize + Ord + Send, + V: NixDeserialize + Send, +{ + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + if let Some(len) = reader.try_read_value::<usize>().await? { + let mut ret = BTreeMap::new(); + for _ in 0..len { + let key = reader.read_value().await?; + let value = reader.read_value().await?; + ret.insert(key, value); + } + Ok(Some(ret)) + } else { + Ok(None) + } + } + } +} + +#[cfg(test)] +mod test { + use std::collections::BTreeMap; + use std::fmt; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixDeserialize, NixRead, NixReader}; + + #[rstest] + #[case::empty(vec![], &hex!("0000 0000 0000 0000"))] + #[case::one(vec![0x29], &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two(vec![0x7469, 10], &hex!("0200 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] + #[tokio::test] + async fn test_read_small_vec(#[case] expected: Vec<usize>, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: Vec<usize> = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + fn empty_map() -> BTreeMap<usize, u64> { + BTreeMap::new() + } + macro_rules! map { + ($($key:expr => $value:expr),*) => {{ + let mut ret = BTreeMap::new(); + $(ret.insert($key, $value);)* + ret + }}; + } + + #[rstest] + #[case::empty(empty_map(), &hex!("0000 0000 0000 0000"))] + #[case::one(map![0x7469usize => 10u64], &hex!("0100 0000 0000 0000 6974 0000 0000 0000 0A00 0000 0000 0000"))] + #[tokio::test] + async fn test_read_small_btree_map<E>(#[case] expected: E, #[case] data: &[u8]) + where + E: NixDeserialize + PartialEq + fmt::Debug, + { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: E = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/int.rs b/tvix/nix-compat/src/nix_daemon/de/int.rs new file mode 100644 index 000000000000..eecf641cfe99 --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/int.rs @@ -0,0 +1,100 @@ +use super::{Error, NixDeserialize, NixRead}; + +impl NixDeserialize for u64 { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + reader.try_read_number().await + } +} + +impl NixDeserialize for usize { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + if let Some(value) = reader.try_read_number().await? { + value.try_into().map_err(R::Error::invalid_data).map(Some) + } else { + Ok(None) + } + } +} + +impl NixDeserialize for bool { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + Ok(reader.try_read_number().await?.map(|v| v != 0)) + } +} +impl NixDeserialize for i64 { + async fn try_deserialize<R>(reader: &mut R) -> Result<Option<Self>, R::Error> + where + R: ?Sized + NixRead + Send, + { + Ok(reader.try_read_number().await?.map(|v| v as i64)) + } +} + +#[cfg(test)] +mod test { + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use crate::nix_daemon::de::{NixRead, NixReader}; + + #[rstest] + #[case::simple_false(false, &hex!("0000 0000 0000 0000"))] + #[case::simple_true(true, &hex!("0100 0000 0000 0000"))] + #[case::other_true(true, &hex!("1234 5600 0000 0000"))] + #[case::max_true(true, &hex!("FFFF FFFF FFFF FFFF"))] + #[tokio::test] + async fn test_read_bool(#[case] expected: bool, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: bool = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[rstest] + #[case::zero(0, &hex!("0000 0000 0000 0000"))] + #[case::one(1, &hex!("0100 0000 0000 0000"))] + #[case::other(0x563412, &hex!("1234 5600 0000 0000"))] + #[case::max_value(u64::MAX, &hex!("FFFF FFFF FFFF FFFF"))] + #[tokio::test] + async fn test_read_u64(#[case] expected: u64, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: u64 = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + #[rstest] + #[case::zero(0, &hex!("0000 0000 0000 0000"))] + #[case::one(1, &hex!("0100 0000 0000 0000"))] + #[case::other(0x563412, &hex!("1234 5600 0000 0000"))] + #[case::max_value(usize::MAX, &usize::MAX.to_le_bytes())] + #[tokio::test] + async fn test_read_usize(#[case] expected: usize, #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual: usize = reader.read_value().await.unwrap(); + assert_eq!(actual, expected); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_read_usize_overflow() { + let mock = Builder::new().read(&u64::MAX.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/mock.rs b/tvix/nix-compat/src/nix_daemon/de/mock.rs new file mode 100644 index 000000000000..31cc3a4897ba --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/mock.rs @@ -0,0 +1,261 @@ +use std::collections::VecDeque; +use std::fmt; +use std::io; +use std::thread; + +use bytes::Bytes; +use thiserror::Error; + +use crate::nix_daemon::ProtocolVersion; + +use super::NixRead; + +#[derive(Debug, Error, PartialEq, Eq, Clone)] +pub enum Error { + #[error("custom error '{0}'")] + Custom(String), + #[error("invalid data '{0}'")] + InvalidData(String), + #[error("missing data '{0}'")] + MissingData(String), + #[error("IO error {0} '{1}'")] + IO(io::ErrorKind, String), + #[error("wrong read: expected {0} got {1}")] + WrongRead(OperationType, OperationType), +} + +impl Error { + pub fn expected_read_number() -> Error { + Error::WrongRead(OperationType::ReadNumber, OperationType::ReadBytes) + } + + pub fn expected_read_bytes() -> Error { + Error::WrongRead(OperationType::ReadBytes, OperationType::ReadNumber) + } +} + +impl super::Error for Error { + fn custom<T: fmt::Display>(msg: T) -> Self { + Self::Custom(msg.to_string()) + } + + fn io_error(err: std::io::Error) -> Self { + Self::IO(err.kind(), err.to_string()) + } + + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + Self::InvalidData(msg.to_string()) + } + + fn missing_data<T: fmt::Display>(msg: T) -> Self { + Self::MissingData(msg.to_string()) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum OperationType { + ReadNumber, + ReadBytes, +} + +impl fmt::Display for OperationType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::ReadNumber => write!(f, "read_number"), + Self::ReadBytes => write!(f, "read_bytess"), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum Operation { + ReadNumber(Result<u64, Error>), + ReadBytes(Result<Bytes, Error>), +} + +impl From<Operation> for OperationType { + fn from(value: Operation) -> Self { + match value { + Operation::ReadNumber(_) => OperationType::ReadNumber, + Operation::ReadBytes(_) => OperationType::ReadBytes, + } + } +} + +pub struct Builder { + version: ProtocolVersion, + ops: VecDeque<Operation>, +} + +impl Builder { + pub fn new() -> Builder { + Builder { + version: Default::default(), + ops: VecDeque::new(), + } + } + + pub fn version<V: Into<ProtocolVersion>>(&mut self, version: V) -> &mut Self { + self.version = version.into(); + self + } + + pub fn read_number(&mut self, value: u64) -> &mut Self { + self.ops.push_back(Operation::ReadNumber(Ok(value))); + self + } + + pub fn read_number_error(&mut self, err: Error) -> &mut Self { + self.ops.push_back(Operation::ReadNumber(Err(err))); + self + } + + pub fn read_bytes(&mut self, value: Bytes) -> &mut Self { + self.ops.push_back(Operation::ReadBytes(Ok(value))); + self + } + + pub fn read_slice(&mut self, data: &[u8]) -> &mut Self { + let value = Bytes::copy_from_slice(data); + self.ops.push_back(Operation::ReadBytes(Ok(value))); + self + } + + pub fn read_bytes_error(&mut self, err: Error) -> &mut Self { + self.ops.push_back(Operation::ReadBytes(Err(err))); + self + } + + pub fn build(&mut self) -> Mock { + Mock { + version: self.version, + ops: self.ops.clone(), + } + } +} + +impl Default for Builder { + fn default() -> Self { + Self::new() + } +} + +pub struct Mock { + version: ProtocolVersion, + ops: VecDeque<Operation>, +} + +impl NixRead for Mock { + type Error = Error; + + fn version(&self) -> ProtocolVersion { + self.version + } + + async fn try_read_number(&mut self) -> Result<Option<u64>, Self::Error> { + match self.ops.pop_front() { + Some(Operation::ReadNumber(ret)) => ret.map(Some), + Some(Operation::ReadBytes(_)) => Err(Error::expected_read_bytes()), + None => Ok(None), + } + } + + async fn try_read_bytes_limited( + &mut self, + _limit: std::ops::RangeInclusive<usize>, + ) -> Result<Option<Bytes>, Self::Error> { + match self.ops.pop_front() { + Some(Operation::ReadBytes(ret)) => ret.map(Some), + Some(Operation::ReadNumber(_)) => Err(Error::expected_read_number()), + None => Ok(None), + } + } +} + +impl Drop for Mock { + fn drop(&mut self) { + // No need to panic again + if thread::panicking() { + return; + } + if let Some(op) = self.ops.front() { + panic!("reader dropped with {op:?} operation still unread") + } + } +} + +#[cfg(test)] +mod test { + use bytes::Bytes; + use hex_literal::hex; + + use crate::nix_daemon::de::NixRead; + + use super::{Builder, Error}; + + #[tokio::test] + async fn read_slice() { + let mut mock = Builder::new() + .read_number(10) + .read_slice(&[]) + .read_slice(&hex!("0000 1234 5678 9ABC DEFF")) + .build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(&[] as &[u8], &mock.read_bytes().await.unwrap()[..]); + assert_eq!( + &hex!("0000 1234 5678 9ABC DEFF"), + &mock.read_bytes().await.unwrap()[..] + ); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn read_bytes() { + let mut mock = Builder::new() + .read_number(10) + .read_bytes(Bytes::from_static(&[])) + .read_bytes(Bytes::from_static(&hex!("0000 1234 5678 9ABC DEFF"))) + .build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(&[] as &[u8], &mock.read_bytes().await.unwrap()[..]); + assert_eq!( + &hex!("0000 1234 5678 9ABC DEFF"), + &mock.read_bytes().await.unwrap()[..] + ); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn read_number() { + let mut mock = Builder::new().read_number(10).build(); + assert_eq!(10, mock.read_number().await.unwrap()); + assert_eq!(None, mock.try_read_number().await.unwrap()); + assert_eq!(None, mock.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn expect_number() { + let mut mock = Builder::new().read_number(10).build(); + assert_eq!( + Error::expected_read_number(), + mock.read_bytes().await.unwrap_err() + ); + } + + #[tokio::test] + async fn expect_bytes() { + let mut mock = Builder::new().read_slice(&[]).build(); + assert_eq!( + Error::expected_read_bytes(), + mock.read_number().await.unwrap_err() + ); + } + + #[test] + #[should_panic] + fn operations_left() { + let _ = Builder::new().read_number(10).build(); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/mod.rs b/tvix/nix-compat/src/nix_daemon/de/mod.rs new file mode 100644 index 000000000000..f85ccd8fea0e --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/mod.rs @@ -0,0 +1,225 @@ +use std::error::Error as StdError; +use std::future::Future; +use std::ops::RangeInclusive; +use std::{fmt, io}; + +use ::bytes::Bytes; + +use super::ProtocolVersion; + +mod bytes; +mod collections; +mod int; +#[cfg(any(test, feature = "test"))] +pub mod mock; +mod reader; + +pub use reader::{NixReader, NixReaderBuilder}; + +/// Like serde the `Error` trait allows `NixRead` implementations to add +/// custom error handling for `NixDeserialize`. +pub trait Error: Sized + StdError { + /// A totally custom non-specific error. + fn custom<T: fmt::Display>(msg: T) -> Self; + + /// Some kind of std::io::Error occured. + fn io_error(err: std::io::Error) -> Self { + Self::custom(format_args!("There was an I/O error {}", err)) + } + + /// The data read from `NixRead` is invalid. + /// This could be that some bytes were supposed to be valid UFT-8 but weren't. + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + Self::custom(msg) + } + + /// Required data is missing. This is mostly like an EOF + fn missing_data<T: fmt::Display>(msg: T) -> Self { + Self::custom(msg) + } +} + +impl Error for io::Error { + fn custom<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::Other, msg.to_string()) + } + + fn io_error(err: std::io::Error) -> Self { + err + } + + fn invalid_data<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::InvalidData, msg.to_string()) + } + + fn missing_data<T: fmt::Display>(msg: T) -> Self { + io::Error::new(io::ErrorKind::UnexpectedEof, msg.to_string()) + } +} + +/// A reader of data from the Nix daemon protocol. +/// Basically there are two basic types in the Nix daemon protocol +/// u64 and a bytes buffer. Everything else is more or less built on +/// top of these two types. +pub trait NixRead: Send { + type Error: Error + Send; + + /// Some types are serialized differently depending on the version + /// of the protocol and so this can be used for implementing that. + fn version(&self) -> ProtocolVersion; + + /// Read a single u64 from the protocol. + /// This returns an Option to support graceful shutdown. + fn try_read_number( + &mut self, + ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_; + + /// Read bytes from the protocol. + /// A size limit on the returned bytes has to be specified. + /// This returns an Option to support graceful shutdown. + fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_; + + /// Read bytes from the protocol without a limit. + /// The default implementation just calls `try_read_bytes_limited` with a + /// limit of `0..=usize::MAX` but other implementations are free to have a + /// reader wide limit. + /// This returns an Option to support graceful shutdown. + fn try_read_bytes( + &mut self, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + self.try_read_bytes_limited(0..=usize::MAX) + } + + /// Read a single u64 from the protocol. + /// This will return an error if the number could not be read. + fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ { + async move { + match self.try_read_number().await? { + Some(v) => Ok(v), + None => Err(Self::Error::missing_data("unexpected end-of-file")), + } + } + } + + /// Read bytes from the protocol. + /// A size limit on the returned bytes has to be specified. + /// This will return an error if the number could not be read. + fn read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + async move { + match self.try_read_bytes_limited(limit).await? { + Some(v) => Ok(v), + None => Err(Self::Error::missing_data("unexpected end-of-file")), + } + } + } + + /// Read bytes from the protocol. + /// The default implementation just calls `read_bytes_limited` with a + /// limit of `0..=usize::MAX` but other implementations are free to have a + /// reader wide limit. + /// This will return an error if the bytes could not be read. + fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + self.read_bytes_limited(0..=usize::MAX) + } + + /// Read a value from the protocol. + /// Uses `NixDeserialize::deserialize` to read a value. + fn read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ { + V::deserialize(self) + } + + /// Read a value from the protocol. + /// Uses `NixDeserialize::try_deserialize` to read a value. + /// This returns an Option to support graceful shutdown. + fn try_read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ { + V::try_deserialize(self) + } +} + +impl<T: ?Sized + NixRead> NixRead for &mut T { + type Error = T::Error; + + fn version(&self) -> ProtocolVersion { + (**self).version() + } + + fn try_read_number( + &mut self, + ) -> impl Future<Output = Result<Option<u64>, Self::Error>> + Send + '_ { + (**self).try_read_number() + } + + fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + (**self).try_read_bytes_limited(limit) + } + + fn try_read_bytes( + &mut self, + ) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + (**self).try_read_bytes() + } + + fn read_number(&mut self) -> impl Future<Output = Result<u64, Self::Error>> + Send + '_ { + (**self).read_number() + } + + fn read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + (**self).read_bytes_limited(limit) + } + + fn read_bytes(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + (**self).read_bytes() + } + + fn try_read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<Option<V>, Self::Error>> + Send + '_ { + (**self).try_read_value() + } + + fn read_value<V: NixDeserialize>( + &mut self, + ) -> impl Future<Output = Result<V, Self::Error>> + Send + '_ { + (**self).read_value() + } +} + +/// A data structure that can be deserialized from the Nix daemon +/// worker protocol. +pub trait NixDeserialize: Sized { + /// Read a value from the reader. + /// This returns an Option to support gracefull shutdown. + fn try_deserialize<R>( + reader: &mut R, + ) -> impl Future<Output = Result<Option<Self>, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send; + + fn deserialize<R>(reader: &mut R) -> impl Future<Output = Result<Self, R::Error>> + Send + '_ + where + R: ?Sized + NixRead + Send, + { + async move { + match Self::try_deserialize(reader).await? { + Some(v) => Ok(v), + None => Err(R::Error::missing_data("unexpected end-of-file")), + } + } + } +} diff --git a/tvix/nix-compat/src/nix_daemon/de/reader.rs b/tvix/nix-compat/src/nix_daemon/de/reader.rs new file mode 100644 index 000000000000..87c623b2220c --- /dev/null +++ b/tvix/nix-compat/src/nix_daemon/de/reader.rs @@ -0,0 +1,527 @@ +use std::future::poll_fn; +use std::io::{self, Cursor}; +use std::ops::RangeInclusive; +use std::pin::Pin; +use std::task::{ready, Context, Poll}; + +use bytes::{Buf, BufMut, Bytes, BytesMut}; +use pin_project_lite::pin_project; +use tokio::io::{AsyncBufRead, AsyncRead, AsyncReadExt, ReadBuf}; + +use crate::nix_daemon::ProtocolVersion; +use crate::wire::EMPTY_BYTES; + +use super::{Error, NixRead}; + +pub struct NixReaderBuilder { + buf: Option<BytesMut>, + reserved_buf_size: usize, + max_buf_size: usize, + version: ProtocolVersion, +} + +impl Default for NixReaderBuilder { + fn default() -> Self { + Self { + buf: Default::default(), + reserved_buf_size: 8192, + max_buf_size: 8192, + version: Default::default(), + } + } +} + +impl NixReaderBuilder { + pub fn set_buffer(mut self, buf: BytesMut) -> Self { + self.buf = Some(buf); + self + } + + pub fn set_reserved_buf_size(mut self, size: usize) -> Self { + self.reserved_buf_size = size; + self + } + + pub fn set_max_buf_size(mut self, size: usize) -> Self { + self.max_buf_size = size; + self + } + + pub fn set_version(mut self, version: ProtocolVersion) -> Self { + self.version = version; + self + } + + pub fn build<R>(self, reader: R) -> NixReader<R> { + let buf = self.buf.unwrap_or_else(|| BytesMut::with_capacity(0)); + NixReader { + buf, + inner: reader, + reserved_buf_size: self.reserved_buf_size, + max_buf_size: self.max_buf_size, + version: self.version, + } + } +} + +pin_project! { + pub struct NixReader<R> { + #[pin] + inner: R, + buf: BytesMut, + reserved_buf_size: usize, + max_buf_size: usize, + version: ProtocolVersion, + } +} + +impl NixReader<Cursor<Vec<u8>>> { + pub fn builder() -> NixReaderBuilder { + NixReaderBuilder::default() + } +} + +impl<R> NixReader<R> +where + R: AsyncReadExt, +{ + pub fn new(reader: R) -> NixReader<R> { + NixReader::builder().build(reader) + } + + pub fn buffer(&self) -> &[u8] { + &self.buf[..] + } + + #[cfg(test)] + pub(crate) fn buffer_mut(&mut self) -> &mut BytesMut { + &mut self.buf + } + + /// Remaining capacity in internal buffer + pub fn remaining_mut(&self) -> usize { + self.buf.capacity() - self.buf.len() + } + + fn poll_force_fill_buf( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + ) -> Poll<io::Result<usize>> { + // Ensure that buffer has space for at least reserved_buf_size bytes + if self.remaining_mut() < self.reserved_buf_size { + let me = self.as_mut().project(); + me.buf.reserve(*me.reserved_buf_size); + } + let me = self.project(); + let n = { + let dst = me.buf.spare_capacity_mut(); + let mut buf = ReadBuf::uninit(dst); + let ptr = buf.filled().as_ptr(); + ready!(me.inner.poll_read(cx, &mut buf)?); + + // Ensure the pointer does not change from under us + assert_eq!(ptr, buf.filled().as_ptr()); + buf.filled().len() + }; + + // SAFETY: This is guaranteed to be the number of initialized (and read) + // bytes due to the invariants provided by `ReadBuf::filled`. + unsafe { + me.buf.advance_mut(n); + } + Poll::Ready(Ok(n)) + } +} + +impl<R> NixReader<R> +where + R: AsyncReadExt + Unpin, +{ + async fn force_fill(&mut self) -> io::Result<usize> { + let mut p = Pin::new(self); + let read = poll_fn(|cx| p.as_mut().poll_force_fill_buf(cx)).await?; + Ok(read) + } +} + +impl<R> NixRead for NixReader<R> +where + R: AsyncReadExt + Send + Unpin, +{ + type Error = io::Error; + + fn version(&self) -> ProtocolVersion { + self.version + } + + async fn try_read_number(&mut self) -> Result<Option<u64>, Self::Error> { + let mut buf = [0u8; 8]; + let read = self.read_buf(&mut &mut buf[..]).await?; + if read == 0 { + return Ok(None); + } + if read < 8 { + self.read_exact(&mut buf[read..]).await?; + } + let num = Buf::get_u64_le(&mut &buf[..]); + Ok(Some(num)) + } + + async fn try_read_bytes_limited( + &mut self, + limit: RangeInclusive<usize>, + ) -> Result<Option<Bytes>, Self::Error> { + assert!( + *limit.end() <= self.max_buf_size, + "The limit must be smaller than {}", + self.max_buf_size + ); + match self.try_read_number().await? { + Some(raw_len) => { + // Check that length is in range and convert to usize + let len = raw_len + .try_into() + .ok() + .filter(|v| limit.contains(v)) + .ok_or_else(|| Self::Error::invalid_data("bytes length out of range"))?; + + // Calculate 64bit aligned length and convert to usize + let aligned: usize = raw_len + .checked_add(7) + .map(|v| v & !7) + .ok_or_else(|| Self::Error::invalid_data("bytes length out of range"))? + .try_into() + .map_err(Self::Error::invalid_data)?; + + // Ensure that there is enough space in buffer for contents + if self.buf.len() + self.remaining_mut() < aligned { + self.buf.reserve(aligned - self.buf.len()); + } + while self.buf.len() < aligned { + if self.force_fill().await? == 0 { + return Err(Self::Error::missing_data( + "unexpected end-of-file reading bytes", + )); + } + } + let mut contents = self.buf.split_to(aligned); + + let padding = aligned - len; + // Ensure padding is all zeros + if contents[len..] != EMPTY_BYTES[..padding] { + return Err(Self::Error::invalid_data("non-zero padding")); + } + + contents.truncate(len); + Ok(Some(contents.freeze())) + } + None => Ok(None), + } + } + + fn try_read_bytes( + &mut self, + ) -> impl std::future::Future<Output = Result<Option<Bytes>, Self::Error>> + Send + '_ { + self.try_read_bytes_limited(0..=self.max_buf_size) + } + + fn read_bytes( + &mut self, + ) -> impl std::future::Future<Output = Result<Bytes, Self::Error>> + Send + '_ { + self.read_bytes_limited(0..=self.max_buf_size) + } +} + +impl<R: AsyncRead> AsyncRead for NixReader<R> { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll<io::Result<()>> { + let rem = ready!(self.as_mut().poll_fill_buf(cx))?; + let amt = std::cmp::min(rem.len(), buf.remaining()); + buf.put_slice(&rem[0..amt]); + self.consume(amt); + Poll::Ready(Ok(())) + } +} + +impl<R: AsyncRead> AsyncBufRead for NixReader<R> { + fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> { + if self.as_ref().project_ref().buf.is_empty() { + ready!(self.as_mut().poll_force_fill_buf(cx))?; + } + let me = self.project(); + Poll::Ready(Ok(&me.buf[..])) + } + + fn consume(self: Pin<&mut Self>, amt: usize) { + let me = self.project(); + me.buf.advance(amt) + } +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use hex_literal::hex; + use rstest::rstest; + use tokio_test::io::Builder; + + use super::*; + use crate::nix_daemon::de::NixRead; + + #[tokio::test] + async fn test_read_u64() { + let mock = Builder::new().read(&hex!("0100 0000 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!(""), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!(""), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_rest() { + let mock = Builder::new() + .read(&hex!("0100 0000 0000 0000 0123 4567 89AB CDEF")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!("0123 4567 89AB CDEF"), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!("0123 4567 89AB CDEF"), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_partial() { + let mock = Builder::new() + .read(&hex!("0100 0000")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000 0123 4567 89AB CDEF")) + .wait(Duration::ZERO) + .read(&hex!("0100 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!(1, reader.read_number().await.unwrap()); + assert_eq!(hex!("0123 4567 89AB CDEF"), reader.buffer()); + + let mut buf = Vec::new(); + reader.read_to_end(&mut buf).await.unwrap(); + assert_eq!(hex!("0123 4567 89AB CDEF 0100 0000"), &buf[..]); + } + + #[tokio::test] + async fn test_read_u64_eof() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.read_number().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_u64_none() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!(None, reader.try_read_number().await.unwrap()); + } + + #[tokio::test] + async fn test_try_read_u64_eof() { + let mock = Builder::new().read(&hex!("0100 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_number().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_u64_eof2() { + let mock = Builder::new() + .read(&hex!("0100")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_number().await.unwrap_err().kind() + ); + } + + #[rstest] + #[case::empty(b"", &hex!("0000 0000 0000 0000"))] + #[case::one(b")", &hex!("0100 0000 0000 0000 2900 0000 0000 0000"))] + #[case::two(b"it", &hex!("0200 0000 0000 0000 6974 0000 0000 0000"))] + #[case::three(b"tea", &hex!("0300 0000 0000 0000 7465 6100 0000 0000"))] + #[case::four(b"were", &hex!("0400 0000 0000 0000 7765 7265 0000 0000"))] + #[case::five(b"where", &hex!("0500 0000 0000 0000 7768 6572 6500 0000"))] + #[case::six(b"unwrap", &hex!("0600 0000 0000 0000 756E 7772 6170 0000"))] + #[case::seven(b"where's", &hex!("0700 0000 0000 0000 7768 6572 6527 7300"))] + #[case::aligned(b"read_tea", &hex!("0800 0000 0000 0000 7265 6164 5F74 6561"))] + #[case::more_bytes(b"read_tess", &hex!("0900 0000 0000 0000 7265 6164 5F74 6573 7300 0000 0000 0000"))] + #[tokio::test] + async fn test_read_bytes(#[case] expected: &[u8], #[case] data: &[u8]) { + let mock = Builder::new().read(data).build(); + let mut reader = NixReader::new(mock); + let actual = reader.read_bytes().await.unwrap(); + assert_eq!(&actual[..], expected); + } + + #[tokio::test] + async fn test_read_bytes_empty() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_bytes_none() { + let mock = Builder::new().build(); + let mut reader = NixReader::new(mock); + + assert_eq!(None, reader.try_read_bytes().await.unwrap()); + } + + #[tokio::test] + async fn test_try_read_bytes_missing_data() { + let mock = Builder::new() + .read(&hex!("0500")) + .wait(Duration::ZERO) + .read(&hex!("0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_try_read_bytes_missing_padding() { + let mock = Builder::new() + .read(&hex!("0200 0000 0000 0000")) + .wait(Duration::ZERO) + .read(&hex!("1234")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::UnexpectedEof, + reader.try_read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_bad_padding() { + let mock = Builder::new() + .read(&hex!("0200 0000 0000 0000")) + .wait(Duration::ZERO) + .read(&hex!("1234 0100 0000 0000")) + .build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_bytes().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_limited_out_of_range() { + let mock = Builder::new().read(&hex!("FFFF 0000 0000 0000")).build(); + let mut reader = NixReader::new(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader.read_bytes_limited(0..=50).await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_read_bytes_length_overflow() { + let mock = Builder::new().read(&hex!("F9FF FFFF FFFF FFFF")).build(); + let mut reader = NixReader::builder() + .set_max_buf_size(usize::MAX) + .build(mock); + + assert_eq!( + io::ErrorKind::InvalidData, + reader + .read_bytes_limited(0..=usize::MAX) + .await + .unwrap_err() + .kind() + ); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_bytes_length_conversion_overflow() { + let len = (usize::MAX as u64) + 1; + let mock = Builder::new().read(&len.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } + + // FUTUREWORK: Test this on supported hardware + #[tokio::test] + #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] + async fn test_bytes_aligned_length_conversion_overflow() { + let len = (usize::MAX - 6) as u64; + let mock = Builder::new().read(&len.to_le_bytes()).build(); + let mut reader = NixReader::new(mock); + assert_eq!( + std::io::ErrorKind::InvalidData, + reader.read_value::<usize>().await.unwrap_err().kind() + ); + } + + #[tokio::test] + async fn test_buffer_resize() { + let mock = Builder::new() + .read(&hex!("0100")) + .read(&hex!("0000 0000 0000")) + .build(); + let mut reader = NixReader::builder().set_reserved_buf_size(8).build(mock); + // buffer has no capacity initially + assert_eq!(0, reader.buffer_mut().capacity()); + + assert_eq!(2, reader.force_fill().await.unwrap()); + + // After first read buffer should have capacity we chose + assert_eq!(8, reader.buffer_mut().capacity()); + + // Because there was only 6 bytes remaining in buffer, + // which is enough to read the last 6 bytes, but we require + // capacity for 8 bytes, it doubled the capacity + assert_eq!(6, reader.force_fill().await.unwrap()); + assert_eq!(16, reader.buffer_mut().capacity()); + + assert_eq!(1, reader.read_number().await.unwrap()); + } +} diff --git a/tvix/nix-compat/src/nix_daemon/mod.rs b/tvix/nix-compat/src/nix_daemon/mod.rs index fe652377d1b4..11413e85fd1b 100644 --- a/tvix/nix-compat/src/nix_daemon/mod.rs +++ b/tvix/nix-compat/src/nix_daemon/mod.rs @@ -2,3 +2,5 @@ pub mod worker_protocol; mod protocol_version; pub use protocol_version::ProtocolVersion; + +pub mod de; diff --git a/tvix/nix-compat/src/nix_daemon/protocol_version.rs b/tvix/nix-compat/src/nix_daemon/protocol_version.rs index 8fd2b085c962..19da28d484dd 100644 --- a/tvix/nix-compat/src/nix_daemon/protocol_version.rs +++ b/tvix/nix-compat/src/nix_daemon/protocol_version.rs @@ -1,3 +1,6 @@ +/// The latest version that is currently supported by nix-compat. +static DEFAULT_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion::from_parts(1, 37); + /// Protocol versions are represented as a u16. /// The upper 8 bits are the major version, the lower bits the minor. /// This is not aware of any endianness, use [crate::wire::read_u64] to get an @@ -20,6 +23,12 @@ impl ProtocolVersion { } } +impl Default for ProtocolVersion { + fn default() -> Self { + DEFAULT_PROTOCOL_VERSION + } +} + impl PartialOrd for ProtocolVersion { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) @@ -45,6 +54,13 @@ impl From<u16> for ProtocolVersion { } } +#[cfg(any(test, feature = "test"))] +impl From<(u8, u8)> for ProtocolVersion { + fn from((major, minor): (u8, u8)) -> Self { + Self::from_parts(major, minor) + } +} + impl TryFrom<u64> for ProtocolVersion { type Error = &'static str; diff --git a/tvix/nix-compat/src/nix_http/mod.rs b/tvix/nix-compat/src/nix_http/mod.rs new file mode 100644 index 000000000000..89ba147b8071 --- /dev/null +++ b/tvix/nix-compat/src/nix_http/mod.rs @@ -0,0 +1,115 @@ +use tracing::trace; + +use crate::nixbase32; + +/// The mime type used for NAR files, both compressed and uncompressed +pub const MIME_TYPE_NAR: &str = "application/x-nix-nar"; +/// The mime type used for NARInfo files +pub const MIME_TYPE_NARINFO: &str = "text/x-nix-narinfo"; +/// The mime type used for the `nix-cache-info` file +pub const MIME_TYPE_CACHE_INFO: &str = "text/x-nix-cache-info"; + +/// Parses a `14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar` +/// string and returns the nixbase32-decoded digest, as well as the compression +/// suffix (which might be empty). +pub fn parse_nar_str(s: &str) -> Option<([u8; 32], &str)> { + if !s.is_char_boundary(52) { + trace!("invalid string, no char boundary at 52"); + return None; + } + + let (hash_str, suffix) = s.split_at(52); + + // we know hash_str is 52 bytes, so it's ok to unwrap here. + let hash_str_fixed: [u8; 52] = hash_str.as_bytes().try_into().unwrap(); + + match suffix.strip_prefix(".nar") { + Some(compression_suffix) => match nixbase32::decode_fixed(hash_str_fixed) { + Err(e) => { + trace!(err=%e, "invalid nixbase32 encoding"); + None + } + Ok(digest) => Some((digest, compression_suffix)), + }, + None => { + trace!("no .nar suffix"); + None + } + } +} + +/// Parses a `3mzh8lvgbynm9daj7c82k2sfsfhrsfsy.narinfo` string and returns the +/// nixbase32-decoded digest. +pub fn parse_narinfo_str(s: &str) -> Option<[u8; 20]> { + if !s.is_char_boundary(32) { + trace!("invalid string, no char boundary at 32"); + return None; + } + + match s.split_at(32) { + (hash_str, ".narinfo") => { + // we know this is 32 bytes, so it's ok to unwrap here. + let hash_str_fixed: [u8; 32] = hash_str.as_bytes().try_into().unwrap(); + + match nixbase32::decode_fixed(hash_str_fixed) { + Err(e) => { + trace!(err=%e, "invalid nixbase32 encoding"); + None + } + Ok(digest) => Some(digest), + } + } + _ => { + trace!("invalid string, no .narinfo suffix"); + None + } + } +} + +#[cfg(test)] +mod test { + use super::{parse_nar_str, parse_narinfo_str}; + use hex_literal::hex; + + #[test] + fn parse_nar_str_success() { + assert_eq!( + ( + hex!("13a8cf7ca57f68a9f1752acee36a72a55187d3a954443c112818926f26109d91"), + "" + ), + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar").unwrap() + ); + + assert_eq!( + ( + hex!("13a8cf7ca57f68a9f1752acee36a72a55187d3a954443c112818926f26109d91"), + ".xz" + ), + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0k.nar.xz").unwrap() + ) + } + + #[test] + fn parse_nar_str_failure() { + assert!(parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0").is_none()); + assert!( + parse_nar_str("14cx20k6z4hq508kqi2lm79qfld5f9mf7kiafpqsjs3zlmycza0🦊.nar").is_none() + ) + } + #[test] + fn parse_narinfo_str_success() { + assert_eq!( + hex!("8a12321522fd91efbd60ebb2481af88580f61600"), + parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la.narinfo").unwrap() + ); + } + + #[test] + fn parse_narinfo_str_failure() { + assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44la").is_none()); + assert!(parse_narinfo_str("/00bgd045z0d4icpbc2yyz4gx48ak44la").is_none()); + assert!(parse_narinfo_str("000000").is_none()); + assert!(parse_narinfo_str("00bgd045z0d4icpbc2yyz4gx48ak44l🦊.narinfo").is_none()); + } +} diff --git a/tvix/nix-compat/src/nixhash/ca_hash.rs b/tvix/nix-compat/src/nixhash/ca_hash.rs index 423531696afe..e6cbaf5b710a 100644 --- a/tvix/nix-compat/src/nixhash/ca_hash.rs +++ b/tvix/nix-compat/src/nixhash/ca_hash.rs @@ -72,7 +72,8 @@ impl CAHash { /// - `text:sha256:$nixbase32sha256digest` /// - `fixed:r:$algo:$nixbase32digest` /// - `fixed:$algo:$nixbase32digest` - /// which is the format that's used in the NARInfo for example. + /// + /// These formats are used in NARInfo, for example. pub fn from_nix_hex_str(s: &str) -> Option<Self> { let (tag, s) = s.split_once(':')?; @@ -108,11 +109,13 @@ impl CAHash { /// know whether we have a invalid or a missing NixHashWithMode structure in another structure, /// e.g. Output. /// This means we have this combinatorial situation: + /// /// - no hash, no hashAlgo: no [CAHash] so we return Ok(None). /// - present hash, missing hashAlgo: invalid, we will return missing_field /// - missing hash, present hashAlgo: same /// - present hash, present hashAlgo: either we return ourselves or a type/value validation - /// error. + /// error. + /// /// This function is for internal consumption regarding those needs until we have a better /// solution. Now this is said, let's explain how this works. /// diff --git a/tvix/nix-compat/src/store_path/mod.rs b/tvix/nix-compat/src/store_path/mod.rs index 707c41a92d74..177cc96ce20f 100644 --- a/tvix/nix-compat/src/store_path/mod.rs +++ b/tvix/nix-compat/src/store_path/mod.rs @@ -2,14 +2,15 @@ use crate::nixbase32; use data_encoding::{DecodeError, BASE64}; use serde::{Deserialize, Serialize}; use std::{ - fmt, - path::PathBuf, + fmt::{self, Display}, + ops::Deref, + path::Path, str::{self, FromStr}, }; use thiserror; #[cfg(target_family = "unix")] -use std::os::unix::ffi::OsStringExt; +use std::os::unix::ffi::OsStrExt; mod utils; @@ -54,17 +55,26 @@ pub enum Error { /// A [StorePath] does not encode any additional subpath "inside" the store /// path. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct StorePath { +pub struct StorePath<S> +where + S: std::cmp::Eq + std::cmp::PartialEq, +{ digest: [u8; DIGEST_SIZE], - name: Box<str>, + name: S, } +/// Like [StorePath], but without a heap allocation for the name. +/// Used by [StorePath] for parsing. +pub type StorePathRef<'a> = StorePath<&'a str>; -impl StorePath { +impl<S> StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str>, +{ pub fn digest(&self) -> &[u8; DIGEST_SIZE] { &self.digest } - pub fn name(&self) -> &str { + pub fn name(&self) -> &S { &self.name } @@ -74,60 +84,101 @@ impl StorePath { name: &self.name, } } -} -impl PartialOrd for StorePath { - fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { - Some(self.cmp(other)) + pub fn to_owned(&self) -> StorePath<String> { + StorePath { + digest: self.digest, + name: self.name.to_string(), + } } -} -/// `StorePath`s are sorted by their reverse digest to match the sorting order -/// of the nixbase32-encoded string. -impl Ord for StorePath { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ref().cmp(&other.as_ref()) + /// Construct a [StorePath] by passing the `$digest-$name` string + /// that comes after [STORE_DIR_WITH_SLASH]. + pub fn from_bytes<'a>(s: &'a [u8]) -> Result<Self, Error> + where + S: From<&'a str>, + { + // the whole string needs to be at least: + // + // - 32 characters (encoded hash) + // - 1 dash + // - 1 character for the name + if s.len() < ENCODED_DIGEST_SIZE + 2 { + Err(Error::InvalidLength)? + } + + let digest = nixbase32::decode_fixed(&s[..ENCODED_DIGEST_SIZE])?; + + if s[ENCODED_DIGEST_SIZE] != b'-' { + return Err(Error::MissingDash); + } + + Ok(StorePath { + digest, + name: validate_name(&s[ENCODED_DIGEST_SIZE + 1..])?.into(), + }) } -} -impl FromStr for StorePath { - type Err = Error; + /// Construct a [StorePathRef] from a name and digest. + /// The name is validated, and the digest checked for size. + pub fn from_name_and_digest<'a>(name: &'a str, digest: &[u8]) -> Result<Self, Error> + where + S: From<&'a str>, + { + let digest_fixed = digest.try_into().map_err(|_| Error::InvalidLength)?; + Self::from_name_and_digest_fixed(name, digest_fixed) + } - /// Construct a [StorePath] by passing the `$digest-$name` string - /// that comes after [STORE_DIR_WITH_SLASH]. - fn from_str(s: &str) -> Result<Self, Self::Err> { - Self::from_bytes(s.as_bytes()) + /// Construct a [StorePathRef] from a name and digest of correct length. + /// The name is validated. + pub fn from_name_and_digest_fixed<'a>( + name: &'a str, + digest: [u8; DIGEST_SIZE], + ) -> Result<Self, Error> + where + S: From<&'a str>, + { + Ok(Self { + name: validate_name(name.as_bytes())?.into(), + digest, + }) } -} -impl StorePath { - /// Construct a [StorePath] by passing the `$digest-$name` string - /// that comes after [STORE_DIR_WITH_SLASH]. - pub fn from_bytes(s: &[u8]) -> Result<StorePath, Error> { - Ok(StorePathRef::from_bytes(s)?.to_owned()) + /// Construct a [StorePathRef] from an absolute store path string. + /// This is equivalent to calling [StorePathRef::from_bytes], but stripping + /// the [STORE_DIR_WITH_SLASH] prefix before. + pub fn from_absolute_path<'a>(s: &'a [u8]) -> Result<Self, Error> + where + S: From<&'a str>, + { + match s.strip_prefix(STORE_DIR_WITH_SLASH.as_bytes()) { + Some(s_stripped) => Self::from_bytes(s_stripped), + None => Err(Error::MissingStoreDir), + } } /// Decompose a string into a [StorePath] and a [PathBuf] containing the /// rest of the path, or an error. #[cfg(target_family = "unix")] - pub fn from_absolute_path_full(s: &str) -> Result<(StorePath, PathBuf), Error> { + pub fn from_absolute_path_full<'a>(s: &'a str) -> Result<(Self, &'a Path), Error> + where + S: From<&'a str>, + { // strip [STORE_DIR_WITH_SLASH] from s + match s.strip_prefix(STORE_DIR_WITH_SLASH) { None => Err(Error::MissingStoreDir), Some(rest) => { - // put rest in a PathBuf - let mut p = PathBuf::new(); - p.push(rest); - - let mut it = p.components(); + let mut it = Path::new(rest).components(); // The first component of the rest must be parse-able as a [StorePath] if let Some(first_component) = it.next() { // convert first component to StorePath - let first_component_bytes = first_component.as_os_str().to_owned().into_vec(); - let store_path = StorePath::from_bytes(&first_component_bytes)?; + let store_path = StorePath::from_bytes(first_component.as_os_str().as_bytes())?; + // collect rest - let rest_buf: PathBuf = it.collect(); + let rest_buf = it.as_path(); + Ok((store_path, rest_buf)) } else { Err(Error::InvalidLength) // Well, or missing "/"? @@ -139,139 +190,48 @@ impl StorePath { /// Returns an absolute store path string. /// That is just the string representation, prefixed with the store prefix /// ([STORE_DIR_WITH_SLASH]), - pub fn to_absolute_path(&self) -> String { - let sp_ref: StorePathRef = self.into(); - sp_ref.to_absolute_path() - } -} - -impl<'de> Deserialize<'de> for StorePath { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: serde::Deserializer<'de>, - { - let r = <StorePathRef<'de> as Deserialize<'de>>::deserialize(deserializer)?; - Ok(r.to_owned()) - } -} - -impl Serialize for StorePath { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + pub fn to_absolute_path(&self) -> String where - S: serde::Serializer, + S: Display, { - let r: StorePathRef = self.into(); - r.serialize(serializer) - } -} - -/// Like [StorePath], but without a heap allocation for the name. -/// Used by [StorePath] for parsing. -/// -#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)] -pub struct StorePathRef<'a> { - digest: [u8; DIGEST_SIZE], - name: &'a str, -} - -impl<'a> From<&'a StorePath> for StorePathRef<'a> { - fn from(&StorePath { digest, ref name }: &'a StorePath) -> Self { - StorePathRef { digest, name } + format!("{}{}", STORE_DIR_WITH_SLASH, self) } } -impl<'a> PartialOrd for StorePathRef<'a> { +impl<S> PartialOrd for StorePath<S> +where + S: std::cmp::PartialEq + std::cmp::Eq, +{ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { Some(self.cmp(other)) } } -/// `StorePathRef`s are sorted by their reverse digest to match the sorting order +/// `StorePath`s are sorted by their reverse digest to match the sorting order /// of the nixbase32-encoded string. -impl<'a> Ord for StorePathRef<'a> { +impl<S> Ord for StorePath<S> +where + S: std::cmp::PartialEq + std::cmp::Eq, +{ fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.digest.iter().rev().cmp(other.digest.iter().rev()) } } -impl<'a> StorePathRef<'a> { - pub fn digest(&self) -> &[u8; DIGEST_SIZE] { - &self.digest - } - - pub fn name(&self) -> &'a str { - self.name - } - - pub fn to_owned(&self) -> StorePath { - StorePath { - digest: self.digest, - name: self.name.into(), - } - } - - /// Construct a [StorePathRef] from a name and digest. - /// The name is validated, and the digest checked for size. - pub fn from_name_and_digest(name: &'a str, digest: &[u8]) -> Result<Self, Error> { - let digest_fixed = digest.try_into().map_err(|_| Error::InvalidLength)?; - Self::from_name_and_digest_fixed(name, digest_fixed) - } - - /// Construct a [StorePathRef] from a name and digest of correct length. - /// The name is validated. - pub fn from_name_and_digest_fixed( - name: &'a str, - digest: [u8; DIGEST_SIZE], - ) -> Result<Self, Error> { - Ok(Self { - name: validate_name(name.as_bytes())?, - digest, - }) - } - - /// Construct a [StorePathRef] from an absolute store path string. - /// This is equivalent to calling [StorePathRef::from_bytes], but stripping - /// the [STORE_DIR_WITH_SLASH] prefix before. - pub fn from_absolute_path(s: &'a [u8]) -> Result<Self, Error> { - match s.strip_prefix(STORE_DIR_WITH_SLASH.as_bytes()) { - Some(s_stripped) => Self::from_bytes(s_stripped), - None => Err(Error::MissingStoreDir), - } - } +impl<'a, 'b: 'a> FromStr for StorePath<String> { + type Err = Error; - /// Construct a [StorePathRef] by passing the `$digest-$name` string + /// Construct a [StorePath] by passing the `$digest-$name` string /// that comes after [STORE_DIR_WITH_SLASH]. - pub fn from_bytes(s: &'a [u8]) -> Result<Self, Error> { - // the whole string needs to be at least: - // - // - 32 characters (encoded hash) - // - 1 dash - // - 1 character for the name - if s.len() < ENCODED_DIGEST_SIZE + 2 { - Err(Error::InvalidLength)? - } - - let digest = nixbase32::decode_fixed(&s[..ENCODED_DIGEST_SIZE])?; - - if s[ENCODED_DIGEST_SIZE] != b'-' { - return Err(Error::MissingDash); - } - - Ok(StorePathRef { - digest, - name: validate_name(&s[ENCODED_DIGEST_SIZE + 1..])?, - }) - } - - /// Returns an absolute store path string. - /// That is just the string representation, prefixed with the store prefix - /// ([STORE_DIR_WITH_SLASH]), - pub fn to_absolute_path(&self) -> String { - format!("{}{}", STORE_DIR_WITH_SLASH, self) + fn from_str(s: &str) -> Result<Self, Self::Err> { + StorePath::<String>::from_bytes(s.as_bytes()) } } -impl<'de: 'a, 'a> Deserialize<'de> for StorePathRef<'a> { +impl<'a, 'de: 'a, S> Deserialize<'de> for StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str> + From<&'a str>, +{ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>, @@ -284,16 +244,19 @@ impl<'de: 'a, 'a> Deserialize<'de> for StorePathRef<'a> { &"store path prefix", ) })?; - StorePathRef::from_bytes(stripped.as_bytes()).map_err(|_| { + StorePath::from_bytes(stripped.as_bytes()).map_err(|_| { serde::de::Error::invalid_value(serde::de::Unexpected::Str(string), &"StorePath") }) } } -impl Serialize for StorePathRef<'_> { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> +impl<S> Serialize for StorePath<S> +where + S: std::cmp::Eq + Deref<Target = str> + Display, +{ + fn serialize<SR>(&self, serializer: SR) -> Result<SR::Ok, SR::Error> where - S: serde::Serializer, + SR: serde::Serializer, { let string: String = self.to_absolute_path(); string.serialize(serializer) @@ -347,13 +310,10 @@ pub(crate) fn validate_name(s: &(impl AsRef<[u8]> + ?Sized)) -> Result<&str, Err Ok(unsafe { str::from_utf8_unchecked(s) }) } -impl fmt::Display for StorePath { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - StorePathRef::from(self).fmt(f) - } -} - -impl fmt::Display for StorePathRef<'_> { +impl<S> fmt::Display for StorePath<S> +where + S: fmt::Display + std::cmp::Eq, +{ /// The string representation of a store path starts with a digest (20 /// bytes), [crate::nixbase32]-encoded, followed by a `-`, /// and ends with the name. @@ -386,12 +346,12 @@ mod tests { fn happy_path() { let example_nix_path_str = "00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432"; - let nixpath = StorePath::from_bytes(example_nix_path_str.as_bytes()) + let nixpath = StorePathRef::from_bytes(example_nix_path_str.as_bytes()) .expect("Error parsing example string"); let expected_digest: [u8; DIGEST_SIZE] = hex!("8a12321522fd91efbd60ebb2481af88580f61600"); - assert_eq!("net-tools-1.60_p20170221182432", nixpath.name()); + assert_eq!("net-tools-1.60_p20170221182432", *nixpath.name()); assert_eq!(nixpath.digest, expected_digest); assert_eq!(example_nix_path_str, nixpath.to_string()) @@ -426,8 +386,8 @@ mod tests { if w.len() < 2 { continue; } - let (pa, _) = StorePath::from_absolute_path_full(w[0]).expect("parseable"); - let (pb, _) = StorePath::from_absolute_path_full(w[1]).expect("parseable"); + let (pa, _) = StorePathRef::from_absolute_path_full(w[0]).expect("parseable"); + let (pb, _) = StorePathRef::from_absolute_path_full(w[1]).expect("parseable"); assert_eq!( Ordering::Less, pa.cmp(&pb), @@ -448,36 +408,38 @@ mod tests { /// https://github.com/NixOS/nix/pull/9867 (revert-of-revert) #[test] fn starts_with_dot() { - StorePath::from_bytes(b"fli4bwscgna7lpm7v5xgnjxrxh0yc7ra-.gitignore") + StorePathRef::from_bytes(b"fli4bwscgna7lpm7v5xgnjxrxh0yc7ra-.gitignore") .expect("must succeed"); } #[test] fn empty_name() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-").expect_err("must fail"); + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-").expect_err("must fail"); } #[test] fn excessive_length() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") .expect_err("must fail"); } #[test] fn invalid_hash_length() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yy-net-tools-1.60_p20170221182432") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yy-net-tools-1.60_p20170221182432") .expect_err("must fail"); } #[test] fn invalid_encoding_hash() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432") - .expect_err("must fail"); + StorePathRef::from_bytes( + b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432", + ) + .expect_err("must fail"); } #[test] fn more_than_just_the_bare_nix_store_path() { - StorePath::from_bytes( + StorePathRef::from_bytes( b"00bgd045z0d4icpbc2yyz4gx48aku4la-net-tools-1.60_p20170221182432/bin/arp", ) .expect_err("must fail"); @@ -485,7 +447,7 @@ mod tests { #[test] fn no_dash_between_hash_and_name() { - StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432") + StorePathRef::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44lanet-tools-1.60_p20170221182432") .expect_err("must fail"); } @@ -534,7 +496,7 @@ mod tests { #[test] fn serialize_owned() { - let nixpath_actual = StorePath::from_bytes( + let nixpath_actual = StorePathRef::from_bytes( b"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432", ) .expect("can parse"); @@ -578,7 +540,8 @@ mod tests { let store_path_str_json = "\"/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432\""; - let store_path: StorePath = serde_json::from_str(store_path_str_json).expect("valid json"); + let store_path: StorePath<String> = + serde_json::from_str(store_path_str_json).expect("valid json"); assert_eq!( "/nix/store/00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432", @@ -601,7 +564,7 @@ mod tests { StorePath::from_bytes(b"00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432").unwrap(), PathBuf::from("bin/arp/"))] fn from_absolute_path_full( #[case] s: &str, - #[case] exp_store_path: StorePath, + #[case] exp_store_path: StorePath<&str>, #[case] exp_path: PathBuf, ) { let (actual_store_path, actual_path) = @@ -615,15 +578,15 @@ mod tests { fn from_absolute_path_errors() { assert_eq!( Error::InvalidLength, - StorePath::from_absolute_path_full("/nix/store/").expect_err("must fail") + StorePathRef::from_absolute_path_full("/nix/store/").expect_err("must fail") ); assert_eq!( Error::InvalidLength, - StorePath::from_absolute_path_full("/nix/store/foo").expect_err("must fail") + StorePathRef::from_absolute_path_full("/nix/store/foo").expect_err("must fail") ); assert_eq!( Error::MissingStoreDir, - StorePath::from_absolute_path_full( + StorePathRef::from_absolute_path_full( "00bgd045z0d4icpbc2yyz4gx48ak44la-net-tools-1.60_p20170221182432" ) .expect_err("must fail") diff --git a/tvix/nix-compat/src/store_path/utils.rs b/tvix/nix-compat/src/store_path/utils.rs index d6f390db85c2..4bfbb72fcdde 100644 --- a/tvix/nix-compat/src/store_path/utils.rs +++ b/tvix/nix-compat/src/store_path/utils.rs @@ -1,6 +1,6 @@ use crate::nixbase32; use crate::nixhash::{CAHash, NixHash}; -use crate::store_path::{Error, StorePathRef, STORE_DIR}; +use crate::store_path::{Error, StorePath, StorePathRef, STORE_DIR}; use data_encoding::HEXLOWER; use sha2::{Digest, Sha256}; use thiserror; @@ -43,11 +43,17 @@ pub fn compress_hash<const OUTPUT_SIZE: usize>(input: &[u8]) -> [u8; OUTPUT_SIZE /// derivation or a literal text file that may contain references. /// If you don't want to have to pass the entire contents, you might want to use /// [build_ca_path] instead. -pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>>( - name: &str, +pub fn build_text_path<'a, S, SP, I, C>( + name: &'a str, content: C, references: I, -) -> Result<StorePathRef<'_>, BuildStorePathError> { +) -> Result<StorePath<SP>, BuildStorePathError> +where + S: AsRef<str>, + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, + I: IntoIterator<Item = S>, + C: AsRef<[u8]>, +{ // produce the sha256 digest of the contents let content_digest = Sha256::new_with_prefix(content).finalize().into(); @@ -55,12 +61,17 @@ pub fn build_text_path<S: AsRef<str>, I: IntoIterator<Item = S>, C: AsRef<[u8]>> } /// This builds a store path from a [CAHash] and a list of references. -pub fn build_ca_path<'a, S: AsRef<str>, I: IntoIterator<Item = S>>( +pub fn build_ca_path<'a, S, SP, I>( name: &'a str, ca_hash: &CAHash, references: I, self_reference: bool, -) -> Result<StorePathRef<'a>, BuildStorePathError> { +) -> Result<StorePath<SP>, BuildStorePathError> +where + S: AsRef<str>, + SP: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, + I: IntoIterator<Item = S>, +{ // self references are only allowed for CAHash::Nar(NixHash::Sha256(_)). if self_reference && matches!(ca_hash, CAHash::Nar(NixHash::Sha256(_))) { return Err(BuildStorePathError::InvalidReference()); @@ -145,17 +156,20 @@ pub fn build_output_path<'a>( /// bytes. /// Inside a StorePath, that digest is printed nixbase32-encoded /// (32 characters). -fn build_store_path_from_fingerprint_parts<'a>( +fn build_store_path_from_fingerprint_parts<'a, S>( ty: &str, inner_digest: &[u8; 32], name: &'a str, -) -> Result<StorePathRef<'a>, Error> { +) -> Result<StorePath<S>, Error> +where + S: std::cmp::Eq + std::ops::Deref<Target = str> + std::convert::From<&'a str>, +{ let fingerprint = format!( "{ty}:sha256:{}:{STORE_DIR}:{name}", HEXLOWER.encode(inner_digest) ); // name validation happens in here. - StorePathRef::from_name_and_digest_fixed( + StorePath::from_name_and_digest_fixed( name, compress_hash(&Sha256::new_with_prefix(fingerprint).finalize()), ) @@ -216,7 +230,7 @@ mod test { // nix-repl> builtins.toFile "foo" "bar" // "/nix/store/vxjiwkjkn7x4079qvh1jkl5pn05j2aw0-foo" - let store_path = build_text_path("foo", "bar", Vec::<String>::new()) + let store_path: StorePathRef = build_text_path("foo", "bar", Vec::<String>::new()) .expect("build_store_path() should succeed"); assert_eq!( @@ -232,11 +246,11 @@ mod test { // nix-repl> builtins.toFile "baz" "${builtins.toFile "foo" "bar"}" // "/nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz" - let inner = build_text_path("foo", "bar", Vec::<String>::new()) + let inner: StorePathRef = build_text_path("foo", "bar", Vec::<String>::new()) .expect("path_with_references() should succeed"); let inner_path = inner.to_absolute_path(); - let outer = build_text_path("baz", &inner_path, vec![inner_path.as_str()]) + let outer: StorePathRef = build_text_path("baz", &inner_path, vec![inner_path.as_str()]) .expect("path_with_references() should succeed"); assert_eq!( @@ -247,7 +261,7 @@ mod test { #[test] fn build_sha1_path() { - let outer = build_ca_path( + let outer: StorePathRef = build_ca_path( "bar", &CAHash::Nar(NixHash::Sha1(hex!( "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33" @@ -272,7 +286,7 @@ mod test { // // $ nix store make-content-addressed /nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz // rewrote '/nix/store/5xd714cbfnkz02h2vbsj4fm03x3f15nf-baz' to '/nix/store/s89y431zzhmdn3k8r96rvakryddkpv2v-baz' - let outer = build_ca_path( + let outer: StorePathRef = build_ca_path( "baz", &CAHash::Nar(NixHash::Sha256( nixbase32::decode(b"1xqkzcb3909fp07qngljr4wcdnrh1gdam1m2n29i6hhrxlmkgkv1") diff --git a/tvix/nix-compat/src/wire/bytes/mod.rs b/tvix/nix-compat/src/wire/bytes/mod.rs index 47bfb5eabacf..74adfb49b6a4 100644 --- a/tvix/nix-compat/src/wire/bytes/mod.rs +++ b/tvix/nix-compat/src/wire/bytes/mod.rs @@ -1,9 +1,12 @@ +#[cfg(feature = "async")] +use std::mem::MaybeUninit; use std::{ io::{Error, ErrorKind}, - mem::MaybeUninit, ops::RangeInclusive, }; -use tokio::io::{self, AsyncReadExt, AsyncWriteExt, ReadBuf}; +#[cfg(feature = "async")] +use tokio::io::ReadBuf; +use tokio::io::{self, AsyncReadExt, AsyncWriteExt}; pub(crate) mod reader; pub use reader::BytesReader; @@ -11,7 +14,7 @@ mod writer; pub use writer::BytesWriter; /// 8 null bytes, used to write out padding. -const EMPTY_BYTES: &[u8; 8] = &[0u8; 8]; +pub(crate) const EMPTY_BYTES: &[u8; 8] = &[0u8; 8]; /// The length of the size field, in bytes is always 8. const LEN_SIZE: usize = 8; @@ -79,6 +82,7 @@ where Ok(buf) } +#[cfg(feature = "async")] pub(crate) async fn read_bytes_buf<'a, const N: usize, R>( reader: &mut R, buf: &'a mut [MaybeUninit<u8>; N], @@ -132,6 +136,7 @@ where } /// SAFETY: The bytes have to actually be initialized. +#[cfg(feature = "async")] unsafe fn assume_init_bytes(slice: &[MaybeUninit<u8>]) -> &[u8] { &*(slice as *const [MaybeUninit<u8>] as *const [u8]) } diff --git a/tvix/nix-compat/src/wire/bytes/reader/mod.rs b/tvix/nix-compat/src/wire/bytes/reader/mod.rs index 81474df70657..77950496ed6b 100644 --- a/tvix/nix-compat/src/wire/bytes/reader/mod.rs +++ b/tvix/nix-compat/src/wire/bytes/reader/mod.rs @@ -109,8 +109,6 @@ where } /// Remaining data length, ie not including data already read. - /// - /// If the size has not been read yet, this is [None]. pub fn len(&self) -> u64 { match self.state { State::Body { diff --git a/tvix/serde/Cargo.toml b/tvix/serde/Cargo.toml index 5652126ada1d..fc5f08a2ddcd 100644 --- a/tvix/serde/Cargo.toml +++ b/tvix/serde/Cargo.toml @@ -5,5 +5,5 @@ edition = "2021" [dependencies] tvix-eval = { path = "../eval" } -serde = { version = "1.0", features = ["derive"] } -bstr = { version = "1.8.0", features = ["serde"] } +serde = { workspace = true, features = ["derive"] } +bstr = { workspace = true, features = ["serde"] } diff --git a/tvix/shell.nix b/tvix/shell.nix index 947cda269b2f..d6b4bb7d3458 100644 --- a/tvix/shell.nix +++ b/tvix/shell.nix @@ -10,13 +10,6 @@ depot.third_party.sources = import ./sources { }; additionalOverlays = [ (self: super: { - # https://github.com/googleapis/google-cloud-go/pull/9665 - cbtemulator = super.cbtemulator.overrideAttrs (old: { - patches = old.patches or [ ] ++ [ - ./nixpkgs/cbtemulator-uds.patch - ]; - }); - # macFUSE bump containing fix for https://github.com/osxfuse/osxfuse/issues/974 # https://github.com/NixOS/nixpkgs/pull/320197 fuse = diff --git a/tvix/store/Cargo.toml b/tvix/store/Cargo.toml index 0cbaa102f051..9d54ad1ea760 100644 --- a/tvix/store/Cargo.toml +++ b/tvix/store/Cargo.toml @@ -4,68 +4,62 @@ version = "0.1.0" edition = "2021" [dependencies] -anyhow = "1.0.68" -async-compression = { version = "0.4.9", features = ["tokio", "bzip2", "gzip", "xz", "zstd"]} -async-stream = "0.3.5" -blake3 = { version = "1.3.1", features = ["rayon", "std"] } -bstr = "1.6.0" -bytes = "1.4.0" -clap = { version = "4.0", features = ["derive", "env"] } -count-write = "0.1.0" -data-encoding = "2.6.0" -futures = "0.3.30" -lazy_static = "1.4.0" +anyhow = { workspace = true } +async-compression = { workspace = true, features = ["tokio", "bzip2", "gzip", "xz", "zstd"] } +async-stream = { workspace = true } +blake3 = { workspace = true, features = ["rayon", "std"] } +bstr = { workspace = true } +bytes = { workspace = true } +clap = { workspace = true, features = ["derive", "env"] } +count-write = { workspace = true } +data-encoding = { workspace = true } +futures = { workspace = true } +lazy_static = { workspace = true } nix-compat = { path = "../nix-compat", features = ["async"] } -pin-project-lite = "0.2.13" -prost = "0.13.1" -serde = { version = "1.0.197", features = [ "derive" ] } -serde_json = "1.0" -serde_with = "3.7.0" -serde_qs = "0.12.0" -sha2 = "0.10.6" -sled = { version = "0.34.7" } -thiserror = "1.0.38" -tokio = { version = "1.32.0", features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } -tokio-listener = { version = "0.4.2", features = [ "clap", "multi-listener", "sd_listen", "tonic012" ] } -tokio-stream = { version = "0.1.14", features = ["fs"] } -tokio-util = { version = "0.7.9", features = ["io", "io-util", "compat"] } -tonic = { version = "0.12.0", features = ["tls", "tls-roots"] } -tower = "0.4.13" -tower-http = { version = "0.5.0", features = ["trace"] } +pin-project-lite = { workspace = true } +prost = { workspace = true } +serde = { workspace = true, features = ["derive"] } +serde_json = { workspace = true } +serde_with = { workspace = true } +serde_qs = { workspace = true } +sha2 = { workspace = true } +sled = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal"] } +tokio-listener = { workspace = true, features = ["clap", "multi-listener", "sd_listen", "tonic012"] } +tokio-stream = { workspace = true, features = ["fs"] } +tokio-util = { workspace = true, features = ["io", "io-util", "compat"] } +tonic = { workspace = true, features = ["tls", "tls-roots"] } +tower = { workspace = true } +tower-http = { workspace = true, features = ["trace"] } tvix-castore = { path = "../castore" } -url = "2.4.0" -walkdir = "2.4.0" -reqwest = { version = "0.12.0", features = ["rustls-tls-native-roots", "stream"], default-features = false } -reqwest-middleware = "0.3.0" -lru = "0.12.3" -parking_lot = "0.12.2" +url = { workspace = true } +walkdir = { workspace = true } +reqwest = { workspace = true, features = ["rustls-tls-native-roots", "stream"] } +reqwest-middleware = { workspace = true } +lru = { workspace = true } +parking_lot = { workspace = true } tvix-tracing = { path = "../tracing", features = ["tonic", "reqwest"] } -tracing = "0.1.40" -tracing-indicatif = "0.3.6" -hyper-util = "0.1.6" -toml = { version = "0.8.15", optional = true } -tonic-health = { version = "0.12.1", default-features = false } -redb = "2.1.1" -mimalloc = "0.1.43" - -[dependencies.tonic-reflection] -optional = true -version = "0.12.0" - -[dependencies.bigtable_rs] -optional = true -version = "0.2.10" +tracing = { workspace = true } +tracing-indicatif = { workspace = true } +hyper-util = { workspace = true } +toml = { version = "0.8.19", optional = true } +tonic-health = { workspace = true } +redb = { workspace = true } +mimalloc = { workspace = true } +tonic-reflection = { workspace = true, optional = true } +bigtable_rs = { workspace = true, optional = true } [build-dependencies] -prost-build = "0.13.1" -tonic-build = "0.12.0" +prost-build = { workspace = true } +tonic-build = { workspace = true } [dev-dependencies] -async-process = "2.1.0" -rstest = "0.19.0" -rstest_reuse = "0.6.0" -tempfile = "3.3.0" -tokio-retry = "0.3.0" +async-process = { workspace = true } +rstest = { workspace = true } +rstest_reuse = { workspace = true } +tempfile = { workspace = true } +tokio-retry = { workspace = true } [features] default = ["cloud", "fuse", "otlp", "tonic-reflection"] diff --git a/tvix/store/build.rs b/tvix/store/build.rs index 8a92ab26fd64..4e0371311220 100644 --- a/tvix/store/build.rs +++ b/tvix/store/build.rs @@ -25,7 +25,7 @@ fn main() -> Result<()> { ], // If we are in running `cargo build` manually, using `../..` works fine, // but in case we run inside a nix build, we need to instead point PROTO_ROOT - // to a sparseTree containing that structure. + // to a custom tree containing that structure. &[match std::env::var_os("PROTO_ROOT") { Some(proto_root) => proto_root.to_str().unwrap().to_owned(), None => "../..".to_string(), diff --git a/tvix/store/default.nix b/tvix/store/default.nix index b8541d072224..863ddb6de23f 100644 --- a/tvix/store/default.nix +++ b/tvix/store/default.nix @@ -35,7 +35,7 @@ in targets = [ "integration-tests" ] ++ lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); extraSteps.import-docs = (mkImportCheck "tvix/docs/src/store" ../docs/src/store); }; - passthru = (depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = ([ "cloud" "fuse" "otlp" "tonic-reflection" "xp-store-composition" ] # virtiofs feature currently fails to build on Darwin diff --git a/tvix/store/protos/default.nix b/tvix/store/protos/default.nix index 56345d9338b2..005a2697e5e9 100644 --- a/tvix/store/protos/default.nix +++ b/tvix/store/protos/default.nix @@ -1,17 +1,12 @@ -{ depot, pkgs, ... }: +{ depot, pkgs, lib, ... }: let - protos = depot.nix.sparseTree { - name = "store-protos"; - root = depot.path.origSrc; - paths = [ - # We need to include castore.proto (only), as it's referred. - ../../castore/protos/castore.proto - ./pathinfo.proto - ./rpc_pathinfo.proto - ../../../buf.yaml - ../../../buf.gen.yaml - ]; - }; + protos = lib.sourceByRegex depot.path.origSrc [ + "buf.yaml" + "buf.gen.yaml" + # We need to include castore.proto (only), as it's referred. + "^tvix(/castore(/protos(/castore\.proto)?)?)?$" + "^tvix(/store(/protos(/.*\.proto)?)?)?$" + ]; in depot.nix.readTree.drvTargets { inherit protos; diff --git a/tvix/store/src/bin/tvix-store.rs b/tvix/store/src/bin/tvix-store.rs index d639a6e9d78d..6da239a8fee3 100644 --- a/tvix/store/src/bin/tvix-store.rs +++ b/tvix/store/src/bin/tvix-store.rs @@ -201,11 +201,18 @@ async fn run_cli(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync #[cfg(feature = "tonic-reflection")] { - let reflection_svc = tonic_reflection::server::Builder::configure() - .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) - .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) - .build()?; - router = router.add_service(reflection_svc); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1alpha()?, + ); + router = router.add_service( + tonic_reflection::server::Builder::configure() + .register_encoded_file_descriptor_set(CASTORE_FILE_DESCRIPTOR_SET) + .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) + .build_v1()?, + ); } let listen_address = &listen_args.listen_address.unwrap_or_else(|| { @@ -351,9 +358,10 @@ async fn run_cli(cli: Cli) -> Result<(), Box<dyn std::error::Error + Send + Sync // Create and upload a PathInfo pointing to the root_node, // annotated with information we have from the reference graph. let path_info = PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node), - }), + node: Some(tvix_castore::proto::Node::from_name_and_node( + elem.path.to_string().into(), + root_node, + )), references: Vec::from_iter( elem.references.iter().map(|e| e.digest().to_vec().into()), ), diff --git a/tvix/store/src/import.rs b/tvix/store/src/import.rs index 70a97982e642..1719669a4285 100644 --- a/tvix/store/src/import.rs +++ b/tvix/store/src/import.rs @@ -1,13 +1,14 @@ +use bstr::ByteSlice; use std::path::Path; use tracing::{debug, instrument}; use tvix_castore::{ - blobservice::BlobService, directoryservice::DirectoryService, import::fs::ingest_path, - proto::node::Node, B3Digest, + blobservice::BlobService, directoryservice::DirectoryService, import::fs::ingest_path, Node, + PathComponent, }; use nix_compat::{ nixhash::{CAHash, NixHash}, - store_path::{self, StorePath}, + store_path::{self, StorePathRef}, }; use crate::{ @@ -27,29 +28,29 @@ impl From<CAHash> for nar_info::Ca { } } -pub fn log_node(node: &Node, path: &Path) { +pub fn log_node(name: &[u8], node: &Node, path: &Path) { match node { - Node::Directory(directory_node) => { + Node::Directory { digest, .. } => { debug!( path = ?path, - name = ?directory_node.name, - digest = %B3Digest::try_from(directory_node.digest.clone()).unwrap(), + name = %name.as_bstr(), + digest = %digest, "import successful", ) } - Node::File(file_node) => { + Node::File { digest, .. } => { debug!( path = ?path, - name = ?file_node.name, - digest = %B3Digest::try_from(file_node.digest.clone()).unwrap(), + name = %name.as_bstr(), + digest = %digest, "import successful" ) } - Node::Symlink(symlink_node) => { + Node::Symlink { target } => { debug!( path = ?path, - name = ?symlink_node.name, - target = ?symlink_node.target, + name = %name.as_bstr(), + target = ?target, "import successful" ) } @@ -82,13 +83,14 @@ pub fn derive_nar_ca_path_info( nar_size: u64, nar_sha256: [u8; 32], ca: Option<&CAHash>, + name: bytes::Bytes, root_node: Node, ) -> PathInfo { // assemble the [crate::proto::PathInfo] object. PathInfo { - node: Some(tvix_castore::proto::Node { - node: Some(root_node), - }), + node: Some(tvix_castore::proto::Node::from_name_and_node( + name, root_node, + )), // There's no reference scanning on path contents ingested like this. references: vec![], narinfo: Some(NarInfo { @@ -113,7 +115,7 @@ pub async fn import_path_as_nar_ca<BS, DS, PS, NS, P>( directory_service: DS, path_info_service: PS, nar_calculation_service: NS, -) -> Result<StorePath, std::io::Error> +) -> Result<StorePathRef, std::io::Error> where P: AsRef<Path> + std::fmt::Debug, BS: BlobService + Clone, @@ -138,14 +140,19 @@ where ) })?; - // rename the root node to match the calculated output path. - let root_node = root_node.rename(output_path.to_string().into_bytes().into()); - log_node(&root_node, path.as_ref()); + let name: PathComponent = output_path + .to_string() + .as_str() + .try_into() + .expect("Tvix bug: StorePath must be PathComponent"); + + log_node(name.as_ref(), &root_node, path.as_ref()); let path_info = derive_nar_ca_path_info( nar_size, nar_sha256, Some(&CAHash::Nar(NixHash::Sha256(nar_sha256))), + name.into(), root_node, ); @@ -154,7 +161,7 @@ where // callers don't really need it. let _path_info = path_info_service.as_ref().put(path_info).await?; - Ok(output_path.to_owned()) + Ok(output_path) } #[cfg(test)] diff --git a/tvix/store/src/nar/import.rs b/tvix/store/src/nar/import.rs index 32c2f4e58061..b9a15fe71384 100644 --- a/tvix/store/src/nar/import.rs +++ b/tvix/store/src/nar/import.rs @@ -12,8 +12,7 @@ use tvix_castore::{ blobs::{self, ConcurrentBlobUploader}, ingest_entries, IngestionEntry, IngestionError, }, - proto::{node::Node, NamedNode}, - PathBuf, + Node, PathBuf, }; /// Ingests the contents from a [AsyncRead] providing NAR into the tvix store, @@ -98,9 +97,7 @@ where let (_, node) = try_join!(produce, consume)?; - // remove the fake "root" name again - debug_assert_eq!(&node.get_name(), b"root"); - Ok(node.rename("".into())) + Ok(node) } async fn produce_nar_inner<BS>( @@ -177,7 +174,7 @@ mod test { DIRECTORY_COMPLICATED, DIRECTORY_WITH_KEEP, EMPTY_BLOB_DIGEST, HELLOWORLD_BLOB_CONTENTS, HELLOWORLD_BLOB_DIGEST, }; - use tvix_castore::proto as castorepb; + use tvix_castore::{Directory, Node}; use crate::tests::fixtures::{ blob_service, directory_service, NAR_CONTENTS_COMPLICATED, NAR_CONTENTS_HELLOWORLD, @@ -199,10 +196,9 @@ mod test { .expect("must parse"); assert_eq!( - castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "".into(), // name must be empty - target: "/nix/store/somewhereelse".into(), - }), + Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap() + }, root_node ); } @@ -222,12 +218,11 @@ mod test { .expect("must parse"); assert_eq!( - castorepb::node::Node::File(castorepb::FileNode { - name: "".into(), // name must be empty - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, root_node ); @@ -250,11 +245,10 @@ mod test { .expect("must parse"); assert_eq!( - castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "".into(), // name must be empty - digest: DIRECTORY_COMPLICATED.digest().into(), - size: DIRECTORY_COMPLICATED.size(), - }), + Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), + size: DIRECTORY_COMPLICATED.size() + }, root_node, ); @@ -262,7 +256,7 @@ mod test { assert!(blob_service.has(&EMPTY_BLOB_DIGEST).await.unwrap()); // directoryservice must contain the directories, at least with get_recursive. - let resp: Result<Vec<castorepb::Directory>, _> = directory_service + let resp: Result<Vec<Directory>, _> = directory_service .get_recursive(&DIRECTORY_COMPLICATED.digest()) .collect() .await; diff --git a/tvix/store/src/nar/mod.rs b/tvix/store/src/nar/mod.rs index 8cbb091f1aab..da798bbf3a3c 100644 --- a/tvix/store/src/nar/mod.rs +++ b/tvix/store/src/nar/mod.rs @@ -8,16 +8,14 @@ pub use import::ingest_nar_and_hash; pub use renderer::calculate_size_and_sha256; pub use renderer::write_nar; pub use renderer::SimpleRenderer; -use tvix_castore::proto as castorepb; +use tvix_castore::Node; #[async_trait] pub trait NarCalculationService: Send + Sync { /// Return the nar size and nar sha256 digest for a given root node. /// This can be used to calculate NAR-based output paths. - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), tvix_castore::Error>; + async fn calculate_nar(&self, root_node: &Node) + -> Result<(u64, [u8; 32]), tvix_castore::Error>; } #[async_trait] @@ -27,7 +25,7 @@ where { async fn calculate_nar( &self, - root_node: &castorepb::node::Node, + root_node: &Node, ) -> Result<(u64, [u8; 32]), tvix_castore::Error> { self.as_ref().calculate_nar(root_node).await } @@ -39,13 +37,13 @@ pub enum RenderError { #[error("failure talking to a backing store client: {0}")] StoreError(#[source] std::io::Error), - #[error("unable to find directory {}, referred from {:?}", .0, .1)] + #[error("unable to find directory {0}, referred from {1:?}")] DirectoryNotFound(B3Digest, bytes::Bytes), - #[error("unable to find blob {}, referred from {:?}", .0, .1)] + #[error("unable to find blob {0}, referred from {1:?}")] BlobNotFound(B3Digest, bytes::Bytes), - #[error("unexpected size in metadata for blob {}, referred from {:?} returned, expected {}, got {}", .0, .1, .2, .3)] + #[error("unexpected size in metadata for blob {0}, referred from {1:?} returned, expected {2}, got {3}")] UnexpectedBlobMeta(B3Digest, bytes::Bytes, u32, u32), #[error("failure using the NAR writer: {0}")] diff --git a/tvix/store/src/nar/renderer.rs b/tvix/store/src/nar/renderer.rs index e3cb54dd229f..afd85f267c6c 100644 --- a/tvix/store/src/nar/renderer.rs +++ b/tvix/store/src/nar/renderer.rs @@ -8,11 +8,7 @@ use tokio::io::{self, AsyncWrite, BufReader}; use tonic::async_trait; use tracing::{instrument, Span}; use tracing_indicatif::span_ext::IndicatifSpanExt; -use tvix_castore::{ - blobservice::BlobService, - directoryservice::DirectoryService, - proto::{self as castorepb, NamedNode}, -}; +use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService, Node}; pub struct SimpleRenderer<BS, DS> { blob_service: BS, @@ -36,7 +32,7 @@ where { async fn calculate_nar( &self, - root_node: &castorepb::node::Node, + root_node: &Node, ) -> Result<(u64, [u8; 32]), tvix_castore::Error> { calculate_size_and_sha256( root_node, @@ -52,7 +48,7 @@ where /// NAR output. #[instrument(skip_all, fields(indicatif.pb_show=1))] pub async fn calculate_size_and_sha256<BS, DS>( - root_node: &castorepb::node::Node, + root_node: &Node, blob_service: BS, directory_service: DS, ) -> Result<(u64, [u8; 32]), RenderError> @@ -80,13 +76,13 @@ where Ok((cw.count(), h.finalize().into())) } -/// Accepts a [castorepb::node::Node] pointing to the root of a (store) path, +/// Accepts a [Node] pointing to the root of a (store) path, /// and uses the passed blob_service and directory_service to perform the /// necessary lookups as it traverses the structure. /// The contents in NAR serialization are writen to the passed [AsyncWrite]. pub async fn write_nar<W, BS, DS>( mut w: W, - proto_root_node: &castorepb::node::Node, + root_node: &Node, blob_service: BS, directory_service: DS, ) -> Result<(), RenderError> @@ -102,7 +98,8 @@ where walk_node( nar_root_node, - proto_root_node, + root_node, + b"", blob_service, directory_service, ) @@ -115,7 +112,8 @@ where /// This consumes the node. async fn walk_node<BS, DS>( nar_node: nar_writer::Node<'_, '_>, - proto_node: &castorepb::node::Node, + castore_node: &Node, + name: &[u8], blob_service: BS, directory_service: DS, ) -> Result<(BS, DS), RenderError> @@ -123,24 +121,20 @@ where BS: BlobService + Send, DS: DirectoryService + Send, { - match proto_node { - castorepb::node::Node::Symlink(proto_symlink_node) => { + match castore_node { + Node::Symlink { target, .. } => { nar_node - .symlink(&proto_symlink_node.target) + .symlink(target.as_ref()) .await .map_err(RenderError::NARWriterError)?; } - castorepb::node::Node::File(proto_file_node) => { - let digest_len = proto_file_node.digest.len(); - let digest = proto_file_node.digest.clone().try_into().map_err(|_| { - RenderError::StoreError(io::Error::new( - io::ErrorKind::Other, - format!("invalid digest len {} in file node", digest_len), - )) - })?; - + Node::File { + digest, + size, + executable, + } => { let mut blob_reader = match blob_service - .open_read(&digest) + .open_read(digest) .await .map_err(RenderError::StoreError)? { @@ -152,39 +146,23 @@ where }?; nar_node - .file( - proto_file_node.executable, - proto_file_node.size, - &mut blob_reader, - ) + .file(*executable, *size, &mut blob_reader) .await .map_err(RenderError::NARWriterError)?; } - castorepb::node::Node::Directory(proto_directory_node) => { - let digest_len = proto_directory_node.digest.len(); - let digest = proto_directory_node - .digest - .clone() - .try_into() - .map_err(|_| { - RenderError::StoreError(io::Error::new( - io::ErrorKind::InvalidData, - format!("invalid digest len {} in directory node", digest_len), - )) - })?; - + Node::Directory { digest, .. } => { // look it up with the directory service match directory_service - .get(&digest) + .get(digest) .await .map_err(|e| RenderError::StoreError(e.into()))? { // if it's None, that's an error! None => Err(RenderError::DirectoryNotFound( - digest, - proto_directory_node.name.clone(), + digest.clone(), + bytes::Bytes::copy_from_slice(name), ))?, - Some(proto_directory) => { + Some(directory) => { // start a directory node let mut nar_node_directory = nar_node .directory() @@ -198,15 +176,16 @@ where // for each node in the directory, create a new entry with its name, // and then recurse on that entry. - for proto_node in proto_directory.nodes() { + for (name, node) in directory.nodes() { let child_node = nar_node_directory - .entry(proto_node.get_name()) + .entry(name.as_ref()) .await .map_err(RenderError::NARWriterError)?; (blob_service, directory_service) = Box::pin(walk_node( child_node, - &proto_node, + node, + name.as_ref(), blob_service, directory_service, )) diff --git a/tvix/store/src/pathinfoservice/fs/mod.rs b/tvix/store/src/pathinfoservice/fs/mod.rs index aa64b1c01f16..1f7fa8a8afce 100644 --- a/tvix/store/src/pathinfoservice/fs/mod.rs +++ b/tvix/store/src/pathinfoservice/fs/mod.rs @@ -1,10 +1,10 @@ use futures::stream::BoxStream; use futures::StreamExt; +use nix_compat::store_path::StorePathRef; use tonic::async_trait; use tvix_castore::fs::{RootNodes, TvixStoreFs}; -use tvix_castore::proto as castorepb; -use tvix_castore::Error; use tvix_castore::{blobservice::BlobService, directoryservice::DirectoryService}; +use tvix_castore::{Error, Node, PathComponent}; use super::PathInfoService; @@ -48,8 +48,8 @@ impl<T> RootNodes for RootNodesWrapper<T> where T: AsRef<dyn PathInfoService> + Send + Sync, { - async fn get_by_basename(&self, name: &[u8]) -> Result<Option<castorepb::node::Node>, Error> { - let Ok(store_path) = nix_compat::store_path::StorePath::from_bytes(name) else { + async fn get_by_basename(&self, name: &PathComponent) -> Result<Option<Node>, Error> { + let Ok(store_path) = StorePathRef::from_bytes(name.as_ref()) else { return Ok(None); }; @@ -59,22 +59,31 @@ where .get(*store_path.digest()) .await? .map(|path_info| { - path_info + let node = path_info .node + .as_ref() .expect("missing root node") - .node - .expect("empty node") - })) + .to_owned(); + + match node.into_name_and_node() { + Ok((_name, node)) => Ok(node), + Err(e) => Err(Error::StorageError(e.to_string())), + } + }) + .transpose()?) } - fn list(&self) -> BoxStream<Result<castorepb::node::Node, Error>> { + fn list(&self) -> BoxStream<Result<(PathComponent, Node), Error>> { Box::pin(self.0.as_ref().list().map(|result| { - result.map(|path_info| { - path_info + result.and_then(|path_info| { + let node = path_info .node + .as_ref() .expect("missing root node") - .node - .expect("empty node") + .to_owned(); + + node.into_name_and_node() + .map_err(|e| Error::StorageError(e.to_string())) }) })) } diff --git a/tvix/store/src/pathinfoservice/grpc.rs b/tvix/store/src/pathinfoservice/grpc.rs index 2ac0e43303cb..7510ccd911f0 100644 --- a/tvix/store/src/pathinfoservice/grpc.rs +++ b/tvix/store/src/pathinfoservice/grpc.rs @@ -11,7 +11,8 @@ use tonic::{async_trait, Code}; use tracing::{instrument, Span}; use tracing_indicatif::span_ext::IndicatifSpanExt; use tvix_castore::composition::{CompositionContext, ServiceBuilder}; -use tvix_castore::{proto as castorepb, Error}; +use tvix_castore::Error; +use tvix_castore::Node; /// Connects to a (remote) tvix-store PathInfoService over gRPC. #[derive(Clone)] @@ -123,10 +124,7 @@ where T::Future: Send, { #[instrument(level = "trace", skip_all, fields(root_node = ?root_node, indicatif.pb_show=1))] - async fn calculate_nar( - &self, - root_node: &castorepb::node::Node, - ) -> Result<(u64, [u8; 32]), Error> { + async fn calculate_nar(&self, root_node: &Node) -> Result<(u64, [u8; 32]), Error> { let span = Span::current(); span.pb_set_message("Waiting for NAR calculation"); span.pb_start(); @@ -134,9 +132,10 @@ where let path_info = self .grpc_client .clone() - .calculate_nar(castorepb::Node { - node: Some(root_node.clone()), - }) + .calculate_nar(tvix_castore::proto::Node::from_name_and_node( + "".into(), + root_node.to_owned(), + )) .await .map_err(|e| Error::StorageError(e.to_string()))? .into_inner(); diff --git a/tvix/store/src/pathinfoservice/lru.rs b/tvix/store/src/pathinfoservice/lru.rs index 39c592bc96fb..695c04636089 100644 --- a/tvix/store/src/pathinfoservice/lru.rs +++ b/tvix/store/src/pathinfoservice/lru.rs @@ -108,8 +108,17 @@ mod test { let mut p = PATHINFO_1.clone(); let root_node = p.node.as_mut().unwrap(); if let castorepb::Node { node: Some(node) } = root_node { - let n = node.to_owned(); - *node = n.rename("11111111111111111111111111111111-dummy2".into()); + match node { + castorepb::node::Node::Directory(n) => { + n.name = "11111111111111111111111111111111-dummy2".into() + } + castorepb::node::Node::File(n) => { + n.name = "11111111111111111111111111111111-dummy2".into() + } + castorepb::node::Node::Symlink(n) => { + n.name = "11111111111111111111111111111111-dummy2".into() + } + } } else { unreachable!() } diff --git a/tvix/store/src/pathinfoservice/nix_http.rs b/tvix/store/src/pathinfoservice/nix_http.rs index a2756033172f..5f1eed1a0a9f 100644 --- a/tvix/store/src/pathinfoservice/nix_http.rs +++ b/tvix/store/src/pathinfoservice/nix_http.rs @@ -228,10 +228,10 @@ where } Ok(Some(PathInfo { - node: Some(castorepb::Node { - // set the name of the root node to the digest-name of the store path. - node: Some(root_node.rename(narinfo.store_path.to_string().to_owned().into())), - }), + node: Some(castorepb::Node::from_name_and_node( + narinfo.store_path.to_string().into(), + root_node, + )), references: pathinfo.references, narinfo: pathinfo.narinfo, })) diff --git a/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs index 68f557567629..60da73012df7 100644 --- a/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs +++ b/tvix/store/src/proto/grpc_pathinfoservice_wrapper.rs @@ -74,24 +74,19 @@ where &self, request: Request<castorepb::Node>, ) -> Result<Response<proto::CalculateNarResponse>> { - match request.into_inner().node { - None => Err(Status::invalid_argument("no root node sent")), - Some(root_node) => { - if let Err(e) = root_node.validate() { - warn!(err = %e, "invalid root node"); - Err(Status::invalid_argument("invalid root node"))? - } + let (_, root_node) = request.into_inner().into_name_and_node().map_err(|e| { + warn!(err = %e, "invalid root node"); + Status::invalid_argument("invalid root node") + })?; - match self.nar_calculation_service.calculate_nar(&root_node).await { - Ok((nar_size, nar_sha256)) => Ok(Response::new(proto::CalculateNarResponse { - nar_size, - nar_sha256: nar_sha256.to_vec().into(), - })), - Err(e) => { - warn!(err = %e, "error during NAR calculation"); - Err(e.into()) - } - } + match self.nar_calculation_service.calculate_nar(&root_node).await { + Ok((nar_size, nar_sha256)) => Ok(Response::new(proto::CalculateNarResponse { + nar_size, + nar_sha256: nar_sha256.to_vec().into(), + })), + Err(e) => { + warn!(err = %e, "error during NAR calculation"); + Err(e.into()) } } } diff --git a/tvix/store/src/proto/mod.rs b/tvix/store/src/proto/mod.rs index b45e6fda46fe..f3ea4b196946 100644 --- a/tvix/store/src/proto/mod.rs +++ b/tvix/store/src/proto/mod.rs @@ -9,7 +9,7 @@ use nix_compat::{ store_path::{self, StorePathRef}, }; use thiserror::Error; -use tvix_castore::proto::{self as castorepb, NamedNode, ValidateNodeError}; +use tvix_castore::DirectoryError; mod grpc_pathinfoservice_wrapper; @@ -39,7 +39,7 @@ pub enum ValidatePathInfoError { /// Node fails validation #[error("Invalid root node: {:?}", .0.to_string())] - InvalidRootNode(ValidateNodeError), + InvalidRootNode(DirectoryError), /// Invalid node name encountered. Root nodes in PathInfos have more strict name requirements #[error("Failed to parse {} as StorePath: {1}", .0.to_str_lossy())] @@ -87,7 +87,7 @@ impl PathInfo { /// validate performs some checks on the PathInfo struct, /// Returning either a [store_path::StorePath] of the root node, or a /// [ValidatePathInfoError]. - pub fn validate(&self) -> Result<store_path::StorePathRef<'_>, ValidatePathInfoError> { + pub fn validate(&self) -> Result<store_path::StorePath<String>, ValidatePathInfoError> { // ensure the references have the right number of bytes. for (i, reference) in self.references.iter().enumerate() { if reference.len() != store_path::DIGEST_SIZE { @@ -118,7 +118,7 @@ impl PathInfo { // parse references in reference_names. for (i, reference_name_str) in narinfo.reference_names.iter().enumerate() { // ensure thy parse as (non-absolute) store path - let reference_names_store_path = store_path::StorePath::from_bytes( + let reference_names_store_path = store_path::StorePathRef::from_bytes( reference_name_str.as_bytes(), ) .map_err(|_| { @@ -158,14 +158,20 @@ impl PathInfo { // Ensure there is a (root) node present, and it properly parses to a [store_path::StorePath]. let root_nix_path = match &self.node { - None | Some(castorepb::Node { node: None }) => { - Err(ValidatePathInfoError::NoNodePresent)? - } - Some(castorepb::Node { node: Some(node) }) => { - node.validate() + None => Err(ValidatePathInfoError::NoNodePresent)?, + Some(node) => { + // NOTE: We could have some PathComponent not allocating here, + // so this can return StorePathRef. + // However, as this will get refactored away to stricter types + // soon anyways, there's no point. + let (name, _node) = node + .clone() + .into_name_and_node() .map_err(ValidatePathInfoError::InvalidRootNode)?; + // parse the name of the node itself and return - parse_node_name_root(node.get_name(), ValidatePathInfoError::InvalidNodeName)? + parse_node_name_root(name.as_ref(), ValidatePathInfoError::InvalidNodeName)? + .to_owned() } }; @@ -219,7 +225,7 @@ impl PathInfo { .signatures .iter() .map(|sig| { - nix_compat::narinfo::Signature::new( + nix_compat::narinfo::SignatureRef::new( &sig.name, // This shouldn't pass validation sig.data[..].try_into().expect("invalid signature len"), @@ -354,7 +360,7 @@ impl From<&nix_compat::narinfo::NarInfo<'_>> for NarInfo { signatures, reference_names: value.references.iter().map(|r| r.to_string()).collect(), deriver: value.deriver.as_ref().map(|sp| StorePath { - name: sp.name().to_owned(), + name: (*sp.name()).to_owned(), digest: Bytes::copy_from_slice(sp.digest()), }), ca: value.ca.as_ref().map(|ca| ca.into()), diff --git a/tvix/store/src/proto/tests/pathinfo.rs b/tvix/store/src/proto/tests/pathinfo.rs index 4d0834878d7c..eb47e592be8c 100644 --- a/tvix/store/src/proto/tests/pathinfo.rs +++ b/tvix/store/src/proto/tests/pathinfo.rs @@ -3,17 +3,18 @@ use crate::tests::fixtures::*; use bytes::Bytes; use data_encoding::BASE64; use nix_compat::nixbase32; -use nix_compat::store_path::{self, StorePathRef}; +use nix_compat::store_path::{self, StorePath, StorePathRef}; use rstest::rstest; use tvix_castore::proto as castorepb; +use tvix_castore::{DirectoryError, ValidateNodeError}; #[rstest] #[case::no_node(None, Err(ValidatePathInfoError::NoNodePresent))] -#[case::no_node_2(Some(castorepb::Node { node: None}), Err(ValidatePathInfoError::NoNodePresent))] +#[case::no_node_2(Some(castorepb::Node { node: None}), Err(ValidatePathInfoError::InvalidRootNode(DirectoryError::NoNodeSet)))] fn validate_pathinfo( #[case] node: Option<castorepb::Node>, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, + #[case] exp_result: Result<StorePath<String>, ValidatePathInfoError>, ) { // construct the PathInfo object let p = PathInfo { @@ -22,9 +23,6 @@ fn validate_pathinfo( }; assert_eq!(exp_result, p.validate()); - - let err = p.validate().expect_err("validation should fail"); - assert!(matches!(err, ValidatePathInfoError::NoNodePresent)); } #[rstest] @@ -32,12 +30,12 @@ fn validate_pathinfo( name: DUMMY_PATH.into(), digest: DUMMY_DIGEST.clone().into(), size: 0, -}, Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()))] +}, Ok(StorePath::from_bytes(DUMMY_PATH.as_bytes()).unwrap()))] #[case::invalid_digest_length(castorepb::DirectoryNode { name: DUMMY_PATH.into(), digest: Bytes::new(), size: 0, -}, Err(ValidatePathInfoError::InvalidRootNode(castorepb::ValidateNodeError::InvalidDigestLen(0))))] +}, Err(ValidatePathInfoError::InvalidRootNode(DirectoryError::InvalidNode(DUMMY_PATH.try_into().unwrap(), ValidateNodeError::InvalidDigestLen(0)))))] #[case::invalid_node_name_no_storepath(castorepb::DirectoryNode { name: "invalid".into(), digest: DUMMY_DIGEST.clone().into(), @@ -48,7 +46,7 @@ fn validate_pathinfo( )))] fn validate_directory( #[case] directory_node: castorepb::DirectoryNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, + #[case] exp_result: Result<StorePath<String>, ValidatePathInfoError>, ) { // construct the PathInfo object let p = PathInfo { @@ -68,7 +66,7 @@ fn validate_directory( size: 0, executable: false, }, - Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) + Ok(StorePath::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) )] #[case::invalid_digest_len( castorepb::FileNode { @@ -76,7 +74,7 @@ fn validate_directory( digest: Bytes::new(), ..Default::default() }, - Err(ValidatePathInfoError::InvalidRootNode(castorepb::ValidateNodeError::InvalidDigestLen(0))) + Err(ValidatePathInfoError::InvalidRootNode(DirectoryError::InvalidNode(DUMMY_PATH.try_into().unwrap(), ValidateNodeError::InvalidDigestLen(0)))) )] #[case::invalid_node_name( castorepb::FileNode { @@ -91,7 +89,7 @@ fn validate_directory( )] fn validate_file( #[case] file_node: castorepb::FileNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, + #[case] exp_result: Result<StorePath<String>, ValidatePathInfoError>, ) { // construct the PathInfo object let p = PathInfo { @@ -109,7 +107,7 @@ fn validate_file( name: DUMMY_PATH.into(), target: "foo".into(), }, - Ok(StorePathRef::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) + Ok(StorePath::from_bytes(DUMMY_PATH.as_bytes()).unwrap()) )] #[case::invalid_node_name( castorepb::SymlinkNode { @@ -123,7 +121,7 @@ fn validate_file( )] fn validate_symlink( #[case] symlink_node: castorepb::SymlinkNode, - #[case] exp_result: Result<StorePathRef, ValidatePathInfoError>, + #[case] exp_result: Result<StorePath<String>, ValidatePathInfoError>, ) { // construct the PathInfo object let p = PathInfo { @@ -228,24 +226,28 @@ fn validate_inconsistent_narinfo_reference_name_digest() { /// Create a node with an empty symlink target, and ensure it fails validation. #[test] fn validate_symlink_empty_target_invalid() { - let node = castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "foo".into(), - target: "".into(), - }); - - node.validate().expect_err("must fail validation"); + castorepb::Node { + node: Some(castorepb::node::Node::Symlink(castorepb::SymlinkNode { + name: "foo".into(), + target: "".into(), + })), + } + .into_name_and_node() + .expect_err("must fail validation"); } /// Create a node with a symlink target including null bytes, and ensure it /// fails validation. #[test] fn validate_symlink_target_null_byte_invalid() { - let node = castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "foo".into(), - target: "foo\0".into(), - }); - - node.validate().expect_err("must fail validation"); + castorepb::Node { + node: Some(castorepb::node::Node::Symlink(castorepb::SymlinkNode { + name: "foo".into(), + target: "foo\0".into(), + })), + } + .into_name_and_node() + .expect_err("must fail validation"); } /// Create a PathInfo with a correct deriver field and ensure it succeeds. diff --git a/tvix/store/src/tests/nar_renderer.rs b/tvix/store/src/tests/nar_renderer.rs index 8bfb5a72bb2f..03eaa28aaac8 100644 --- a/tvix/store/src/tests/nar_renderer.rs +++ b/tvix/store/src/tests/nar_renderer.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use tokio::io::sink; use tvix_castore::blobservice::BlobService; use tvix_castore::directoryservice::DirectoryService; -use tvix_castore::proto as castorepb; +use tvix_castore::Node; #[rstest] #[tokio::test] @@ -22,10 +22,9 @@ async fn single_symlink( write_nar( &mut buf, - &castorepb::node::Node::Symlink(castorepb::SymlinkNode { - name: "doesntmatter".into(), - target: "/nix/store/somewhereelse".into(), - }), + &Node::Symlink { + target: "/nix/store/somewhereelse".try_into().unwrap(), + }, // don't put anything in the stores, as we don't actually do any requests. blob_service, directory_service, @@ -45,12 +44,11 @@ async fn single_file_missing_blob( ) { let e = write_nar( sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + &Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, // the blobservice is empty intentionally, to provoke the error. blob_service, directory_service, @@ -90,12 +88,11 @@ async fn single_file_wrong_blob_size( // Test with a root FileNode of a too big size let e = write_nar( sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + &Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: 42, // <- note the wrong size here! executable: false, - }), + }, blob_service.clone(), directory_service.clone(), ) @@ -112,12 +109,11 @@ async fn single_file_wrong_blob_size( // Test with a root FileNode of a too small size let e = write_nar( sink(), - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + &Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: 2, // <- note the wrong size here! executable: false, - }), + }, blob_service, directory_service, ) @@ -153,12 +149,11 @@ async fn single_file( write_nar( &mut buf, - &castorepb::node::Node::File(castorepb::FileNode { - name: "doesntmatter".into(), - digest: HELLOWORLD_BLOB_DIGEST.clone().into(), + &Node::File { + digest: HELLOWORLD_BLOB_DIGEST.clone(), size: HELLOWORLD_BLOB_CONTENTS.len() as u64, executable: false, - }), + }, blob_service, directory_service, ) @@ -196,11 +191,10 @@ async fn test_complicated( write_nar( &mut buf, - &castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), + &Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), size: DIRECTORY_COMPLICATED.size(), - }), + }, blob_service.clone(), directory_service.clone(), ) @@ -211,11 +205,10 @@ async fn test_complicated( // ensure calculate_nar does return the correct sha256 digest and sum. let (nar_size, nar_digest) = calculate_size_and_sha256( - &castorepb::node::Node::Directory(castorepb::DirectoryNode { - name: "doesntmatter".into(), - digest: DIRECTORY_COMPLICATED.digest().into(), + &Node::Directory { + digest: DIRECTORY_COMPLICATED.digest(), size: DIRECTORY_COMPLICATED.size(), - }), + }, blob_service, directory_service, ) diff --git a/tvix/store/src/utils.rs b/tvix/store/src/utils.rs index c550ad365ed7..1385ece39f8a 100644 --- a/tvix/store/src/utils.rs +++ b/tvix/store/src/utils.rs @@ -29,6 +29,10 @@ pub struct CompositionConfigs { >, } +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases accessing data +/// directly locally, like the `tvix-store daemon` command. #[derive(clap::Parser, Clone)] pub struct ServiceUrls { #[arg( @@ -56,7 +60,10 @@ pub struct ServiceUrls { experimental_store_composition: Option<String>, } -/// like ServiceUrls, but with different clap defaults +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases accessing data +/// from another running tvix daemon, via gRPC. #[derive(clap::Parser, Clone)] pub struct ServiceUrlsGrpc { #[arg(long, env, default_value = "grpc+http://[::1]:8000")] @@ -73,7 +80,13 @@ pub struct ServiceUrlsGrpc { experimental_store_composition: Option<String>, } -/// like ServiceUrls, but with different clap defaults +/// Provides a set clap arguments to configure tvix-[ca]store services. +/// +/// This particular variant has defaults tailored for usecases keeping all data +/// in memory. +/// It's currently used in tvix-cli, as we don't really care about persistency +/// there yet, and using something else here might make some perf output harder +/// to interpret. #[derive(clap::Parser, Clone)] pub struct ServiceUrlsMemory { #[arg(long, env, default_value = "memory://")] diff --git a/tvix/tools/crunch-v2/Cargo.lock b/tvix/tools/crunch-v2/Cargo.lock index e1d25dc1d8f6..71f0516c844d 100644 --- a/tvix/tools/crunch-v2/Cargo.lock +++ b/tvix/tools/crunch-v2/Cargo.lock @@ -365,9 +365,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "bzip2" @@ -627,16 +627,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -999,9 +998,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.22" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1244,6 +1243,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "libredox" version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1343,6 +1352,15 @@ dependencies = [ ] [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1359,9 +1377,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1402,11 +1420,13 @@ version = "0.1.0" dependencies = [ "bitflags 2.4.1", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", "enum-primitive-derive", "glob", + "mimalloc", "nom", "num-traits", "pin-project-lite", @@ -1415,6 +1435,7 @@ dependencies = [ "sha2 0.10.8", "thiserror", "tokio", + "tracing", ] [[package]] @@ -1610,12 +1631,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" - -[[package]] name = "polars" version = "0.35.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2441,9 +2456,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -2763,10 +2778,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] [[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] name = "tracing-core" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3176,18 +3203,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.26" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", diff --git a/tvix/tools/crunch-v2/Cargo.nix b/tvix/tools/crunch-v2/Cargo.nix index 811fd4a5a5cc..5af8289a6720 100644 --- a/tvix/tools/crunch-v2/Cargo.nix +++ b/tvix/tools/crunch-v2/Cargo.nix @@ -207,6 +207,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -218,6 +219,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -234,6 +236,7 @@ rec { version = "0.2.16"; edition = "2018"; sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -249,6 +252,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -326,6 +330,7 @@ rec { version = "0.2.3"; edition = "2021"; sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -345,6 +350,7 @@ rec { version = "1.0.2"; edition = "2021"; sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; @@ -360,6 +366,7 @@ rec { version = "3.0.2"; edition = "2021"; sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -424,6 +431,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; "arrayref" = rec { @@ -455,6 +463,7 @@ rec { version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -490,6 +499,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -515,6 +525,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -541,6 +552,7 @@ rec { edition = "2021"; sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -792,6 +804,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -808,6 +821,7 @@ rec { version = "0.9.0"; edition = "2018"; sha256 = "1r4pf90s7d7lj1wdjhlnqa26vvbm6pnc33z138lxpnp9srpi2lj1"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -865,6 +879,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -1000,9 +1015,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.6.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0lnryqfiymbq5mfflfmbsqvfnw80kkh36nk5kpiscgxb9ac1cad1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -1100,6 +1115,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -1335,6 +1351,7 @@ rec { version = "0.9.5"; edition = "2021"; sha256 = "0vxb4d25mgk8y0phay7j078limx2553716ixsr1x5605k31j5h98"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -1357,6 +1374,7 @@ rec { version = "0.9.3"; edition = "2015"; sha256 = "0ii1ihpjb30fk38gdikm5wqlkmyr8k46fh4k2r8sagz5dng7ljhr"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -1384,6 +1402,7 @@ rec { version = "0.8.4"; edition = "2015"; sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -1446,6 +1465,7 @@ rec { version = "0.5.8"; edition = "2018"; sha256 = "004jz4wxp9k26z657i7rsh9s7586dklx2c5aqf1n3w1dgzvjng53"; + libName = "crossbeam_channel"; dependencies = [ { name = "cfg-if"; @@ -1470,6 +1490,7 @@ rec { version = "0.8.3"; edition = "2018"; sha256 = "1vqczbcild7nczh5z116w8w46z991kpjyw7qxkf24c14apwdcvyf"; + libName = "crossbeam_deque"; dependencies = [ { name = "cfg-if"; @@ -1501,6 +1522,7 @@ rec { version = "0.9.15"; edition = "2018"; sha256 = "1ixwc3cq816wb8rlh3ix4jnybqbyyq4l61nwlx0mfm3ck0s148df"; + libName = "crossbeam_epoch"; dependencies = [ { name = "cfg-if"; @@ -1541,6 +1563,7 @@ rec { version = "0.3.8"; edition = "2018"; sha256 = "1p9s6n4ckwdgxkb7a8ay9zjzmgc8ppfbxix2vr07rwskibmb7kyi"; + libName = "crossbeam_queue"; dependencies = [ { name = "cfg-if"; @@ -1564,6 +1587,7 @@ rec { version = "0.8.16"; edition = "2018"; sha256 = "153j0gikblz7n7qdvdi8pslhi008s1yp9cmny6vw07ad7pbb48js"; + libName = "crossbeam_utils"; dependencies = [ { name = "cfg-if"; @@ -1593,6 +1617,7 @@ rec { } ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; + libName = "crunch_v2"; dependencies = [ { name = "anyhow"; @@ -1702,6 +1727,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1727,6 +1753,7 @@ rec { version = "0.11.1"; edition = "2018"; sha256 = "05672ncc54h66vph42s0a42ljl69bwnqjh0x4xgj2v1395psildi"; + libName = "crypto_mac"; authors = [ "RustCrypto Developers" ]; @@ -1749,9 +1776,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.1"; + version = "4.1.3"; edition = "2021"; - sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1797,10 +1825,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1824,6 +1848,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1846,6 +1871,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1950,6 +1976,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -1970,6 +1997,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -1999,6 +2027,7 @@ rec { version = "1.0.16"; edition = "2018"; sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -2041,6 +2070,7 @@ rec { version = "2.1.0"; edition = "2021"; sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -2148,6 +2178,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -2264,6 +2295,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -2274,6 +2306,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -2319,6 +2352,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -2498,6 +2532,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1jxsifvrbqzdadk0svbax71cba5d3qg3wgjq8i160mxmd1kdckgz"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -2525,6 +2560,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1308bpj0g36nhx2y6bl4mm6f1gnh9xyvvw2q2wpdgnb6dv3247gb"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -2537,6 +2573,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1g4pjni0sw28djx6mlcfz584abm2lpifz86cmng0kkxh7mlvhkqg"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -2567,6 +2604,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1ajsljgny3zfxwahba9byjzclrgvm1ypakca8z854k2w7cb4mwwb"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -2578,6 +2616,7 @@ rec { edition = "2018"; sha256 = "1nwd18i8kvpkdfwm045hddjli0n96zi7pn6f99zi9c74j7ym7cak"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -2600,6 +2639,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "05q8jykqddxzp8nwf00wjk5m5mqi546d7i8hsxma7hiqxrw36vg3"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -2611,6 +2651,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1qmsss8rb5ppql4qvd4r70h9gpfcpd0bg2b3qilxrnhdkc397lgg"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -2622,6 +2663,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "0141rkqh0psj4h8x8lgsl1p29dhqr7z2wcixkcbs60z74kb2d5d1"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -2825,9 +2867,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.3.22"; + version = "0.3.26"; edition = "2018"; - sha256 = "0y41jlflvw8niifdirgng67zdmic62cjf5m2z69hzrpn5qr50qjd"; + sha256 = "1s7msnfv7xprzs6xzfj5sg6p8bjcdpcqcmjjbkd345cyi1x55zl1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -2964,6 +3006,7 @@ rec { version = "0.3.3"; edition = "2021"; sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -3068,6 +3111,7 @@ rec { version = "0.4.5"; edition = "2018"; sha256 = "1l967qwwlvhp198xdrnc0p5d7jwfcp6q2lm510j6zqw4s4b8zwym"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -3224,6 +3268,7 @@ rec { version = "0.23.2"; edition = "2018"; sha256 = "0736s6a32dqr107f943xaz1n05flbinq6l19lq1wsrxkc5g9d20p"; + libName = "hyper_rustls"; dependencies = [ { name = "http"; @@ -3298,6 +3343,7 @@ rec { version = "0.1.58"; edition = "2018"; sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -3343,6 +3389,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -3503,6 +3550,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -3557,6 +3605,33 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "libredox" = rec { crateName = "libredox"; version = "0.0.1"; @@ -3590,6 +3665,7 @@ rec { version = "0.4.11"; edition = "2021"; sha256 = "0adqqaya81s7k5r323g65pw6q85pxd1x4prz9whh5i4abysqi54n"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -3677,6 +3753,7 @@ rec { edition = "2015"; links = "lz4"; sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -3702,6 +3779,7 @@ rec { edition = "2018"; links = "lzma"; sha256 = "09sxp20waxyglgn3cjz8qjkspb3ryz2fwx4rigkwvrk46ymh9njz"; + libName = "lzma_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3818,11 +3896,40 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "minimal-lexical" = rec { crateName = "minimal-lexical"; version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -3860,9 +3967,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.9"; + version = "0.8.11"; edition = "2018"; - sha256 = "1l23hg513c23nhcdzvk25caaj28mic6qgqadbn8axgj6bqf2ikix"; + sha256 = "034byyl0ardml5yliy1hmvx8arkmn9rv479pid794sm07ia519m4"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -3943,6 +4050,7 @@ rec { edition = "2021"; sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -3976,6 +4084,7 @@ rec { edition = "2021"; crateBin = [ ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; @@ -3987,6 +4096,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -4007,6 +4121,10 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "nom"; packageId = "nom"; } @@ -4042,21 +4160,30 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; "default" = [ "async" "wire" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "async" "default" "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "pin-project-lite" "tokio" "wire" ]; }; "nom" = rec { crateName = "nom"; @@ -4128,6 +4255,7 @@ rec { version = "0.2.19"; edition = "2021"; sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -4240,6 +4368,7 @@ rec { version = "0.3.0"; edition = "2018"; sha256 = "1m8kzi4nd6shdqimn0mgb24f0hxslhnqd1whakyq06wcqd086jk2"; + libName = "opaque_debug"; authors = [ "RustCrypto Developers" ]; @@ -4250,6 +4379,7 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4405,6 +4535,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -4434,6 +4565,7 @@ rec { version = "2.3.0"; edition = "2018"; sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -4478,6 +4610,7 @@ rec { version = "0.2.13"; edition = "2018"; sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -4485,6 +4618,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -4529,6 +4663,7 @@ rec { version = "0.3.27"; edition = "2015"; sha256 = "0r39ryh1magcq4cz5g9x88jllsnxnhcqr753islvyk4jp9h2h1r6"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -4550,21 +4685,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.2.0"; - edition = "2018"; - sha256 = "1c6bzwn877aqdbbmyqsl753ycbciwvbdh4lpzijb8vrfb4zsprhl"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.35.4"; @@ -4759,6 +4879,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1rxa9dfsqy7mh4w9gy7y7kpig0wrzrjqi1axj43rnxyrlqq38l6x"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4937,6 +5058,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1mnginlmgmlp167ij0r5lywvy50zns1cr8db1ikxxv2xwnwdawxf"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5086,6 +5208,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "127l5hazh5hn73j767cfyjwgbvvbab8hj53l1jp976daivb201gb"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5122,6 +5245,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "01mwcdikw7y92xjhlsmj4wf0p9r3kvmhrvsbnsfh1mmc8l3hmqcn"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5280,6 +5404,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "084gp9qa1w9b7dglcmrvlx6xrcl7hw5nmlb26w6xvrjvf1czfm9m"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5469,6 +5594,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "0dpnxcgc57k8xvp4jmjhz8jwz8rclf62h22zjiwpzaka54cb4zhs"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5609,6 +5735,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1pb79wb1f31pk48lfm2w72hdfxqz6vv65iyxb072skfxnzj10q0l"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -5729,6 +5856,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1v5xniw8yxx9cnksc4bf169b3p7gcl6dzryzgfd2m4scyrylw2b6"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -5836,6 +5964,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1g2z0g0hpg05jp4n9s6m6m32adrjrdlq6zxd5c9lp1ggb04jmqqh"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6019,6 +6148,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1b3d8pdxz12dzg75nqb7b2p83l15c1z4r6589sknp462ra0sndfi"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6048,6 +6178,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "17jiflfmyymz1fdk2mrsdri2yqs1h7rqn66y3yny79a9d1wdgnxq"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6112,6 +6243,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "0lgyk3fpp7krbyfra51pb4fqn6m3hk5gbj61fdvn3pffx5wnzrda"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6190,6 +6322,7 @@ rec { version = "0.35.4"; edition = "2021"; sha256 = "1z7v7h54p883ww64mqpn4cphzwv0fd2bgsn8b1lx8qgyd60ycv6s"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -6257,6 +6390,7 @@ rec { version = "1.5.1"; edition = "2018"; sha256 = "0fxg0i7n3wmffbfn95nwi062srdg40bwkj5143w1kk6pgw7apk1v"; + libName = "portable_atomic"; features = { "critical-section" = [ "dep:critical-section" ]; "default" = [ "fallback" ]; @@ -6269,6 +6403,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; @@ -6316,6 +6451,7 @@ rec { version = "1.0.69"; edition = "2021"; sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -6364,6 +6500,7 @@ rec { version = "0.12.2"; edition = "2021"; sha256 = "0f57mmf6cg7f4401x9s3fgdc1idnz7i1nxxjxyzi2jbhr22d18qz"; + libName = "prost_build"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -6456,6 +6593,7 @@ rec { edition = "2021"; sha256 = "1g268fzmswaf6rx1sm8000h6a4rigd4b6zg55wysi95cvyjifmq6"; procMacro = true; + libName = "prost_derive"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -6493,6 +6631,7 @@ rec { version = "0.12.2"; edition = "2021"; sha256 = "0lls5w7yh2jxi764kd9k44dwskrr85j2fs335wg2i47m6qig6fc3"; + libName = "prost_types"; authors = [ "Dan Burkert <dan@danburkert.com>" "Lucio Franco <luciofranco14@gmail.com" @@ -6697,6 +6836,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1vaq0q71yfvcwlmia0iqf6ixj2fibjcf2xjy92n1m1izv1mgpqsw"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -6844,6 +6984,7 @@ rec { version = "0.4.3"; edition = "2021"; sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -6904,6 +7045,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -7384,6 +7526,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -7564,6 +7707,7 @@ rec { version = "0.6.3"; edition = "2021"; sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -7592,6 +7736,7 @@ rec { version = "1.0.4"; edition = "2018"; sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; + libName = "rustls_pemfile"; dependencies = [ { name = "base64"; @@ -7686,6 +7831,7 @@ rec { version = "2.9.2"; edition = "2021"; sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -7732,6 +7878,7 @@ rec { version = "2.9.1"; edition = "2021"; sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -7777,6 +7924,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -7981,6 +8129,7 @@ rec { version = "0.6.3"; edition = "2018"; sha256 = "0kp480744vkwg3fqx98379nsdw1lzzzimd88v0qgpqqic03afyzj"; + libName = "sha2_asm"; authors = [ "RustCrypto Developers" ]; @@ -7994,12 +8143,16 @@ rec { }; "shlex" = rec { crateName = "shlex"; - version = "1.2.0"; + version = "1.3.0"; edition = "2015"; - sha256 = "1033pj9dyb76nm5yv597nnvj3zpvr2aw9rm5wy0gah3dk99f1km7"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; authors = [ "comex <comexk@gmail.com>" "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" ]; features = { "default" = [ "std" ]; @@ -8011,6 +8164,7 @@ rec { version = "1.4.1"; edition = "2015"; sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -8359,6 +8513,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -8372,6 +8527,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -8568,6 +8724,7 @@ rec { version = "0.1.5"; edition = "2021"; sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -8635,6 +8792,7 @@ rec { edition = "2021"; sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8770,6 +8928,7 @@ rec { edition = "2021"; sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8795,6 +8954,7 @@ rec { version = "0.23.4"; edition = "2018"; sha256 = "0nfsmmi8l1lgpbfy6079d5i13984djzcxrdr9jc06ghi0cwyhgn4"; + libName = "tokio_rustls"; authors = [ "quininer kel <quininer@live.com>" ]; @@ -8833,6 +8993,7 @@ rec { version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8895,6 +9056,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -8915,6 +9077,11 @@ rec { packageId = "pin-project-lite"; } { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { name = "tracing-core"; packageId = "tracing-core"; usesDefaultFeatures = false; @@ -8929,13 +9096,44 @@ rec { "tracing-attributes" = [ "dep:tracing-attributes" ]; "valuable" = [ "tracing-core/valuable" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.39"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; }; "tracing-core" = rec { crateName = "tracing-core"; version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -8959,6 +9157,7 @@ rec { version = "0.2.4"; edition = "2015"; sha256 = "1vc15paa4zi06ixsxihwbvfn24d708nsyg1ncgqwcrn42byyqa1m"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -8984,6 +9183,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -8994,6 +9194,7 @@ rec { version = "0.1.11"; edition = "2015"; sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -9087,6 +9288,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -9118,6 +9320,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -9163,6 +9366,7 @@ rec { edition = "2018"; sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -9187,6 +9391,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -9225,6 +9430,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -9235,6 +9441,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "11ba406ca9qssc21c37v49sn2y2gsdn6c3nva4hjf8v3yv2rkd2x"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -9788,6 +9995,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -9798,6 +10006,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -9808,6 +10017,7 @@ rec { version = "0.51.1"; edition = "2021"; sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -9825,6 +10035,7 @@ rec { version = "0.45.0"; edition = "2018"; sha256 = "1l36bcqm4g89pknfp8r9rl1w4bn017q6a8qlx8viv0xjxzjkna3m"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -10111,6 +10322,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -10404,6 +10616,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -10651,6 +10864,7 @@ rec { version = "0.42.2"; edition = "2018"; sha256 = "0wfhnib2fisxlx8c507dbmh97kgij4r6kcxdi0f9nk6l1k080lcf"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -10723,6 +10937,7 @@ rec { version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -10770,6 +10985,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -11039,6 +11255,7 @@ rec { version = "0.8.7"; edition = "2018"; sha256 = "0yz037yrkn0qa0g0r6733ynd1xbw7zvx58v6qylhyi2kv9wb2a4q"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -11068,9 +11285,9 @@ rec { }; "zerocopy" = rec { crateName = "zerocopy"; - version = "0.7.26"; + version = "0.7.35"; edition = "2018"; - sha256 = "184s51bzn8mpx3p9h6klrlppv9b7ja1b8y9998jr36jmj1a42zp9"; + sha256 = "1w36q7b9il2flg0qskapgi9ymgg7p985vniqd09vi0mwib8lz6qv"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -11104,10 +11321,11 @@ rec { }; "zerocopy-derive" = rec { crateName = "zerocopy-derive"; - version = "0.7.26"; + version = "0.7.35"; edition = "2018"; - sha256 = "17v8yshfa23z5az2xhclpwrlzih26nj7imwbra12i5b6y764hznx"; + sha256 = "0gnf2ap2y92nwdalzz3x7142f2b83sni66l39vxp2ijd6j080kzs"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -11182,6 +11400,7 @@ rec { version = "7.0.0"; edition = "2018"; sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -11215,6 +11434,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -11344,52 +11564,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e - - export RUST_BACKTRACE=1 - - # recreate a file hierarchy as when running tests with cargo - - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ - - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} - - # build outputs - testRoot=target/debug - mkdir -p $testRoot - - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . - - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; + + inherit (crate) src; + + inherit testCrateFlags; + + buildInputs = testInputs; + + buildPhase = '' + set -e + export RUST_BACKTRACE=1 + + # build outputs + testRoot=target/debug + mkdir -p $testRoot + + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . + + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/tvix/tools/crunch-v2/Cargo.toml b/tvix/tools/crunch-v2/Cargo.toml index d2b7126bd241..4421c8b9ab34 100644 --- a/tvix/tools/crunch-v2/Cargo.toml +++ b/tvix/tools/crunch-v2/Cargo.toml @@ -11,7 +11,7 @@ anyhow = { version = "1.0.75", features = ["backtrace"] } lazy_static = "1.4.0" bstr = "1.8.0" -bytes = "1.5.0" +bytes = "1.6.1" futures = "0.3.29" tokio = { version = "1.37.0", features = ["full"] } diff --git a/tvix/tools/crunch-v2/default.nix b/tvix/tools/crunch-v2/default.nix index a3eb25eb9ad6..8014aa9443c8 100644 --- a/tvix/tools/crunch-v2/default.nix +++ b/tvix/tools/crunch-v2/default.nix @@ -10,4 +10,6 @@ nativeBuildInputs = [ pkgs.protobuf ]; }; }; -}).rootCrate.build +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/narinfo2parquet/Cargo.lock b/tvix/tools/narinfo2parquet/Cargo.lock index 88809eb57cf2..151ce0b47f44 100644 --- a/tvix/tools/narinfo2parquet/Cargo.lock +++ b/tvix/tools/narinfo2parquet/Cargo.lock @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "cc" @@ -398,16 +398,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -817,6 +816,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "linux-raw-sys" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -873,6 +882,15 @@ dependencies = [ ] [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -938,11 +956,13 @@ version = "0.1.0" dependencies = [ "bitflags 2.4.1", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", "enum-primitive-derive", "glob", + "mimalloc", "nom", "num-traits", "pin-project-lite", @@ -951,6 +971,7 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tracing", ] [[package]] @@ -1070,12 +1091,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" - -[[package]] name = "polars" version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1860,6 +1875,37 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/tvix/tools/narinfo2parquet/Cargo.nix b/tvix/tools/narinfo2parquet/Cargo.nix index d00ceaf4f2e3..9804b92a5e76 100644 --- a/tvix/tools/narinfo2parquet/Cargo.nix +++ b/tvix/tools/narinfo2parquet/Cargo.nix @@ -207,6 +207,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -218,6 +219,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -234,6 +236,7 @@ rec { version = "0.2.16"; edition = "2018"; sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -249,6 +252,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -320,6 +324,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; "arrow-format" = rec { @@ -327,6 +332,7 @@ rec { version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -362,6 +368,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -387,6 +394,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -413,6 +421,7 @@ rec { edition = "2021"; sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -605,6 +614,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -660,6 +670,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -782,9 +793,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.6.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0lnryqfiymbq5mfflfmbsqvfnw80kkh36nk5kpiscgxb9ac1cad1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -828,6 +839,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -892,6 +904,7 @@ rec { version = "0.9.5"; edition = "2021"; sha256 = "0vxb4d25mgk8y0phay7j078limx2553716ixsr1x5605k31j5h98"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -904,6 +917,7 @@ rec { version = "0.8.4"; edition = "2015"; sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -966,6 +980,7 @@ rec { version = "0.5.8"; edition = "2018"; sha256 = "004jz4wxp9k26z657i7rsh9s7586dklx2c5aqf1n3w1dgzvjng53"; + libName = "crossbeam_channel"; dependencies = [ { name = "cfg-if"; @@ -990,6 +1005,7 @@ rec { version = "0.8.3"; edition = "2018"; sha256 = "1vqczbcild7nczh5z116w8w46z991kpjyw7qxkf24c14apwdcvyf"; + libName = "crossbeam_deque"; dependencies = [ { name = "cfg-if"; @@ -1021,6 +1037,7 @@ rec { version = "0.9.15"; edition = "2018"; sha256 = "1ixwc3cq816wb8rlh3ix4jnybqbyyq4l61nwlx0mfm3ck0s148df"; + libName = "crossbeam_epoch"; dependencies = [ { name = "cfg-if"; @@ -1061,6 +1078,7 @@ rec { version = "0.3.8"; edition = "2018"; sha256 = "1p9s6n4ckwdgxkb7a8ay9zjzmgc8ppfbxix2vr07rwskibmb7kyi"; + libName = "crossbeam_queue"; dependencies = [ { name = "cfg-if"; @@ -1084,6 +1102,7 @@ rec { version = "0.8.16"; edition = "2018"; sha256 = "153j0gikblz7n7qdvdi8pslhi008s1yp9cmny6vw07ad7pbb48js"; + libName = "crossbeam_utils"; dependencies = [ { name = "cfg-if"; @@ -1101,6 +1120,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1123,9 +1143,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.1"; + version = "4.1.3"; edition = "2021"; - sha256 = "0p7ns5917k6369gajrsbfj24llc5zfm635yh3abla7sb5rm8r6z8"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1171,10 +1192,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1198,6 +1215,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1220,6 +1238,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1303,6 +1322,7 @@ rec { version = "1.0.16"; edition = "2018"; sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -1345,6 +1365,7 @@ rec { version = "2.1.0"; edition = "2021"; sha256 = "1h13qm789m9gdjl6jazss80hqi8ll37m0afwcnw23zcbqjp8wqhz"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1437,6 +1458,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -1553,6 +1575,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -1563,6 +1586,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -1592,6 +1616,7 @@ rec { version = "0.2.5"; edition = "2018"; sha256 = "1dxn0g50pv0ppal779vi7k40fr55pbhkyv4in7i13pgl4sn3wmr7"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1721,6 +1746,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1jxsifvrbqzdadk0svbax71cba5d3qg3wgjq8i160mxmd1kdckgz"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1748,6 +1774,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1308bpj0g36nhx2y6bl4mm6f1gnh9xyvvw2q2wpdgnb6dv3247gb"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1760,6 +1787,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1g4pjni0sw28djx6mlcfz584abm2lpifz86cmng0kkxh7mlvhkqg"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -1790,6 +1818,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1ajsljgny3zfxwahba9byjzclrgvm1ypakca8z854k2w7cb4mwwb"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -1801,6 +1830,7 @@ rec { edition = "2018"; sha256 = "1nwd18i8kvpkdfwm045hddjli0n96zi7pn6f99zi9c74j7ym7cak"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1823,6 +1853,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "05q8jykqddxzp8nwf00wjk5m5mqi546d7i8hsxma7hiqxrw36vg3"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1834,6 +1865,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "1qmsss8rb5ppql4qvd4r70h9gpfcpd0bg2b3qilxrnhdkc397lgg"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1845,6 +1877,7 @@ rec { version = "0.3.29"; edition = "2018"; sha256 = "0141rkqh0psj4h8x8lgsl1p29dhqr7z2wcixkcbs60z74kb2d5d1"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -2098,6 +2131,7 @@ rec { version = "0.3.3"; edition = "2021"; sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2132,6 +2166,7 @@ rec { version = "0.1.58"; edition = "2018"; sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -2177,6 +2212,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -2234,6 +2270,7 @@ rec { edition = "2018"; links = "jemalloc"; sha256 = "1wpbpwhfs6wd484cdfpl0zdf441ann9wj0fypy67i8ffw531jv5c"; + libName = "jemalloc_sys"; authors = [ "Alex Crichton <alex@alexcrichton.com>" "Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>" @@ -2316,6 +2353,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -2357,11 +2395,39 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "linux-raw-sys" = rec { crateName = "linux-raw-sys"; version = "0.4.10"; edition = "2021"; sha256 = "0gz0671d4hgrdngrryaajxl962ny4g40pykg0vq0pr32q3l7j96s"; + libName = "linux_raw_sys"; authors = [ "Dan Gohman <dev@sunfishcode.online>" ]; @@ -2421,6 +2487,7 @@ rec { edition = "2015"; links = "lz4"; sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -2497,11 +2564,40 @@ rec { features = { }; resolvedDefaultFeatures = [ "default" ]; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "minimal-lexical" = rec { crateName = "minimal-lexical"; version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2608,6 +2704,7 @@ rec { edition = "2021"; sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -2684,6 +2781,7 @@ rec { edition = "2021"; crateBin = [ ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; @@ -2695,6 +2793,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2715,6 +2818,10 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "nom"; packageId = "nom"; } @@ -2750,21 +2857,30 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; "default" = [ "async" "wire" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "async" "default" "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "pin-project-lite" "tokio" "wire" ]; }; "nom" = rec { crateName = "nom"; @@ -2836,6 +2952,7 @@ rec { version = "0.2.19"; edition = "2021"; sha256 = "0h984rhdkkqd4ny9cif7y2azl3xdfb7768hb9irhpsch4q3gq787"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2935,6 +3052,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -2964,6 +3082,7 @@ rec { version = "2.3.0"; edition = "2018"; sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2978,6 +3097,7 @@ rec { version = "0.2.13"; edition = "2018"; sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2985,6 +3105,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -3029,6 +3150,7 @@ rec { version = "0.3.27"; edition = "2015"; sha256 = "0r39ryh1magcq4cz5g9x88jllsnxnhcqr753islvyk4jp9h2h1r6"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3050,21 +3172,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.2.0"; - edition = "2018"; - sha256 = "1c6bzwn877aqdbbmyqsl753ycbciwvbdh4lpzijb8vrfb4zsprhl"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.36.2"; @@ -3265,6 +3372,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0vxql6amvwyp6qj0w87vm21y33qa0i61pshs4ry7ixwgd4ps0s6f"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -3443,6 +3551,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1pa4l1w41gdzdff81ih1z05z3gz568k81i6flibbca8v2igvqkxi"; + libName = "polars_compute"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3482,6 +3591,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "08sar9h97znpb8ziyvrrvvx28lyzc21vwsd7gvwybjxn6kkyzxfh"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3636,6 +3746,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "11m80a899kp45b3dz9jbvrn5001hw8izbdp7d2czrswrixwdx5k3"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3672,6 +3783,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1smamd34ghlxyxdd4aqdplk7k8xm1l626brmzlc4fvwlx3pmh13x"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3830,6 +3942,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1mdml4hs574njb23mb9gl6x92x2bb4vdfzsazkl3ifq516s0awcx"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4024,6 +4137,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "13m7dh4vpdmcah04a7kql933l7y7045f0hybbmgff4dbav2ay29f"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4175,6 +4289,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0gay037sw5hcg2q93pxcfh7krcchl1px8g838d8vhjpnn5klv8kv"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4295,6 +4410,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "00217q51mnq7i57k3sax293xnwghm5hridbpgl11fffcfg8fmdyr"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4408,6 +4524,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l5ca38v7ksq4595wdr6wsd74pdgszwivq9y8wfc6l6h4ib1fjiq"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4596,6 +4713,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0by7x6jlj5dwr3f1gj49v8w65l3kpqhwhzb9qzlv6gdqrdx2ycij"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4625,6 +4743,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1dcmm993gycw75a6c5hxcr6h2cy6fa2r3hsbx19h9zgxvxnlq2wz"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4689,6 +4808,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l24fmpv5v1qshxfd4592z8x6bnjlwy4njhf9rcbdlbbr6gn9qny"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4767,6 +4887,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1nmvfqwyzbaxcw457amspz479y5vcnpalq043awxfixdfx5clx5i"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4834,6 +4955,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; @@ -4847,6 +4969,7 @@ rec { version = "1.0.69"; edition = "2021"; sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -5048,6 +5171,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1vaq0q71yfvcwlmia0iqf6ixj2fibjcf2xjy92n1m1izv1mgpqsw"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -5145,6 +5269,7 @@ rec { version = "0.4.3"; edition = "2021"; sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5205,6 +5330,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5221,6 +5347,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -5412,6 +5539,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5755,6 +5883,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -5768,6 +5897,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -5954,6 +6084,7 @@ rec { version = "0.1.5"; edition = "2021"; sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -6004,6 +6135,7 @@ rec { version = "0.3.4"; edition = "2018"; sha256 = "1xksx1l1019k9q0az9mhqsgb14w0vm88yax30iq6178s3d9yhjx7"; + libName = "tempfile_fast"; authors = [ "Chris West (Faux) <git@goeswhere.com>" ]; @@ -6046,6 +6178,7 @@ rec { edition = "2021"; sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6170,6 +6303,7 @@ rec { edition = "2021"; sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6195,6 +6329,7 @@ rec { version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6245,6 +6380,96 @@ rec { }; resolvedDefaultFeatures = [ "default" "io" "io-util" ]; }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.39"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "once_cell" "std" ]; + }; "typenum" = rec { crateName = "typenum"; version = "1.17.0"; @@ -6265,6 +6490,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6302,6 +6528,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -6333,6 +6560,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -6378,6 +6606,7 @@ rec { edition = "2018"; sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -6402,6 +6631,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -6440,6 +6670,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -6475,6 +6706,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -6485,6 +6717,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -7176,6 +7409,7 @@ rec { version = "0.51.1"; edition = "2021"; sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -7193,6 +7427,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -7210,6 +7445,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -7503,6 +7739,7 @@ rec { version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7550,6 +7787,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7737,6 +7975,7 @@ rec { version = "0.8.7"; edition = "2018"; sha256 = "0yz037yrkn0qa0g0r6733ynd1xbw7zvx58v6qylhyi2kv9wb2a4q"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -7785,6 +8024,7 @@ rec { edition = "2018"; sha256 = "0fqvglw01w3hp7xj9gdk1800x9j7v58s9w8ijiyiz2a7krb39s8m"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -7859,6 +8099,7 @@ rec { version = "7.0.0"; edition = "2018"; sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -7892,6 +8133,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8021,52 +8263,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/tvix/tools/narinfo2parquet/default.nix b/tvix/tools/narinfo2parquet/default.nix index 0b486f08849a..dfe2b66655c8 100644 --- a/tvix/tools/narinfo2parquet/default.nix +++ b/tvix/tools/narinfo2parquet/default.nix @@ -6,4 +6,6 @@ src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; }; -}).rootCrate.build +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/narinfo2parquet/src/main.rs b/tvix/tools/narinfo2parquet/src/main.rs index b96b134f103a..ea3d39af5503 100644 --- a/tvix/tools/narinfo2parquet/src/main.rs +++ b/tvix/tools/narinfo2parquet/src/main.rs @@ -187,7 +187,7 @@ impl FrameBuilder { assert!(entry.signatures.len() <= 1); self.signature .append_option(entry.signatures.get(0).map(|sig| { - assert_eq!(sig.name(), "cache.nixos.org-1"); + assert_eq!(sig.name(), &"cache.nixos.org-1"); sig.bytes() })); diff --git a/tvix/tools/turbofetch/Cargo.lock b/tvix/tools/turbofetch/Cargo.lock index b2aaf1cccb67..c865efb47466 100644 --- a/tvix/tools/turbofetch/Cargo.lock +++ b/tvix/tools/turbofetch/Cargo.lock @@ -265,6 +265,12 @@ dependencies = [ ] [[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -388,9 +394,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "h2" -version = "0.3.21" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -407,9 +413,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hermit-abi" @@ -541,11 +547,11 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ - "autocfg", + "equivalent", "hashbrown", ] @@ -697,9 +703,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1151,9 +1157,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" diff --git a/tvix/tools/turbofetch/Cargo.nix b/tvix/tools/turbofetch/Cargo.nix index 72fcac307de6..09c9493430d5 100644 --- a/tvix/tools/turbofetch/Cargo.nix +++ b/tvix/tools/turbofetch/Cargo.nix @@ -132,6 +132,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -158,6 +159,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -183,6 +185,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -209,6 +212,7 @@ rec { edition = "2021"; sha256 = "1ydhbsqjqqa6bxbv0kgys2wq2vi3jpwjy57dk162ajwppgqkfrd6"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -463,6 +467,7 @@ rec { version = "0.9.0"; edition = "2018"; sha256 = "1r4pf90s7d7lj1wdjhlnqa26vvbm6pnc33z138lxpnp9srpi2lj1"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -546,6 +551,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -616,6 +622,7 @@ rec { version = "0.9.3"; edition = "2015"; sha256 = "0ii1ihpjb30fk38gdikm5wqlkmyr8k46fh4k2r8sagz5dng7ljhr"; + libName = "core_foundation"; authors = [ "The Servo Project Developers" ]; @@ -643,6 +650,7 @@ rec { version = "0.8.4"; edition = "2015"; sha256 = "1yhf471qj6snnm2mcswai47vsbc9w30y4abmdp4crb4av87sb5p4"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -705,6 +713,7 @@ rec { version = "0.11.1"; edition = "2018"; sha256 = "05672ncc54h66vph42s0a42ljl69bwnqjh0x4xgj2v1395psildi"; + libName = "crypto_mac"; authors = [ "RustCrypto Developers" ]; @@ -730,6 +739,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -765,6 +775,7 @@ rec { version = "2.0.0"; edition = "2018"; sha256 = "1q9kr151h9681wwp6is18750ssghz6j9j7qm7qi1ngcwy7mzi35r"; + libName = "dirs_next"; authors = [ "The @xdg-rs members" ]; @@ -785,6 +796,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "0kavhavdxv4phzj4l0psvh55hszwnr0rcz8sxbvx20pyqi2a3gaf"; + libName = "dirs_sys_next"; authors = [ "The @xdg-rs members" ]; @@ -809,6 +821,13 @@ rec { ]; }; + "equivalent" = rec { + crateName = "equivalent"; + version = "1.0.1"; + edition = "2015"; + sha256 = "1malmx5f4lkfvqasz319lq6gb3ddg19yzf9s8cykfsgzdmyq0hsl"; + + }; "fnv" = rec { crateName = "fnv"; version = "1.0.7"; @@ -889,6 +908,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -916,6 +936,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -928,6 +949,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -958,6 +980,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -969,6 +992,7 @@ rec { edition = "2018"; sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -991,6 +1015,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1002,6 +1027,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1013,6 +1039,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -1175,9 +1202,9 @@ rec { }; "h2" = rec { crateName = "h2"; - version = "0.3.21"; + version = "0.3.26"; edition = "2018"; - sha256 = "0cq8g5bgk3fihnqicy3g8gc3dpsalzqjg4bjyip9g4my26m27z4i"; + sha256 = "1s7msnfv7xprzs6xzfj5sg6p8bjcdpcqcmjjbkd345cyi1x55zl1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -1227,7 +1254,7 @@ rec { { name = "tokio-util"; packageId = "tokio-util"; - features = [ "codec" ]; + features = [ "codec" "io" ]; } { name = "tracing"; @@ -1247,21 +1274,23 @@ rec { }; "hashbrown" = rec { crateName = "hashbrown"; - version = "0.12.3"; + version = "0.14.5"; edition = "2021"; - sha256 = "1268ka4750pyg2pbgsr43f0289l5zah4arir2k4igx5a8c6fg7la"; + sha256 = "1wa1vy1xs3mp11bn3z9dv0jricgr6a2j0zkf1g19yz3vw4il89z5"; authors = [ "Amanieu d'Antras <amanieu@gmail.com>" ]; features = { "ahash" = [ "dep:ahash" ]; - "ahash-compile-time-rng" = [ "ahash/compile-time-rng" ]; "alloc" = [ "dep:alloc" ]; - "bumpalo" = [ "dep:bumpalo" ]; + "allocator-api2" = [ "dep:allocator-api2" ]; "compiler_builtins" = [ "dep:compiler_builtins" ]; "core" = [ "dep:core" ]; - "default" = [ "ahash" "inline-more" ]; + "default" = [ "ahash" "inline-more" "allocator-api2" ]; + "equivalent" = [ "dep:equivalent" ]; + "nightly" = [ "allocator-api2?/nightly" "bumpalo/allocator_api" ]; "rayon" = [ "dep:rayon" ]; + "rkyv" = [ "dep:rkyv" ]; "rustc-dep-of-std" = [ "nightly" "core" "compiler_builtins" "alloc" "rustc-internal-api" ]; "serde" = [ "dep:serde" ]; }; @@ -1272,6 +1301,7 @@ rec { version = "0.3.3"; edition = "2021"; sha256 = "1dyc8qsjh876n74a3rcz8h43s27nj1sypdhsn2ms61bd3b47wzyp"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -1358,6 +1388,7 @@ rec { version = "0.4.5"; edition = "2018"; sha256 = "1l967qwwlvhp198xdrnc0p5d7jwfcp6q2lm510j6zqw4s4b8zwym"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1384,6 +1415,7 @@ rec { version = "1.1.3"; edition = "2021"; sha256 = "1vnald3g10gxj15dc5jjjk7aff23p1zly0xgzhn5gwfrb9k0nmkg"; + libName = "http_serde"; authors = [ "Kornel <kornel@geekhood.net>" ]; @@ -1535,6 +1567,7 @@ rec { version = "0.23.2"; edition = "2018"; sha256 = "0736s6a32dqr107f943xaz1n05flbinq6l19lq1wsrxkc5g9d20p"; + libName = "hyper_rustls"; dependencies = [ { name = "http"; @@ -1609,6 +1642,7 @@ rec { version = "0.1.58"; edition = "2018"; sha256 = "081vcr8z8ddhl5r1ywif6grnswk01b2ac4nks2bhn8zzdimvh9l3"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -1654,6 +1688,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -1667,32 +1702,32 @@ rec { }; "indexmap" = rec { crateName = "indexmap"; - version = "1.9.3"; + version = "2.4.0"; edition = "2021"; - sha256 = "16dxmy7yvk51wvnih3a3im6fp5lmx0wx76i03n06wyak6cwhw1xx"; + sha256 = "0p2hwvmir50qcl5q6lib8fjq5dzv4f0gqy8czcyfva3yzhzdbslk"; dependencies = [ { + name = "equivalent"; + packageId = "equivalent"; + usesDefaultFeatures = false; + } + { name = "hashbrown"; packageId = "hashbrown"; usesDefaultFeatures = false; features = [ "raw" ]; } ]; - buildDependencies = [ - { - name = "autocfg"; - packageId = "autocfg"; - } - ]; features = { "arbitrary" = [ "dep:arbitrary" ]; + "borsh" = [ "dep:borsh" ]; + "default" = [ "std" ]; "quickcheck" = [ "dep:quickcheck" ]; "rayon" = [ "dep:rayon" ]; "rustc-rayon" = [ "dep:rustc-rayon" ]; "serde" = [ "dep:serde" ]; - "serde-1" = [ "serde" ]; }; - resolvedDefaultFeatures = [ "std" ]; + resolvedDefaultFeatures = [ "default" "std" ]; }; "itoa" = rec { crateName = "itoa"; @@ -1728,6 +1763,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "1s1gaxgzpqfyygc7f2pwp9y128rh5f8zvsc4nm5yazgna9cw7h2l"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -1981,6 +2017,7 @@ rec { version = "0.1.1"; edition = "2021"; sha256 = "0bpzcrwq89cc5q8mgkmsyx39vjsqaxvaxs29qp8k04rndc7ysfh0"; + libName = "magic_buffer"; authors = [ "Sebastian Klose <mail@sklose.com>" ]; @@ -2094,9 +2131,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.9"; + version = "0.8.11"; edition = "2018"; - sha256 = "1l23hg513c23nhcdzvk25caaj28mic6qgqadbn8axgj6bqf2ikix"; + sha256 = "034byyl0ardml5yliy1hmvx8arkmn9rv479pid794sm07ia519m4"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2137,6 +2174,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -2165,6 +2203,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "0z16bi5zwgfysz6765v3rd6whfbjpihx3mhsn4dg8dzj2c221qrr"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2256,6 +2295,7 @@ rec { version = "0.3.0"; edition = "2018"; sha256 = "1m8kzi4nd6shdqimn0mgb24f0hxslhnqd1whakyq06wcqd086jk2"; + libName = "opaque_debug"; authors = [ "RustCrypto Developers" ]; @@ -2266,6 +2306,7 @@ rec { version = "0.1.5"; edition = "2015"; sha256 = "1kq18qm48rvkwgcggfkqq6pm948190czqc94d6bm2sir5hq1l0gz"; + libName = "openssl_probe"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -2353,6 +2394,7 @@ rec { version = "2.3.0"; edition = "2018"; sha256 = "152slflmparkh27hprw62sph8rv77wckzhwl2dhqk6bf563lfalv"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2367,6 +2409,7 @@ rec { version = "1.1.3"; edition = "2021"; sha256 = "08k4cpy8q3j93qqgnrbzkcgpn7g0a88l4a9nm33kyghpdhffv97x"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -2381,6 +2424,7 @@ rec { edition = "2021"; sha256 = "01a4l3vb84brv9v7wl71chzxra2kynm6yvcjca66xv3ij6fgsna3"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -2403,6 +2447,7 @@ rec { version = "0.2.13"; edition = "2018"; sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2410,6 +2455,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2420,6 +2466,7 @@ rec { version = "1.0.69"; edition = "2021"; sha256 = "1nljgyllbm3yr3pa081bf83gxh6l4zvjqzaldw7v4mj9xfgihk0k"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -2978,6 +3025,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3049,6 +3097,7 @@ rec { version = "0.6.3"; edition = "2021"; sha256 = "007zind70rd5rfsrkdcfm8vn09j8sg02phg9334kark6rdscxam9"; + libName = "rustls_native_certs"; dependencies = [ { name = "openssl-probe"; @@ -3077,6 +3126,7 @@ rec { version = "1.0.4"; edition = "2018"; sha256 = "1324n5bcns0rnw6vywr5agff3rwfvzphi7rmbyzwnv6glkhclx0w"; + libName = "rustls_pemfile"; dependencies = [ { name = "base64"; @@ -3159,6 +3209,7 @@ rec { version = "2.9.2"; edition = "2021"; sha256 = "1pplxk15s5yxvi2m1sz5xfmjibp96cscdcl432w9jzbk0frlzdh5"; + libName = "security_framework"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -3205,6 +3256,7 @@ rec { version = "2.9.1"; edition = "2021"; sha256 = "0yhciwlsy9dh0ps1gw3197kvyqx1bvc4knrhiznhid6kax196cp9"; + libName = "security_framework_sys"; authors = [ "Steven Fackler <sfackler@gmail.com>" "Kornel <kornel@geekhood.net>" @@ -3417,6 +3469,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -3432,12 +3485,16 @@ rec { }; "shlex" = rec { crateName = "shlex"; - version = "1.2.0"; + version = "1.3.0"; edition = "2015"; - sha256 = "1033pj9dyb76nm5yv597nnvj3zpvr2aw9rm5wy0gah3dk99f1km7"; + sha256 = "0r1y6bv26c1scpxvhg2cabimrmwgbp4p3wy6syj9n0c4s3q2znhg"; authors = [ "comex <comexk@gmail.com>" "Fenhl <fenhl@fenhl.net>" + "Adrian Taylor <adetaylor@chromium.org>" + "Alex Touchet <alextouchet@outlook.com>" + "Daniel Parks <dp+git@oxidized.org>" + "Garrett Berg <googberg@gmail.com>" ]; features = { "default" = [ "std" ]; @@ -3449,6 +3506,7 @@ rec { version = "1.4.1"; edition = "2015"; sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -3651,6 +3709,7 @@ rec { edition = "2021"; sha256 = "1f0lmam4765sfnwr4b1n00y14vxh10g0311mkk0adr80pi02wsr6"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3806,6 +3865,7 @@ rec { edition = "2021"; sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3831,6 +3891,7 @@ rec { version = "0.23.4"; edition = "2018"; sha256 = "0nfsmmi8l1lgpbfy6079d5i13984djzcxrdr9jc06ghi0cwyhgn4"; + libName = "tokio_rustls"; authors = [ "quininer kel <quininer@live.com>" ]; @@ -3869,6 +3930,7 @@ rec { version = "0.1.14"; edition = "2021"; sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3912,6 +3974,7 @@ rec { version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3967,7 +4030,7 @@ rec { "time" = [ "tokio/time" "slab" ]; "tracing" = [ "dep:tracing" ]; }; - resolvedDefaultFeatures = [ "codec" "default" "tracing" ]; + resolvedDefaultFeatures = [ "codec" "default" "io" "tracing" ]; }; "tower" = rec { crateName = "tower"; @@ -4062,6 +4125,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -4072,6 +4136,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -4130,6 +4195,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -4158,6 +4224,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4188,6 +4255,7 @@ rec { version = "0.1.4"; edition = "2018"; sha256 = "1wmxawaz94sk52i4vs2wg5d5clyks972rqskrvc93rxl14ki2lgp"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4220,6 +4288,7 @@ rec { version = "0.1.3"; edition = "2018"; sha256 = "1qfr0va69djvxqvjrx4vqq7p6myy414lx4w1f6amcn0hfwqj2sxw"; + libName = "tracing_serde"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4244,6 +4313,7 @@ rec { version = "0.3.17"; edition = "2018"; sha256 = "0xvwfpmb943hdy4gzyn7a2azgigf30mfd1kx10gyh5gr6yy539ih"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -4338,6 +4408,7 @@ rec { version = "0.2.4"; edition = "2015"; sha256 = "1vc15paa4zi06ixsxihwbvfn24d708nsyg1ncgqwcrn42byyqa1m"; + libName = "try_lock"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -4459,6 +4530,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -4546,6 +4618,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "1khgsh4z9bga35mjhg41dl7523i69ffc5m8ckhqaw6ssyabc5bkx"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -4577,6 +4650,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "05zj8yl243rvs87rhicq2l1d6443lnm6k90khf744khf9ikg95z3"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -4622,6 +4696,7 @@ rec { edition = "2018"; sha256 = "1chn3wgw9awmvs0fpmazbqyc5rwfgy3pj7lzwczmzb887dxh2qar"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -4646,6 +4721,7 @@ rec { version = "0.2.88"; edition = "2018"; sha256 = "01rrzg3y1apqygsjz1jg0n7p831nm4kdyxmxyl85x7v6mf6kndf5"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -4684,6 +4760,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "02vmw2rzsla1qm0zgfng4kqz52xn8k54v8ads4g1macv09fnq10d"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -4694,6 +4771,7 @@ rec { version = "0.3.65"; edition = "2018"; sha256 = "11ba406ca9qssc21c37v49sn2y2gsdn6c3nva4hjf8v3yv2rkd2x"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -5213,6 +5291,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5223,6 +5302,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5233,6 +5313,7 @@ rec { version = "0.51.1"; edition = "2021"; sha256 = "0r1f57hsshsghjyc7ypp2s0i78f7b1vr93w68sdb8baxyf2czy7i"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -5250,6 +5331,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -5543,6 +5625,7 @@ rec { version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -5719,6 +5802,7 @@ rec { version = "4.1.3+zstd.1.5.1"; edition = "2018"; sha256 = "0yfvqzzkbj871f2vaikal5rm2gf60p1mdzp3jk3w5hmkkywq37g9"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -5753,6 +5837,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "17xcr0mw8ps9hlc8m0dzj7yd52lb9r9ic9fbpxa4994yilj2zbrd"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -5885,52 +5970,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/tvix/tools/turbofetch/default.nix b/tvix/tools/turbofetch/default.nix index 10f3d134138e..a98b2f0b4330 100644 --- a/tvix/tools/turbofetch/default.nix +++ b/tvix/tools/turbofetch/default.nix @@ -6,4 +6,6 @@ src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; }; -}).rootCrate.build +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tools/weave/Cargo.lock b/tvix/tools/weave/Cargo.lock index 5fb04a522b21..bb571af1a20d 100644 --- a/tvix/tools/weave/Cargo.lock +++ b/tvix/tools/weave/Cargo.lock @@ -271,9 +271,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "cc" @@ -422,16 +422,15 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -805,6 +804,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "lock_api" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -856,6 +865,15 @@ dependencies = [ ] [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -872,9 +890,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -909,11 +927,13 @@ version = "0.1.0" dependencies = [ "bitflags 2.4.2", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", "enum-primitive-derive", "glob", + "mimalloc", "nom", "num-traits", "pin-project-lite", @@ -922,6 +942,7 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tracing", ] [[package]] @@ -1073,12 +1094,6 @@ dependencies = [ ] [[package]] -name = "platforms" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" - -[[package]] name = "polars" version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1864,6 +1879,37 @@ dependencies = [ ] [[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/tvix/tools/weave/Cargo.nix b/tvix/tools/weave/Cargo.nix index e485ecd28089..25b2c94a3f11 100644 --- a/tvix/tools/weave/Cargo.nix +++ b/tvix/tools/weave/Cargo.nix @@ -207,6 +207,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1cy6r2sfv5y5cigv86vms7n5nlwhx1rbyxwcraqnmm1rxiib2yyc"; + libName = "alloc_no_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -218,6 +219,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "1kkfbld20ab4165p29v172h8g0wvq8i06z8vnng14whw0isq5ywl"; + libName = "alloc_stdlib"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" ]; @@ -234,6 +236,7 @@ rec { version = "0.2.16"; edition = "2018"; sha256 = "1iayppgq4wqbfbfcqmsbwgamj0s65012sskfvyx07pxavk3gyhh9"; + libName = "allocator_api2"; authors = [ "Zakarum <zaq.dev@icloud.com>" ]; @@ -249,6 +252,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1w7ynjxrfs97xg3qlcdns4kgfpwcdv824g611fq32cag4cdr96g9"; + libName = "android_tzdata"; authors = [ "RumovZ" ]; @@ -320,6 +324,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0xpbqf7qkvzplpjd7f0wbcf2n1v9vygdccwxkd1amxp4il0hlzdz"; + libName = "array_init_cursor"; }; "arrow-format" = rec { @@ -327,6 +332,7 @@ rec { version = "0.8.1"; edition = "2018"; sha256 = "1irj67p6c224dzw86jr7j3z9r5zfid52gy6ml8rdqk4r2si4x207"; + libName = "arrow_format"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" ]; @@ -362,6 +368,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -387,6 +394,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -413,6 +421,7 @@ rec { edition = "2021"; sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -604,6 +613,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -659,6 +669,7 @@ rec { edition = "2015"; crateBin = [ ]; sha256 = "0kyyh9701dwqzwvn2frff4ww0zibikqd1s1xvl7n1pfpc3z4lbjf"; + libName = "brotli_decompressor"; authors = [ "Daniel Reiter Horn <danielrh@dropbox.com>" "The Brotli Authors" @@ -781,9 +792,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.6.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0lnryqfiymbq5mfflfmbsqvfnw80kkh36nk5kpiscgxb9ac1cad1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -827,6 +838,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -897,6 +909,7 @@ rec { version = "7.1.0"; edition = "2021"; sha256 = "11i6sm6vznv9982hqpbrba43vfd7vv7zqzlywdc4qykvdhyh8r3w"; + libName = "comfy_table"; authors = [ "Arne Beer <contact@arne.beer>" ]; @@ -944,6 +957,7 @@ rec { version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -956,6 +970,7 @@ rec { version = "0.8.6"; edition = "2018"; sha256 = "13w6sdf06r0hn7bx2b45zxsg1mm2phz34jikm6xc5qrbr6djpsh6"; + libName = "core_foundation_sys"; authors = [ "The Servo Project Developers" ]; @@ -1021,6 +1036,7 @@ rec { version = "0.5.11"; edition = "2021"; sha256 = "16v48qdflpw3hgdik70bhsj7hympna79q7ci47rw0mlgnxsw2v8p"; + libName = "crossbeam_channel"; dependencies = [ { name = "crossbeam-utils"; @@ -1039,6 +1055,7 @@ rec { version = "0.8.5"; edition = "2021"; sha256 = "03bp38ljx4wj6vvy4fbhx41q8f585zyqix6pncz1mkz93z08qgv1"; + libName = "crossbeam_deque"; dependencies = [ { name = "crossbeam-epoch"; @@ -1062,6 +1079,7 @@ rec { version = "0.9.18"; edition = "2021"; sha256 = "03j2np8llwf376m3fxqx859mgp9f83hj1w34153c7a9c7i5ar0jv"; + libName = "crossbeam_epoch"; dependencies = [ { name = "crossbeam-utils"; @@ -1083,6 +1101,7 @@ rec { version = "0.3.11"; edition = "2021"; sha256 = "0d8y8y3z48r9javzj67v3p2yfswd278myz1j9vzc4sp7snslc0yz"; + libName = "crossbeam_queue"; dependencies = [ { name = "crossbeam-utils"; @@ -1102,6 +1121,7 @@ rec { version = "0.8.19"; edition = "2021"; sha256 = "0iakrb1b8fjqrag7wphl94d10irhbh2fw1g444xslsywqyn3p3i4"; + libName = "crossbeam_utils"; features = { "default" = [ "std" ]; "loom" = [ "dep:loom" ]; @@ -1178,6 +1198,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -1200,9 +1221,10 @@ rec { }; "curve25519-dalek" = rec { crateName = "curve25519-dalek"; - version = "4.1.2"; + version = "4.1.3"; edition = "2021"; - sha256 = "0j7kqchcgycs4a11gvlda93h9w2jr05nn4hjpfyh2kn94a4pnrqa"; + sha256 = "1gmjb9dsknrr8lypmhkyjd67p1arb8mbfamlwxm7vph38my8pywp"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1248,10 +1270,6 @@ rec { ]; buildDependencies = [ { - name = "platforms"; - packageId = "platforms"; - } - { name = "rustc_version"; packageId = "rustc_version"; } @@ -1275,6 +1293,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1297,6 +1316,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1380,6 +1400,7 @@ rec { version = "1.0.16"; edition = "2018"; sha256 = "0pa9kas6a241pbx0q82ipwi4f7m7wwyzkkc725caky24gl4j4nsl"; + libName = "dyn_clone"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -1422,6 +1443,7 @@ rec { version = "2.1.1"; edition = "2021"; sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1514,6 +1536,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -1590,6 +1613,7 @@ rec { version = "0.1.9"; edition = "2015"; sha256 = "0nj6j26p71bjy8h42x6jahx1hn0ng6mc2miwpgwnp8vnwqf4jq3k"; + libName = "fallible_streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -1600,6 +1624,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "0g7kfll3xyh99kc7r352lhljnwvgayxxa6saifb6725inikmyxlm"; + libName = "fast_float"; authors = [ "Ivan Smirnov <i.s.smirnov@gmail.com>" ]; @@ -1613,6 +1638,7 @@ rec { version = "0.2.6"; edition = "2018"; sha256 = "10hkkkjynhibvchznkxx81gwxqarn9i5sgz40d6xxb8xzhsz8xhn"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1742,6 +1768,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1769,6 +1796,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1781,6 +1809,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07dh08gs9vfll2h36kq32q9xd86xm6lyl9xikmmwlkqnmrrgqxm5"; + libName = "futures_executor"; dependencies = [ { name = "futures-core"; @@ -1811,6 +1840,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -1822,6 +1852,7 @@ rec { edition = "2018"; sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1844,6 +1875,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1855,6 +1887,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1866,6 +1899,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -2119,6 +2153,7 @@ rec { version = "0.3.5"; edition = "2021"; sha256 = "1hw2bxkzyvr0rbnpj0lkasi8h8qf3lyb63hp760cn22fjqaj3inh"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2153,6 +2188,7 @@ rec { version = "0.1.60"; edition = "2018"; sha256 = "0hdid5xz3jznm04lysjm3vi93h3c523w0hcc3xba47jl3ddbpzz7"; + libName = "iana_time_zone"; authors = [ "Andrew Straw <strawman@astraw.com>" "René Kijewski <rene.kijewski@fu-berlin.de>" @@ -2198,6 +2234,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "17r6jmj31chn7xs9698r122mapq85mfnv98bb4pg6spm0si2f67k"; + libName = "iana_time_zone_haiku"; authors = [ "René Kijewski <crates.io@k6i.de>" ]; @@ -2271,6 +2308,7 @@ rec { version = "0.3.68"; edition = "2018"; sha256 = "1vm98fhnhs4w6yakchi9ip7ar95900k9vkr24a21qlwd6r5xlv20"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -2312,6 +2350,33 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "lock_api" = rec { crateName = "lock_api"; version = "0.4.11"; @@ -2388,6 +2453,7 @@ rec { edition = "2015"; links = "lz4"; sha256 = "0059ik4xlvnss5qfh6l691psk4g3350ljxaykzv10yr0gqqppljp"; + libName = "lz4_sys"; authors = [ "Jens Heyens <jens.heyens@ewetel.net>" "Artem V. Navrotskiy <bozaro@buzzsoft.ru>" @@ -2447,11 +2513,40 @@ rec { "stable_deref_trait" = [ "dep:stable_deref_trait" ]; }; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "minimal-lexical" = rec { crateName = "minimal-lexical"; version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2489,9 +2584,9 @@ rec { }; "mio" = rec { crateName = "mio"; - version = "0.8.10"; + version = "0.8.11"; edition = "2018"; - sha256 = "02gyaxvaia9zzi4drrw59k9s0j6pa5d1y2kv7iplwjipdqlhngcg"; + sha256 = "034byyl0ardml5yliy1hmvx8arkmn9rv479pid794sm07ia519m4"; authors = [ "Carl Lerche <me@carllerche.com>" "Thomas de Zeeuw <thomasdezeeuw@gmail.com>" @@ -2558,6 +2653,7 @@ rec { edition = "2021"; sha256 = "1j1avbxw7jscyi7dmnywhlwbiny1fvg1vpp9fy4dc1pd022kva16"; procMacro = true; + libName = "multiversion_macros"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -2591,6 +2687,7 @@ rec { edition = "2021"; crateBin = [ ]; src = lib.cleanSourceWith { filter = sourceFilter; src = ../../nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; @@ -2602,6 +2699,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2622,6 +2724,10 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "nom"; packageId = "nom"; } @@ -2657,21 +2763,30 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; "default" = [ "async" "wire" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "async" "default" "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "pin-project-lite" "tokio" "wire" ]; }; "nom" = rec { crateName = "nom"; @@ -2743,6 +2858,7 @@ rec { version = "0.2.18"; edition = "2018"; sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2926,6 +3042,7 @@ rec { version = "0.2.4"; edition = "2021"; sha256 = "07wf6wf4jrxlq5p3xldxsnabp7jl06my2qp7kiwy9m3x2r5wac8i"; + libName = "parquet_format_safe"; authors = [ "Apache Thrift contributors <dev@thrift.apache.org>" "Jorge Leitao <jorgecarleitao@gmail.com>" @@ -2955,6 +3072,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2969,6 +3087,7 @@ rec { version = "0.2.13"; edition = "2018"; sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2976,6 +3095,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -3020,6 +3140,7 @@ rec { version = "0.3.29"; edition = "2015"; sha256 = "1jy6158v1316khkpmq2sjj1vgbnbnw51wffx7p0k0l9h9vlys019"; + libName = "pkg_config"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3041,21 +3162,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "std" ]; }; - "platforms" = rec { - crateName = "platforms"; - version = "3.3.0"; - edition = "2018"; - sha256 = "0k7q6pigmnvgpfasvssb12m2pv3pc94zrhrfg9by3h3wmhyfqvb2"; - authors = [ - "Tony Arcieri <bascule@gmail.com>" - "Sergey \"Shnatsel\" Davidoff <shnatsel@gmail.com>" - ]; - features = { - "default" = [ "std" ]; - "serde" = [ "dep:serde" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "polars" = rec { crateName = "polars"; version = "0.36.2"; @@ -3262,6 +3368,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0vxql6amvwyp6qj0w87vm21y33qa0i61pshs4ry7ixwgd4ps0s6f"; + libName = "polars_arrow"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -3440,6 +3547,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1pa4l1w41gdzdff81ih1z05z3gz568k81i6flibbca8v2igvqkxi"; + libName = "polars_compute"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3479,6 +3587,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "08sar9h97znpb8ziyvrrvvx28lyzc21vwsd7gvwybjxn6kkyzxfh"; + libName = "polars_core"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3639,6 +3748,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "11m80a899kp45b3dz9jbvrn5001hw8izbdp7d2czrswrixwdx5k3"; + libName = "polars_error"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3675,6 +3785,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1smamd34ghlxyxdd4aqdplk7k8xm1l626brmzlc4fvwlx3pmh13x"; + libName = "polars_io"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -3871,6 +3982,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1mdml4hs574njb23mb9gl6x92x2bb4vdfzsazkl3ifq516s0awcx"; + libName = "polars_lazy"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4065,6 +4177,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "13m7dh4vpdmcah04a7kql933l7y7045f0hybbmgff4dbav2ay29f"; + libName = "polars_ops"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4216,6 +4329,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0gay037sw5hcg2q93pxcfh7krcchl1px8g838d8vhjpnn5klv8kv"; + libName = "polars_parquet"; authors = [ "Jorge C. Leitao <jorgecarleitao@gmail.com>" "Apache Arrow <dev@arrow.apache.org>" @@ -4336,6 +4450,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "00217q51mnq7i57k3sax293xnwghm5hridbpgl11fffcfg8fmdyr"; + libName = "polars_pipe"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4449,6 +4564,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l5ca38v7ksq4595wdr6wsd74pdgszwivq9y8wfc6l6h4ib1fjiq"; + libName = "polars_plan"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4637,6 +4753,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "0by7x6jlj5dwr3f1gj49v8w65l3kpqhwhzb9qzlv6gdqrdx2ycij"; + libName = "polars_row"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4666,6 +4783,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1dcmm993gycw75a6c5hxcr6h2cy6fa2r3hsbx19h9zgxvxnlq2wz"; + libName = "polars_sql"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4730,6 +4848,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1l24fmpv5v1qshxfd4592z8x6bnjlwy4njhf9rcbdlbbr6gn9qny"; + libName = "polars_time"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4808,6 +4927,7 @@ rec { version = "0.36.2"; edition = "2021"; sha256 = "1nmvfqwyzbaxcw457amspz479y5vcnpalq043awxfixdfx5clx5i"; + libName = "polars_utils"; authors = [ "Ritchie Vink <ritchie46@gmail.com>" ]; @@ -4875,6 +4995,7 @@ rec { version = "0.2.17"; edition = "2018"; sha256 = "1pp6g52aw970adv3x2310n7glqnji96z0a9wiamzw89ibf0ayh2v"; + libName = "ppv_lite86"; authors = [ "The CryptoCorrosion Contributors" ]; @@ -4888,6 +5009,7 @@ rec { version = "1.0.78"; edition = "2021"; sha256 = "1bjak27pqdn4f4ih1c9nr3manzyavsgqmf76ygw9k76q8pb2lhp2"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -5091,6 +5213,7 @@ rec { edition = "2021"; links = "rayon-core"; sha256 = "1qpwim68ai5h0j7axa8ai8z0payaawv3id0lrgkqmapx7lx8fr8l"; + libName = "rayon_core"; authors = [ "Niko Matsakis <niko@alum.mit.edu>" "Josh Stone <cuviper@gmail.com>" @@ -5192,6 +5315,7 @@ rec { version = "0.4.5"; edition = "2021"; sha256 = "1karc80mx15z435rm1jg3sqylnc58nxi15gqypcd1inkzzpqgfav"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5252,6 +5376,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -5268,6 +5393,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -5350,6 +5476,7 @@ rec { edition = "2018"; sha256 = "1d50kbaslrrd0374ivx15jg57f03y5xzil1wd2ajlvajzlkbzw53"; procMacro = true; + libName = "seq_macro"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -5507,6 +5634,7 @@ rec { version = "1.4.1"; edition = "2015"; sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -5745,6 +5873,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1wscqj3s30qknda778wf7z99mknk65p0h9hhs658l4pvkfqw6v5z"; + libName = "streaming_decompression"; dependencies = [ { name = "fallible-streaming-iterator"; @@ -5758,6 +5887,7 @@ rec { version = "0.1.9"; edition = "2021"; sha256 = "0845zdv8qb7zwqzglpqc0830i43xh3fb6vqms155wz85qfvk28ib"; + libName = "streaming_iterator"; authors = [ "Steven Fackler <sfackler@gmail.com>" ]; @@ -5960,6 +6090,7 @@ rec { version = "0.1.5"; edition = "2021"; sha256 = "1gb974chm9aj8ifkyibylxkyb5an4bf5y8dxb18pqmck698gmdfg"; + libName = "target_features"; authors = [ "Caleb Zulawski <caleb.zulawski@gmail.com>" ]; @@ -5987,6 +6118,7 @@ rec { edition = "2021"; sha256 = "0w9ldp8fa574ilz4dn7y7scpcq66vdjy59qal8qdpwsh7faal3zs"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6122,6 +6254,7 @@ rec { edition = "2021"; sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6147,6 +6280,7 @@ rec { version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -6197,6 +6331,96 @@ rec { }; resolvedDefaultFeatures = [ "default" "io" "io-util" ]; }; + "tracing" = rec { + crateName = "tracing"; + version = "0.1.40"; + edition = "2018"; + sha256 = "1vv48dac9zgj9650pg2b4d0j3w6f3x9gbggf43scq5hrlysklln3"; + authors = [ + "Eliza Weisman <eliza@buoyant.io>" + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "pin-project-lite"; + packageId = "pin-project-lite"; + } + { + name = "tracing-attributes"; + packageId = "tracing-attributes"; + optional = true; + } + { + name = "tracing-core"; + packageId = "tracing-core"; + usesDefaultFeatures = false; + } + ]; + features = { + "attributes" = [ "tracing-attributes" ]; + "default" = [ "std" "attributes" ]; + "log" = [ "dep:log" ]; + "log-always" = [ "log" ]; + "std" = [ "tracing-core/std" ]; + "tracing-attributes" = [ "dep:tracing-attributes" ]; + "valuable" = [ "tracing-core/valuable" ]; + }; + resolvedDefaultFeatures = [ "attributes" "default" "std" "tracing-attributes" ]; + }; + "tracing-attributes" = rec { + crateName = "tracing-attributes"; + version = "0.1.27"; + edition = "2018"; + sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; + procMacro = true; + libName = "tracing_attributes"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + "Eliza Weisman <eliza@buoyant.io>" + "David Barsky <dbarsky@amazon.com>" + ]; + dependencies = [ + { + name = "proc-macro2"; + packageId = "proc-macro2"; + } + { + name = "quote"; + packageId = "quote"; + } + { + name = "syn"; + packageId = "syn 2.0.48"; + usesDefaultFeatures = false; + features = [ "full" "parsing" "printing" "visit-mut" "clone-impls" "extra-traits" "proc-macro" ]; + } + ]; + features = { }; + }; + "tracing-core" = rec { + crateName = "tracing-core"; + version = "0.1.32"; + edition = "2018"; + sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; + authors = [ + "Tokio Contributors <team@tokio.rs>" + ]; + dependencies = [ + { + name = "once_cell"; + packageId = "once_cell"; + optional = true; + } + ]; + features = { + "default" = [ "std" "valuable/std" ]; + "once_cell" = [ "dep:once_cell" ]; + "std" = [ "once_cell" ]; + "valuable" = [ "dep:valuable" ]; + }; + resolvedDefaultFeatures = [ "once_cell" "std" ]; + }; "typenum" = rec { crateName = "typenum"; version = "1.17.0"; @@ -6217,6 +6441,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -6227,6 +6452,7 @@ rec { version = "0.1.11"; edition = "2015"; sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -6271,6 +6497,7 @@ rec { version = "0.2.91"; edition = "2018"; sha256 = "0zwbb07ln4m5hh6axamc701nnj090nd66syxbf6bagzf189j9qf1"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -6302,6 +6529,7 @@ rec { version = "0.2.91"; edition = "2018"; sha256 = "02zpi9sjzhd8kfv1yj9m1bs4a41ik9ii5bc8hjf60arm1j8f3ry9"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -6347,6 +6575,7 @@ rec { edition = "2018"; sha256 = "1va6dilw9kcnvsg5043h5b9mwc5sgq0lyhj9fif2n62qsgigj2mk"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -6371,6 +6600,7 @@ rec { version = "0.2.91"; edition = "2018"; sha256 = "0rlyl3yzwbcnc691mvx78m1wbqf1qs52mlc3g88bh7ihwrdk4bv4"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -6409,6 +6639,7 @@ rec { edition = "2018"; links = "wasm_bindgen"; sha256 = "0f4qmjv57ppwi4xpdxgcd77vz9vmvlrnybg8dj430hzhvk96n62g"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -6496,6 +6727,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -6506,6 +6738,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -7197,6 +7430,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1nc3qv7sy24x0nlnb32f7alzpd6f72l4p24vl65vydbyil669ark"; + libName = "windows_core"; authors = [ "Microsoft" ]; @@ -7214,6 +7448,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -7507,6 +7742,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -7754,6 +7990,7 @@ rec { version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7801,6 +8038,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "1kg7a27ynzw8zz3krdgy6w5gbqcji27j1sz4p7xk2j5j8082064a"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -7988,6 +8226,7 @@ rec { version = "0.8.8"; edition = "2018"; sha256 = "0q9xl4kxibh61631lw9m7if7pkdvq3pp5ss52zdkxs6rirkhdgjk"; + libName = "xxhash_rust"; authors = [ "Douman <douman@gmx.se>" ]; @@ -8036,6 +8275,7 @@ rec { edition = "2018"; sha256 = "19nj11md42aijyqnfx8pa647fjzhz537xyc624rajwwfrn6b3qcw"; procMacro = true; + libName = "zerocopy_derive"; authors = [ "Joshua Liebow-Feeser <joshlf@google.com>" ]; @@ -8110,6 +8350,7 @@ rec { version = "7.0.0"; edition = "2018"; sha256 = "0gpav2lcibrpmyslmjkcn3w0w64qif3jjljd2h8lr4p249s7qx23"; + libName = "zstd_safe"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8143,6 +8384,7 @@ rec { edition = "2018"; links = "zstd"; sha256 = "0mk6a2367swdi22zg03lcackpnvgq96d7120awd4i83lm2lfy5ly"; + libName = "zstd_sys"; authors = [ "Alexandre Bury <alexandre.bury@gmail.com>" ]; @@ -8272,52 +8514,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/tvix/tools/weave/default.nix b/tvix/tools/weave/default.nix index 8c5e1be928d1..3d979b6d3327 100644 --- a/tvix/tools/weave/default.nix +++ b/tvix/tools/weave/default.nix @@ -6,4 +6,6 @@ src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; }; -}).rootCrate.build +}).rootCrate.build.overrideAttrs { + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; +} diff --git a/tvix/tracing/Cargo.toml b/tvix/tracing/Cargo.toml index 3f3e5330c621..acd968eb231f 100644 --- a/tvix/tracing/Cargo.toml +++ b/tvix/tracing/Cargo.toml @@ -4,27 +4,27 @@ version = "0.1.0" edition = "2021" [dependencies] -lazy_static = "1.4.0" -tracing = { version = "0.1.40", features = ["max_level_trace", "release_max_level_debug"] } -tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -indicatif = "0.17.8" -tracing-indicatif = "0.3.6" -tokio = { version = "1.32.0" , features = ["sync", "rt"] } -thiserror = "1.0.38" +lazy_static = { workspace = true } +tracing = { workspace = true, features = ["max_level_trace", "release_max_level_debug"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +indicatif = { workspace = true } +tracing-indicatif = { workspace = true } +tokio = { workspace = true, features = ["sync", "rt"] } +thiserror = { workspace = true } -tracing-opentelemetry = { version = "0.25.0", optional = true } -opentelemetry = { version = "0.24.0", optional = true } -opentelemetry-otlp = { version = "0.17.0", optional = true } -opentelemetry_sdk = { version = "0.24.1", features = ["rt-tokio"], optional = true } -tracing-tracy = { version = "0.11.0", features = ["flush-on-exit"], optional = true } -opentelemetry-http = { version = "0.13.0", optional = true } +tracing-opentelemetry = { workspace = true, optional = true } +opentelemetry = { workspace = true, optional = true } +opentelemetry-otlp = { workspace = true, optional = true } +opentelemetry_sdk = { workspace = true, features = ["rt-tokio"], optional = true } +tracing-tracy = { workspace = true, features = ["flush-on-exit"], optional = true } +opentelemetry-http = { workspace = true, optional = true } -tonic = { version = "0.12.0", optional = true } -http = { version = "1.1.0", optional = true } +tonic = { workspace = true, optional = true } +http = { workspace = true, optional = true } -reqwest-tracing = { version = "0.5.0", default-features = false, optional = true } +reqwest-tracing = { workspace = true, optional = true } -axum = { version = "0.7.5", optional = true } +axum = { workspace = true, optional = true } [features] default = [] diff --git a/tvix/tracing/default.nix b/tvix/tracing/default.nix index ef1985cb47fb..b519d0ffc0b3 100644 --- a/tvix/tracing/default.nix +++ b/tvix/tracing/default.nix @@ -4,8 +4,8 @@ runTests = true; }).overrideAttrs (old: rec { meta.ci.targets = lib.filter (x: lib.hasPrefix "with-features" x || x == "no-features") (lib.attrNames passthru); - passthru = depot.tvix.utils.mkFeaturePowerset { + passthru = old.passthru // (depot.tvix.utils.mkFeaturePowerset { inherit (old) crateName; features = [ "otlp" "tracy" "tonic" "reqwest" "axum" ]; - }; + }); }) diff --git a/tvix/utils.nix b/tvix/utils.nix index dc40df5007ea..6fa99e63eb05 100644 --- a/tvix/utils.nix +++ b/tvix/utils.nix @@ -1,4 +1,4 @@ -{ lib, depot, ... }: +{ pkgs, lib, depot, ... }: { mkFeaturePowerset = { crateName, features, override ? { } }: @@ -34,7 +34,7 @@ fileset = lib.fileset.intersection (lib.fileset.fromSource root) # We build our final fileset from the original src (lib.fileset.unions ([ - (root + "/src") + (lib.fileset.maybeMissing (root + "/src")) # src may be missing if the crate just has tests for example (lib.fileset.fileFilter (f: f.hasExt "rs") root) ] ++ lib.optionals cargoSupport [ (lib.fileset.fileFilter (f: f.name == "Cargo.toml") root) @@ -62,6 +62,15 @@ extraFileset = root + "/testdata"; }; }; + + nix-compat-derive = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + + nix-compat-derive-tests = prev: { + src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; + }; + tvix-build = prev: { src = depot.tvix.utils.filterRustCrateSrc rec { root = prev.src.origSrc; @@ -125,4 +134,27 @@ src = depot.tvix.utils.filterRustCrateSrc { root = prev.src.origSrc; }; }; }; + + # This creates an extraStep in CI to check whether the Cargo.nix file is up-to-date. + mkCrate2nixCheck = + path: # The path to the Cargo.nix to be checked. + let + relCrateRoot = lib.removePrefix "./" (builtins.dirOf (lib.path.removePrefix depot.path.origSrc path)); + in + { + label = "crate2nix check for ${relCrateRoot}"; + needsOutput = true; + alwaysRun = true; + command = pkgs.writeShellScript "crate2nix-check-for-${lib.replaceStrings [ "/" ] ["-"] relCrateRoot}" '' + (cd $(git rev-parse --show-toplevel)/${relCrateRoot} && + ${depot.tools.crate2nix-generate}/bin/crate2nix-generate && + if [[ -n "$(git status --porcelain -unormal Cargo.nix)" ]]; then + echo "----------------------------------------------------------------------------------------------------" + echo "Cargo.nix needs to be updated, run 'mg run //tools/crate2nix-generate' in ${relCrateRoot}" + echo "----------------------------------------------------------------------------------------------------" + exit 1 + fi + ) + ''; + }; } diff --git a/tvix/verify-lang-tests/default.nix b/tvix/verify-lang-tests/default.nix index 29d963065ea3..e6de1c1f455c 100644 --- a/tvix/verify-lang-tests/default.nix +++ b/tvix/verify-lang-tests/default.nix @@ -11,7 +11,7 @@ let inherit (pkgs.nixVersions) nix_2_3; # The latest Nix version we've verified to work for our testing suite. - nix_latest_verified = pkgs.nixVersions.nix_2_23; + nix_latest_verified = pkgs.nixVersions.nix_2_24; parseTest = dir: baseName: let diff --git a/users/Profpatsch/.gitignore b/users/Profpatsch/.gitignore index c33954f53a06..95941cd52dbe 100644 --- a/users/Profpatsch/.gitignore +++ b/users/Profpatsch/.gitignore @@ -1 +1,2 @@ dist-newstyle/ +result-* diff --git a/users/Profpatsch/README.md b/users/Profpatsch/README.md index 5bb74cd7580f..0f2147e9afc1 100644 --- a/users/Profpatsch/README.md +++ b/users/Profpatsch/README.md @@ -2,7 +2,7 @@ Welcome, Welcome. -Welcome to my user dir, where we optimize f*** around, in order to optimize finding out. +Welcome to my user dir, where we optimize f\*\*\*ing around, in order to optimize finding out. ![fafo graph](./fafo.jpg) diff --git a/users/Profpatsch/git-db/default.nix b/users/Profpatsch/git-db/default.nix deleted file mode 100644 index ad5d927677bf..000000000000 --- a/users/Profpatsch/git-db/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ depot, pkgs, lib, ... }: - -depot.nix.writers.rustSimple -{ - name = "git-db"; - dependencies = [ - depot.third_party.rust-crates.git2 - ]; -} - (builtins.readFile ./git-db.rs) diff --git a/users/Profpatsch/git-db/git-db.rs b/users/Profpatsch/git-db/git-db.rs deleted file mode 100644 index c8019bf03661..000000000000 --- a/users/Profpatsch/git-db/git-db.rs +++ /dev/null @@ -1,90 +0,0 @@ -extern crate git2; -use std::os::unix::ffi::OsStrExt; -use std::path::PathBuf; - -const DEFAULT_BRANCH: &str = "refs/heads/main"; - -fn main() { - let git_db_dir = std::env::var_os("GIT_DB_DIR").expect("set GIT_DB_DIR"); - let git_db = PathBuf::from(git_db_dir).join("git"); - - std::fs::create_dir_all(&git_db).unwrap(); - - let repo = git2::Repository::init_opts( - &git_db, - git2::RepositoryInitOptions::new() - .bare(true) - .mkpath(true) - .description("git-db database") - .initial_head(DEFAULT_BRANCH), - ) - .expect(&format!( - "unable to create or open bare git repo at {}", - &git_db.display() - )); - - let mut index = repo.index().expect("cannot get the git index file"); - eprintln!("{:#?}", index.version()); - index.clear().expect("could not clean the index"); - - let now = std::time::SystemTime::now() - .duration_since(std::time::SystemTime::UNIX_EPOCH) - .expect("unable to get system time"); - - let now_git_time = git2::IndexTime::new( - now.as_secs() as i32, // lol - u32::from(now.subsec_nanos()), - ); - - let data = "hi, it’s me".as_bytes(); - - index - .add_frombuffer( - &git2::IndexEntry { - mtime: now_git_time, - ctime: now_git_time, - // don’t make sense - dev: 0, - ino: 0, - mode: /*libc::S_ISREG*/ 0b1000 << (3+9) | /* read write for owner */ 0o644, - uid: 0, - gid: 0, - file_size: data.len() as u32, // lol again - id: git2::Oid::zero(), - flags: 0, - flags_extended: 0, - path: "hi.txt".as_bytes().to_owned(), - }, - data, - ) - .expect("could not add data to index"); - - let oid = index.write_tree().expect("could not write index tree"); - - let to_add_tree = repo - .find_tree(oid) - .expect("we just created this tree, where did it go?"); - - let parent_commits = match repo.find_reference(DEFAULT_BRANCH) { - Ok(ref_) => vec![ref_.peel_to_commit().expect(&format!( - "reference {} does not point to a commit", - DEFAULT_BRANCH - ))], - Err(err) => match err.code() { - // no commit exists yet - git2::ErrorCode::NotFound => vec![], - _ => panic!("could not read latest commit from {}", DEFAULT_BRANCH), - }, - }; - repo.commit( - Some(DEFAULT_BRANCH), - &git2::Signature::now("Mr. Authorboy", "author@example.com").unwrap(), - &git2::Signature::now("Mr. Commiterboy", "committer@example.com").unwrap(), - "This is my first commit!\n\ - \n\ - I wonder if it supports extended commit descriptions?\n", - &to_add_tree, - &parent_commits.iter().collect::<Vec<_>>()[..], - ) - .expect("could not commit the index we just wrote"); -} diff --git a/users/Profpatsch/lyric.nix b/users/Profpatsch/lyric.nix new file mode 100644 index 000000000000..b3914d195e1f --- /dev/null +++ b/users/Profpatsch/lyric.nix @@ -0,0 +1,54 @@ +# Display lyrics for the given search string; +# search string can contain a substring of band name, album name, song title +# +# Use the database dump from https://lrclib.net/db-dumps and place it in ~/.cache/lyric/lrclib-db-dump.sqlite3 + +{ depot, pkgs, lib, ... }: + +let + bins = depot.nix.getBins pkgs.sqlite-utils [ "sqlite-utils" ] + // depot.nix.getBins pkgs.jq [ "jq" ]; + +in +depot.nix.writeExecline "lyric" { readNArgs = 1; } [ + "backtick" + "-E" + "cache" + [ depot.users.Profpatsch.xdg-cache-home ] + "pipeline" + [ + bins.sqlite-utils + "query" + "\${cache}/lyric/lrclib-db-dump.sqlite3" + '' + select + synced_lyrics, + has_synced_lyrics, + plain_lyrics + from + tracks_fts(:searchstring) tf + join tracks t on t.rowid = tf.rowid + join lyrics l on t.rowid = l.track_id + order by + t.id + limit + 1 + '' + "--param" + "searchstring" + "$1" + ] + bins.jq + "-r" + '' + if .[0] == null + then "" + else + .[0] + | if .has_synced_lyrics == 1 + then .synced_lyrics + else .plain_lyrics + end + end + '' +] diff --git a/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs b/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs index 6ccc45faad0a..87928678a052 100644 --- a/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs +++ b/users/Profpatsch/my-prelude/src/Postgres/MonadPostgres.hs @@ -34,7 +34,7 @@ import Database.PostgreSQL.Simple qualified as Postgres import Database.PostgreSQL.Simple.FromRow qualified as PG import Database.PostgreSQL.Simple.ToField (ToField) import Database.PostgreSQL.Simple.ToRow (ToRow (toRow)) -import Database.PostgreSQL.Simple.Types (Query (..)) +import Database.PostgreSQL.Simple.Types (PGArray (PGArray), Query (..)) import GHC.IO.Handle (Handle) import GHC.Records (getField) import Label @@ -930,6 +930,70 @@ withEvent span start end act = do ) pure res +unzipPGArray :: + forall l1 t1 l2 t2 r. + ( HasField l1 r t1, + HasField l2 r t2 + ) => + [r] -> + (PGArray t1, PGArray t2) +{-# INLINEABLE unzipPGArray #-} +unzipPGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs + ) + +unzip3PGArray :: + forall l1 t1 l2 t2 l3 t3 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3) +{-# INLINEABLE unzip3PGArray #-} +unzip3PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs + ) + +unzip4PGArray :: + forall l1 t1 l2 t2 l3 t3 l4 t4 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3, + HasField l4 r t4 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3, PGArray t4) +{-# INLINEABLE unzip4PGArray #-} +unzip4PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs, + PGArray $ getField @l4 <$> xs + ) + +unzip5PGArray :: + forall l1 t1 l2 t2 l3 t3 l4 t4 l5 t5 r. + ( HasField l1 r t1, + HasField l2 r t2, + HasField l3 r t3, + HasField l4 r t4, + HasField l5 r t5 + ) => + [r] -> + (PGArray t1, PGArray t2, PGArray t3, PGArray t4, PGArray t5) +{-# INLINEABLE unzip5PGArray #-} +unzip5PGArray xs = + ( PGArray $ getField @l1 <$> xs, + PGArray $ getField @l2 <$> xs, + PGArray $ getField @l3 <$> xs, + PGArray $ getField @l4 <$> xs, + PGArray $ getField @l5 <$> xs + ) + instance (ToField t1) => ToRow (Label l1 t1) where toRow t2 = toRow $ PG.Only $ getField @l1 t2 diff --git a/users/Profpatsch/my-prelude/src/Pretty.hs b/users/Profpatsch/my-prelude/src/Pretty.hs index d9d4ce132b11..6711ea951a48 100644 --- a/users/Profpatsch/my-prelude/src/Pretty.hs +++ b/users/Profpatsch/my-prelude/src/Pretty.hs @@ -8,6 +8,7 @@ module Pretty printShowedStringPretty, -- constructors hidden prettyErrs, + prettyErrsNoColor, message, messageString, pretty, @@ -19,6 +20,7 @@ where import Data.Aeson qualified as Json import Data.Aeson.Encode.Pretty qualified as Aeson.Pretty import Data.List qualified as List +import Data.String (IsString (fromString)) import Data.Text.Lazy.Builder qualified as Text.Builder import Language.Haskell.HsColour ( Output (TTYg), @@ -62,7 +64,6 @@ showPrettyJson val = & toStrict -- | Display a list of 'Err's as a colored error message --- and abort the test. prettyErrs :: [Err] -> String prettyErrs errs = res where @@ -74,6 +75,15 @@ prettyErrs errs = res prettyShowString :: String -> String prettyShowString = hscolour' . nicify +-- | Display a list of 'Err's as a plain-colored error message +prettyErrsNoColor :: [Err] -> String +prettyErrsNoColor errs = res + where + res = List.intercalate "\n" $ map one errs + one = \case + ErrMsg s -> s + ErrPrettyString s -> nicify s + -- | Small DSL for pretty-printing errors data Err = -- | Message to display in the error @@ -81,6 +91,9 @@ data Err | -- | Pretty print a String that was produced by 'show' ErrPrettyString String +instance IsString Err where + fromString s = ErrMsg s + -- | Plain message to display, as 'Text' message :: Text -> Err message = ErrMsg . textToString diff --git a/users/Profpatsch/nix-home/default.nix b/users/Profpatsch/nix-home/default.nix index ee154c549a6b..72c77122fc9b 100644 --- a/users/Profpatsch/nix-home/default.nix +++ b/users/Profpatsch/nix-home/default.nix @@ -158,7 +158,10 @@ let name = "scripts/lw"; path = depot.users.Profpatsch.lorri-wait-for-eval; } - + { + name = "scripts/lyric"; + path = depot.users.Profpatsch.lyric; + } ] ++ (lib.pipe depot.users.Profpatsch.aliases [ diff --git a/users/Profpatsch/openlab-tools/src/OpenlabTools.hs b/users/Profpatsch/openlab-tools/src/OpenlabTools.hs index 16f1b626ac10..7ba52c30229d 100644 --- a/users/Profpatsch/openlab-tools/src/OpenlabTools.hs +++ b/users/Profpatsch/openlab-tools/src/OpenlabTools.hs @@ -389,7 +389,7 @@ httpJson opts span parser req = do | statusCode == 200, Nothing <- contentType -> Left [fmt|Server returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Server returned an non-200 error code, code {code}: {resp & showPretty}|] + | code <- statusCode -> Left $ singleError [fmt|Server returned an non-200 error code, code {code}: {[pretty resp] & prettyErrsNoColor}|] ) >>= assertM span diff --git a/users/Profpatsch/whatcd-resolver/.gitignore b/users/Profpatsch/whatcd-resolver/.gitignore new file mode 100644 index 000000000000..f9c4bdf8b808 --- /dev/null +++ b/users/Profpatsch/whatcd-resolver/.gitignore @@ -0,0 +1 @@ +/.ninja/ diff --git a/users/Profpatsch/whatcd-resolver/services/jaeger/run b/users/Profpatsch/whatcd-resolver/services/jaeger/run index 41332f8bb61b..7800d88287d5 100755 --- a/users/Profpatsch/whatcd-resolver/services/jaeger/run +++ b/users/Profpatsch/whatcd-resolver/services/jaeger/run @@ -1,3 +1,3 @@ #!/usr/bin/env execlineb importas -i DEPOT_ROOT DEPOT_ROOT -nix-run { $DEPOT_ROOT -A users.Profpatsch.jaeger -kK --builders '' } +nix-run { $DEPOT_ROOT -A users.Profpatsch.jaeger -kK } diff --git a/users/Profpatsch/whatcd-resolver/src/AppT.hs b/users/Profpatsch/whatcd-resolver/src/AppT.hs index 6a8637bb1660..8550d4aa713e 100644 --- a/users/Profpatsch/whatcd-resolver/src/AppT.hs +++ b/users/Profpatsch/whatcd-resolver/src/AppT.hs @@ -9,8 +9,11 @@ import Data.Error.Tree import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict qualified as HashMap import Data.Pool (Pool) +import Data.String (IsString (fromString)) import Data.Text qualified as Text import Database.PostgreSQL.Simple qualified as Postgres +import FieldParser (FieldParser) +import FieldParser qualified as Field import GHC.Stack qualified import Json.Enc import Json.Enc qualified as Enc @@ -20,6 +23,7 @@ import OpenTelemetry.Trace.Core qualified as Otel hiding (inSpan, inSpan') import OpenTelemetry.Trace.Monad qualified as Otel import PossehlAnalyticsPrelude import Postgres.MonadPostgres +import Pretty qualified import System.IO qualified as IO import UnliftIO import Prelude hiding (span) @@ -40,13 +44,17 @@ data Context = Context newtype AppT m a = AppT {unAppT :: ReaderT Context m a} deriving newtype (Functor, Applicative, Monad, MonadIO, MonadUnliftIO, MonadThrow) -newtype AppException = AppException Text +data AppException + = AppExceptionTree ErrorTree + | AppExceptionPretty [Pretty.Err] deriving anyclass (Exception) -instance Show AppException where - showsPrec _ (AppException t) = ("AppException: " ++) . (textToString t ++) +instance IsString AppException where + fromString s = AppExceptionTree (fromString s) --- * Logging & Opentelemetry +instance Show AppException where + showsPrec _ (AppExceptionTree t) = ("AppException: " ++) . ((textToString $ prettyErrorTree t) ++) + showsPrec _ (AppExceptionPretty t) = ("AppException: " ++) . ((Pretty.prettyErrsNoColor t) ++) instance (MonadIO m) => MonadLogger (AppT m) where monadLoggerLog loc src lvl msg = liftIO $ Logger.defaultOutput IO.stderr loc src lvl (Logger.toLogStr msg) @@ -88,47 +96,58 @@ addEventSimple span name = jsonAttribute :: Enc -> Otel.Attribute jsonAttribute e = e & Enc.encToTextPretty & Otel.toAttribute -orThrowAppErrorNewSpan :: (MonadThrow m, MonadOtel m) => Text -> Either ErrorTree a -> m a +parseOrThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> FieldParser from to -> from -> m to +parseOrThrow span fp f = + f & Field.runFieldParser fp & \case + Left err -> appThrow span (AppExceptionTree $ singleError err) + Right a -> pure a + +orThrowAppErrorNewSpan :: (MonadThrow m, MonadOtel m) => Text -> Either AppException a -> m a orThrowAppErrorNewSpan msg = \case - Left err -> appThrowTreeNewSpan msg err + Left err -> appThrowNewSpan msg err Right a -> pure a -appThrowTreeNewSpan :: (MonadThrow m, MonadOtel m) => Text -> ErrorTree -> m a -appThrowTreeNewSpan spanName exc = inSpan' spanName $ \span -> do - let msg = prettyErrorTree exc +appThrowNewSpan :: (MonadThrow m, MonadOtel m) => Text -> AppException -> m a +appThrowNewSpan spanName exc = inSpan' spanName $ \span -> do + let msg = case exc of + AppExceptionTree e -> prettyErrorTree e + AppExceptionPretty p -> Pretty.prettyErrsNoColor p & stringToText recordException span ( T2 (label @"type_" "AppException") (label @"message" msg) ) - throwM $ AppException msg + throwM $ exc -appThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> ErrorTree -> m a -appThrowTree span exc = do - let msg = prettyErrorTree exc +appThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> AppException -> m a +appThrow span exc = do + let msg = case exc of + AppExceptionTree e -> prettyErrorTree e + AppExceptionPretty p -> Pretty.prettyErrsNoColor p & stringToText recordException span ( T2 (label @"type_" "AppException") (label @"message" msg) ) - throwM $ AppException msg + throwM $ exc -orAppThrowTree :: (MonadThrow m, MonadIO m) => Otel.Span -> Either ErrorTree a -> m a -orAppThrowTree span = \case - Left err -> appThrowTree span err +orAppThrow :: (MonadThrow m, MonadIO m) => Otel.Span -> Either AppException a -> m a +orAppThrow span = \case + Left err -> appThrow span err Right a -> pure a -assertM :: (MonadThrow f, MonadIO f) => Otel.Span -> (t -> Either ErrorTree a) -> t -> f a +-- | If action returns a Left, throw an AppException +assertM :: (MonadThrow f, MonadIO f) => Otel.Span -> (t -> Either AppException a) -> t -> f a assertM span f v = case f v of Right a -> pure a - Left err -> appThrowTree span err + Left err -> appThrow span err -assertMNewSpan :: (MonadThrow f, MonadOtel f) => Text -> (t -> Either ErrorTree a) -> t -> f a +assertMNewSpan :: (MonadThrow f, MonadOtel f) => Text -> (t -> Either AppException a) -> t -> f a assertMNewSpan spanName f v = case f v of Right a -> pure a - Left err -> appThrowTreeNewSpan spanName err + Left err -> appThrowNewSpan spanName err -- | A specialized variant of @addEvent@ that records attributes conforming to -- the OpenTelemetry specification's diff --git a/users/Profpatsch/whatcd-resolver/src/Http.hs b/users/Profpatsch/whatcd-resolver/src/Http.hs index f0f635e7d837..14ce191d520e 100644 --- a/users/Profpatsch/whatcd-resolver/src/Http.hs +++ b/users/Profpatsch/whatcd-resolver/src/Http.hs @@ -91,13 +91,13 @@ httpJson opts parser req = inSpan' "HTTP Request (JSON)" $ \span -> do | statusCode == 200, Nothing <- contentType -> Left [fmt|Server returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Server returned an non-200 error code, code {code}: {resp & showPretty}|] + | code <- statusCode -> Left $ AppExceptionPretty [[fmt|Server returned an non-200 error code, code {code}:|], pretty resp] ) >>= assertM span ( \body -> Json.parseStrict parser body - & first (Json.parseErrorTree "could not parse redacted response") + & first (AppExceptionTree . Json.parseErrorTree "could not parse HTTP response") ) doRequestJson :: diff --git a/users/Profpatsch/whatcd-resolver/src/Redacted.hs b/users/Profpatsch/whatcd-resolver/src/Redacted.hs index 5b6751346b18..7bf9e8c2ce27 100644 --- a/users/Profpatsch/whatcd-resolver/src/Redacted.hs +++ b/users/Profpatsch/whatcd-resolver/src/Redacted.hs @@ -275,20 +275,23 @@ redactedSearchAndInsert extraArguments = do , torrent_id , full_json_result) |] - ( [ ( dat.torrentGroupIdPg :: Int, - group.torrentId :: Int, - group.fullJsonResult :: Json.Value - ) + ( [ T3 + (getLabel @"torrentGroupIdPg" dat) + (getLabel @"torrentId" group) + (getLabel @"fullJsonResult" group) | dat <- dats, group <- dat.torrents ] & unzip3PGArray + @"torrentGroupIdPg" + @Int + @"torrentId" + @Int + @"fullJsonResult" + @Json.Value ) pure () -unzip3PGArray :: [(a1, a2, a3)] -> (PGArray a1, PGArray a2, PGArray a3) -unzip3PGArray xs = xs & unzip3 & \(a, b, c) -> (PGArray a, PGArray b, PGArray c) - redactedGetTorrentFileAndInsert :: ( HasField "torrentId" r Int, MonadPostgres m, @@ -357,7 +360,7 @@ assertOneUpdated :: m () assertOneUpdated span name x = case x.numberOfRowsAffected of 1 -> pure () - n -> appThrowTree span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) + n -> appThrow span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) data TorrentData transmissionInfo = TorrentData { groupId :: Int, @@ -365,7 +368,8 @@ data TorrentData transmissionInfo = TorrentData seedingWeight :: Int, artists :: [T2 "artistId" Int "artistName" Text], torrentGroupJson :: TorrentGroupJson, - torrentStatus :: TorrentStatus transmissionInfo + torrentStatus :: TorrentStatus transmissionInfo, + torrentFormat :: Text } data TorrentGroupJson = TorrentGroupJson @@ -413,7 +417,11 @@ getBestTorrents opts = do -- filter by artist id AND (?::bool OR (to_jsonb(?::int) <@ (jsonb_path_query_array(full_json_result, '$.artists[*].id')))) - ORDER BY torrent_group, seeding_weight DESC + ORDER BY + torrent_group, + -- prefer torrents which we already downloaded + torrent_file, + seeding_weight DESC ) SELECT tg.group_id, @@ -423,7 +431,8 @@ getBestTorrents opts = do tg.full_json_result->>'groupName' AS group_name, tg.full_json_result->>'groupYear' AS group_year, t.torrent_file IS NOT NULL AS has_torrent_file, - t.transmission_torrent_hash + t.transmission_torrent_hash, + t.full_json_result->>'encoding' AS torrent_format FROM filtered_torrents f JOIN redacted.torrents t ON t.id = f.id JOIN redacted.torrent_groups tg ON tg.id = t.torrent_group @@ -452,8 +461,8 @@ getBestTorrents opts = do groupYear <- Dec.textParse Field.decimalNatural pure $ TorrentGroupJson {..} hasTorrentFile <- Dec.fromField @Bool - transmissionTorrentHash <- - Dec.fromField @(Maybe Text) + transmissionTorrentHash <- Dec.fromField @(Maybe Text) + torrentFormat <- Dec.text pure $ TorrentData { torrentStatus = @@ -463,6 +472,13 @@ getBestTorrents opts = do | Just hash <- transmissionTorrentHash -> InTransmission $ T2 (label @"torrentHash" hash) (label @"transmissionInfo" ()), + torrentFormat = case torrentFormat of + "Lossless" -> "flac" + "V0 (VBR)" -> "V0" + "V2 (VBR)" -> "V2" + "320" -> "320" + "256" -> "256" + o -> o, .. } ) @@ -513,7 +529,7 @@ httpTorrent span req = | statusCode == 200, Nothing <- contentType -> Left [fmt|Redacted returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Redacted returned an non-200 error code, code {code}: {resp & showPretty}|] + | code <- statusCode -> Left $ AppExceptionPretty [[fmt|Redacted returned an non-200 error code, code {code}|], pretty resp] ) redactedApiRequestJson :: diff --git a/users/Profpatsch/whatcd-resolver/src/Transmission.hs b/users/Profpatsch/whatcd-resolver/src/Transmission.hs index acbab001621c..3238780af70f 100644 --- a/users/Profpatsch/whatcd-resolver/src/Transmission.hs +++ b/users/Profpatsch/whatcd-resolver/src/Transmission.hs @@ -49,18 +49,20 @@ scientificPercentage = | otherwise -> Right $ Percentage $ ceiling (f * 100) ) --- | Fetch the current status from transmission, and remove the tranmission hash from our database --- iff it does not exist in transmission anymore +-- | Fetch the current status from transmission, +-- and remove the transmission hash and torrent file from our database iff it does not exist in transmission anymore getAndUpdateTransmissionTorrentsStatus :: ( MonadTransmission m, MonadThrow m, MonadLogger m, MonadPostgres m, - MonadOtel m + MonadOtel m, + HasField "groupId" info Int, + HasField "torrentId" info Int ) => - Map (Label "torrentHash" Text) () -> - (Transaction m (Map (Label "torrentHash" Text) (Label "percentDone" Percentage))) -getAndUpdateTransmissionTorrentsStatus knownTorrents = do + Map (Label "torrentHash" Text) info -> + (Transaction m (Label "knownTorrentsStale" Bool, (Map (Label "torrentHash" Text) (Label "percentDone" Percentage)))) +getAndUpdateTransmissionTorrentsStatus knownTorrents = inSpan' "getAndUpdateTransmissionTorrentsStatus" $ \span -> do let fields = ["hashString", "percentDone"] actualTorrents <- lift @Transaction $ @@ -77,14 +79,36 @@ getAndUpdateTransmissionTorrentsStatus knownTorrents = do ) <&> Map.fromList let toDelete = Map.difference knownTorrents actualTorrents - execute - [fmt| - UPDATE redacted.torrents_json - SET transmission_torrent_hash = NULL - WHERE transmission_torrent_hash = ANY (?::text[]) - |] - $ Only (toDelete & Map.keys <&> (.torrentHash) & PGArray :: PGArray Text) - pure actualTorrents + if + | Map.null toDelete -> do + addEventSimple span "We know about all transmission hashes." + pure (label @"knownTorrentsStale" False, actualTorrents) + | otherwise -> inSpan' "Delete outdated transmission hashes" $ \span' -> do + addAttribute + span' + "db.delete-transmission-hashes" + ( toDelete + & Map.toList + & Enc.list + ( \(k, v) -> + Enc.object + [ ("torrentHash", Enc.text k.torrentHash), + ("groupId", Enc.int v.groupId), + ("torrentId", Enc.int v.torrentId) + ] + ) + & jsonAttribute + ) + _ <- + execute + [fmt| + UPDATE redacted.torrents_json + SET transmission_torrent_hash = NULL, + torrent_file = NULL + WHERE transmission_torrent_hash = ANY (?::text[]) + |] + $ Only (toDelete & Map.keys <&> (.torrentHash) & PGArray :: PGArray Text) + pure (label @"knownTorrentsStale" True, actualTorrents) getTransmissionTorrentsTable :: (MonadTransmission m, MonadThrow m, MonadLogger m, MonadOtel m) => m Html @@ -205,9 +229,9 @@ doTransmissionRequest' req = inSpan' "Transmission Request" $ \span -> do transmissionConnectionConfig req case resp.result of - TransmissionResponseFailure err -> appThrowTree span (nestedError "Transmission RPC error" $ singleError $ newError err) + TransmissionResponseFailure err -> appThrow span (AppExceptionTree $ nestedError "Transmission RPC error" $ singleError $ newError err) TransmissionResponseSuccess -> case resp.arguments of - Nothing -> appThrowTree span "Transmission RPC error: No `arguments` field in response" + Nothing -> appThrow span "Transmission RPC error: No `arguments` field in response" Just out -> pure out -- | Contact the transmission RPC, and do the CSRF protection dance. @@ -305,8 +329,8 @@ doTransmissionRequest span dat (req, parser) = do case Json.eitherDecodeStrict' @Json.Value (resp & Http.getResponseBody) of Left _err -> pure () Right val -> logInfo [fmt|failing transmission response: {showPrettyJson val}|] - appThrowTree span err - _ -> liftIO $ unwrapIOError $ Left [fmt|Non-200 response: {showPretty resp}|] + appThrow span (AppExceptionTree err) + _ -> appThrow span $ AppExceptionPretty [[fmt|Non-200 response:|], pretty resp] class MonadTransmission m where getCurrentTransmissionSessionId :: m (Maybe ByteString) diff --git a/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs b/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs index ad363090ffdd..c8850e70a121 100644 --- a/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs +++ b/users/Profpatsch/whatcd-resolver/src/WhatcdResolver.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE QuasiQuotes #-} module WhatcdResolver where @@ -41,7 +42,6 @@ import Network.URI qualified import Network.Wai (ResponseReceived) import Network.Wai qualified as Wai import Network.Wai.Handler.Warp qualified as Warp -import Network.Wai.Parse qualified as Wai import OpenTelemetry.Attributes qualified as Otel import OpenTelemetry.Trace qualified as Otel hiding (getTracer, inSpan, inSpan') import OpenTelemetry.Trace.Monad qualified as Otel @@ -91,14 +91,17 @@ htmlUi = do let catchAppException act = try act >>= \case Right a -> pure a - Left (AppException err) -> do - runInIO (logError err) + Left (AppExceptionTree err) -> do + runInIO (logError (prettyErrorTree err)) + respondOrig (Wai.responseLBS Http.status500 [] "") + Left (AppExceptionPretty err) -> do + runInIO (logError (err & Pretty.prettyErrsNoColor & stringToText)) respondOrig (Wai.responseLBS Http.status500 [] "") catchAppException $ do let mp span parser = Multipart.parseMultipartOrThrow - (appThrowTree span) + (appThrow span . AppExceptionTree) parser req @@ -111,7 +114,7 @@ htmlUi = do let parseQueryArgsNewSpan spanName parser = Parse.runParse "Unable to find the right request query arguments" (lmap Wai.queryString parser) req - & assertMNewSpan spanName id + & assertMNewSpan spanName (first AppExceptionTree) let handlers :: Handlers (AppT IO) handlers respond = @@ -160,7 +163,7 @@ htmlUi = do file <- getTorrentFileById dat <&> annotate [fmt|No torrent file for torrentId "{dat.torrentId}"|] - >>= orAppThrowTree span + >>= orAppThrow span running <- lift @Transaction $ @@ -311,6 +314,12 @@ htmlPageChrome title body = <title>{title}</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> + <!-- + prevent favicon request, based on answers in + https://stackoverflow.com/questions/1321878/how-to-prevent-favicon-ico-requests + TODO: create favicon + --> + <link rel="icon" href="data:,"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script> <script src="https://unpkg.com/htmx.org@1.9.2" integrity="sha384-L6OqL9pRWyyFU3+/bjdSri+iIphTN/bvYyM37tICVyOJkWZLpP2vGn6VUEXgzg6h" crossorigin="anonymous"></script> @@ -551,25 +560,36 @@ getBestTorrentsData :: Transaction m [TorrentData (Label "percentDone" Percentage)] getBestTorrentsData artistFilter = inSpan' "get torrents table data" $ \span -> do artistFilter & doIfJust (\a -> addAttribute span "artist-filter.redacted-id" (a.artistRedactedId & showToText & Otel.toAttribute)) - bestStale :: [TorrentData ()] <- getBestTorrents GetBestTorrentsFilter {onlyArtist = artistFilter, onlyDownloaded = False} - actual <- + let getBest = getBestTorrents GetBestTorrentsFilter {onlyArtist = artistFilter, onlyDownloaded = False} + bestStale :: [TorrentData ()] <- getBest + (statusInfo, transmissionStatus) <- getAndUpdateTransmissionTorrentsStatus ( bestStale & mapMaybe ( \td -> case td.torrentStatus of - InTransmission h -> Just h + InTransmission h -> Just (getLabel @"torrentHash" h, td) _ -> Nothing ) - <&> (\t -> (getLabel @"torrentHash" t, t.transmissionInfo)) & Map.fromList ) + bestBest <- + -- Instead of serving a stale table when a torrent gets deleted, fetch + -- the whole view again. This is a little wasteful, but torrents + -- shouldn’t get deleted very often, so it’s fine. + -- Re-evaluate invariant if this happens too often. + if statusInfo.knownTorrentsStale + then inSpan' "Fetch torrents table data again" $ + \span' -> do + addEventSimple span' "The transmission torrent list was out of date, refetching torrent list." + getBest + else pure bestStale pure $ - bestStale + bestBest -- we have to update the status of every torrent that’s not in tranmission anymore -- TODO I feel like it’s easier (& more correct?) to just do the database request again … <&> ( \td -> case td.torrentStatus of InTransmission info -> - case actual & Map.lookup (getLabel @"torrentHash" info) of + case transmissionStatus & Map.lookup (getLabel @"torrentHash" info) of -- TODO this is also pretty dumb, cause it assumes that we have the torrent file if it was in transmission before, -- which is an internal factum that is established in getBestTorrents (and might change later) Nothing -> td {torrentStatus = NotInTransmissionYet} @@ -621,6 +641,7 @@ mkBestTorrentsTable fresh = do </td> <td>{Html.toHtml @Natural b.torrentGroupJson.groupYear}</td> <td>{Html.toHtml @Int b.seedingWeight}</td> + <td>{Html.toHtml @Text b.torrentFormat}</td> <td><details hx-trigger="toggle once" hx-post="snips/redacted/torrentDataJson" hx-vals={Enc.encToBytesUtf8 $ Enc.object [("torrent-id", Enc.int b.torrentId)]}></details></td> </tr> |] @@ -635,8 +656,8 @@ mkBestTorrentsTable fresh = do <th>Name</th> <th>Year</th> <th>Weight</th> + <th>Format</th> <th>Torrent</th> - <th>Torrent Group</th> </tr> </thead> <tbody> @@ -689,7 +710,7 @@ assertOneUpdated :: m () assertOneUpdated span name x = case x.numberOfRowsAffected of 1 -> pure () - n -> appThrowTree span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) + n -> appThrow span ([fmt|{name :: Text}: Expected to update exactly one row, but updated {n :: Natural} row(s)|]) migrate :: ( MonadPostgres m, @@ -730,7 +751,8 @@ migrate = inSpan "Database Migration" $ do CREATE OR REPLACE FUNCTION calc_seeding_weight(full_json_result jsonb) RETURNS int AS $$ BEGIN RETURN - ((full_json_result->'seeders')::integer*3 + -- three times seeders plus one times snatches + (3 * (full_json_result->'seeders')::integer + (full_json_result->'snatches')::integer ) -- prefer remasters by multiplying them with 3 @@ -738,7 +760,26 @@ migrate = inSpan "Database Migration" $ do WHEN full_json_result->>'remasterTitle' ILIKE '%remaster%' THEN 3 ELSE 1 - END); + END) + -- slightly push mp3 V0, to make sure it’s preferred over 320 CBR + * (CASE + WHEN full_json_result->>'encoding' ILIKE '%v0%' + THEN 2 + ELSE 1 + END) + -- remove 24bit torrents from the result (wayyy too big) + * (CASE + WHEN full_json_result->>'encoding' ILIKE '%24bit%' + THEN 0 + ELSE 1 + END) + -- discount FLACS, so we only use them when there’s no mp3 alternative (to save space) + / (CASE + WHEN full_json_result->>'encoding' ILIKE '%lossless%' + THEN 5 + ELSE 1 + END) + ; END; $$ LANGUAGE plpgsql IMMUTABLE; @@ -764,38 +805,6 @@ migrate = inSpan "Database Migration" $ do |] () -httpTorrent :: - ( MonadIO m, - MonadThrow m - ) => - Otel.Span -> - Http.Request -> - m ByteString -httpTorrent span req = - Http.httpBS req - >>= assertM - span - ( \resp -> do - let statusCode = resp & Http.responseStatus & (.statusCode) - contentType = - resp - & Http.responseHeaders - & List.lookup "content-type" - <&> Wai.parseContentType - <&> (\(ct, _mimeAttributes) -> ct) - if - | statusCode == 200, - Just "application/x-bittorrent" <- contentType -> - Right $ (resp & Http.responseBody) - | statusCode == 200, - Just otherType <- contentType -> - Left [fmt|Redacted returned a non-torrent body, with content-type "{otherType}"|] - | statusCode == 200, - Nothing <- contentType -> - Left [fmt|Redacted returned a body with unspecified content type|] - | code <- statusCode -> Left [fmt|Redacted returned an non-200 error code, code {code}: {resp & showPretty}|] - ) - runAppWith :: AppT IO a -> IO (Either TmpPg.StartError a) runAppWith appT = withTracer $ \tracer -> withDb $ \db -> do tool <- readTools (label @"toolsEnvVar" "WHATCD_RESOLVER_TOOLS") (readTool "pg_format") @@ -828,6 +837,17 @@ runAppWith appT = withTracer $ \tracer -> withDb $ \db -> do logInfo [fmt|Connected to database at {db & TmpPg.toDataDirectory} on socket {db & TmpPg.toConnectionString}|] appT runReaderT newAppT.unAppT Context {..} + `catch` ( \case + AppExceptionPretty p -> throwM $ EscapedException (p & Pretty.prettyErrs) + AppExceptionTree t -> throwM $ EscapedException (t & prettyErrorTree & textToString) + ) + +-- | Just a silly wrapper so that correctly format any 'AppException' that would escape the runAppWith scope. +newtype EscapedException = EscapedException String + deriving anyclass (Exception) + +instance Show EscapedException where + show (EscapedException s) = s withTracer :: (Otel.Tracer -> IO c) -> IO c withTracer f = do diff --git a/users/Profpatsch/xdg-cache-home.nix b/users/Profpatsch/xdg-cache-home.nix new file mode 100644 index 000000000000..6dc02b7f1d66 --- /dev/null +++ b/users/Profpatsch/xdg-cache-home.nix @@ -0,0 +1,14 @@ +{ depot, pkgs, lib, ... }: +depot.nix.writeExecline "xdg-cache-home" { } [ + "if" + "-n" + [ + "printenv" + "XDG_CACHE_HOME" + ] + "importas" + "HOME" + "HOME" + "echo" + "\${HOME}/.cache" +] diff --git a/users/aspen/pkgs/cargo-hakari.nix b/users/aspen/pkgs/cargo-hakari.nix deleted file mode 100644 index b6f4e7e40007..000000000000 --- a/users/aspen/pkgs/cargo-hakari.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ pkgs, ... }: - -with pkgs; - -rustPlatform.buildRustPackage rec { - pname = "cargo-hakari"; - version = "0.9.13"; - - src = fetchFromGitHub { - owner = "facebookincubator"; - repo = "cargo-guppy"; - rev = "cargo-hakari-${version}"; - sha256 = "11ds2zryxdd6rvszkpphb0xnfg7rqisg6kixrwyiydjrm5rdjg9d"; - }; - - cargoSha256 = "0b2hjyak5v4m3g5zjk2q8bdb4iv3015qw1rmhpclv4cv48lcmdbb"; - - buildAndTestSubdir = "tools/cargo-hakari"; - - nativeBuildInputs = [ - pkg-config - ]; - - buildInputs = [ - openssl - ]; -} diff --git a/users/aspen/pkgs/cargo-nextest.nix b/users/aspen/pkgs/cargo-nextest.nix deleted file mode 100644 index dbf3bd7eef19..000000000000 --- a/users/aspen/pkgs/cargo-nextest.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ pkgs, ... }: - -with pkgs; - -rustPlatform.buildRustPackage rec { - pname = "cargo-nextest"; - version = "0.9.36"; - - src = fetchFromGitHub { - owner = "nextest-rs"; - repo = "nextest"; - rev = "cargo-nextest-${version}"; - sha256 = "1g40r38bqmdhc0dy07pj27vkc64d3fw6v5z2vwn82xld2h9dg7w2"; - }; - - cargoSha256 = "1g862azgkn3xk3v3chs8hv1b1prj1pq2vfzbhcx6ir9l00kv6gcv"; - - cargoTestFlags = [ - "--" - "--skip" - "tests_integration::test_relocated_run" - "--skip" - "tests_integration::test_run" - "--skip" - "tests_integration::test_run_after_build" - ]; -} diff --git a/users/aspen/system/home/machines/roswell.nix b/users/aspen/system/home/machines/roswell.nix index 135477b12ddf..600abb052b56 100644 --- a/users/aspen/system/home/machines/roswell.nix +++ b/users/aspen/system/home/machines/roswell.nix @@ -34,7 +34,7 @@ in openssl # Nix things - nixfmt + nixfmt-classic nix-prefetch-github nixpkgs-review cachix diff --git a/users/aspen/system/home/modules/common.nix b/users/aspen/system/home/modules/common.nix index b51ae1c7db7e..5117187d6b98 100644 --- a/users/aspen/system/home/modules/common.nix +++ b/users/aspen/system/home/modules/common.nix @@ -43,7 +43,7 @@ openssl # Nix things - nixfmt + nixfmt-classic nix-prefetch-github nixpkgs-review cachix diff --git a/users/aspen/system/home/modules/development/rust.nix b/users/aspen/system/home/modules/development/rust.nix index c4b20f231546..3c81e2398010 100644 --- a/users/aspen/system/home/modules/development/rust.nix +++ b/users/aspen/system/home/modules/development/rust.nix @@ -10,16 +10,16 @@ with lib; home.packages = with pkgs; [ rustup + + cargo-bloat cargo-edit cargo-expand + cargo-hakari + cargo-nextest cargo-udeps - cargo-bloat sccache evcxr - depot.users.aspen.pkgs.cargo-hakari - depot.users.aspen.pkgs.cargo-nextest - # benchmarking+profiling cargo-criterion cargo-flamegraph diff --git a/users/aspen/system/home/modules/email.nix b/users/aspen/system/home/modules/email.nix index cb92c40cee89..a43e3ab5a68d 100644 --- a/users/aspen/system/home/modules/email.nix +++ b/users/aspen/system/home/modules/email.nix @@ -16,7 +16,7 @@ let personal = { primary = true; address = "root@gws.fyi"; - aliases = [ "aspen@gws.fyi" "aspen@gws.fyi" ]; + aliases = [ "aspen@gws.fyi" ]; passEntry = "root-gws-msmtp"; }; }; diff --git a/users/aspen/system/system/machines/ogopogo.nix b/users/aspen/system/system/machines/ogopogo.nix index e69424118d8c..4b425246034d 100644 --- a/users/aspen/system/system/machines/ogopogo.nix +++ b/users/aspen/system/system/machines/ogopogo.nix @@ -77,12 +77,13 @@ videoDrivers = [ "nvidia" ]; dpi = 100; }; - hardware.opengl.enable = true; + hardware.graphics.enable = true; services.picom = { enable = true; vSync = true; }; hardware.graphics.enable32Bit = true; + hardware.nvidia.open = true; services.postgresql = { enable = true; @@ -90,8 +91,8 @@ authentication = "host all all 0.0.0.0/0 md5"; dataDir = "/data/postgresql"; package = pkgs.postgresql_15; - port = 5431; settings = { + port = 5431; wal_level = "logical"; }; }; diff --git a/users/aspen/system/system/machines/yeren.nix b/users/aspen/system/system/machines/yeren.nix index acab0127376d..4b563df635aa 100644 --- a/users/aspen/system/system/machines/yeren.nix +++ b/users/aspen/system/system/machines/yeren.nix @@ -93,7 +93,7 @@ sof-firmware ]; - hardware.opengl.extraPackages = with pkgs; [ + hardware.graphics.extraPackages = with pkgs; [ vaapiIntel vaapiVdpau libvdpau-va-gl diff --git a/users/aspen/system/system/modules/laptop.nix b/users/aspen/system/system/modules/laptop.nix index b9bf38a4f1fa..57b2bc5a45a9 100644 --- a/users/aspen/system/system/modules/laptop.nix +++ b/users/aspen/system/system/modules/laptop.nix @@ -21,10 +21,5 @@ percentageAction = 3; }; - services.libinput = { - touchpad = { - naturalScrolling = true; - disableWhileTyping = true; - }; - }; + services.libinput.touchpad.naturalScrolling = true; } diff --git a/users/aspen/system/system/modules/sound.nix b/users/aspen/system/system/modules/sound.nix index 2081cbe8476a..c97e19f9b2f8 100644 --- a/users/aspen/system/system/modules/sound.nix +++ b/users/aspen/system/system/modules/sound.nix @@ -3,6 +3,7 @@ { # Enable sound. hardware.pulseaudio.enable = true; + services.pipewire.enable = false; environment.systemPackages = with pkgs; [ pulseaudio-ctl diff --git a/users/azahi/OWNERS b/users/azahi/OWNERS new file mode 100644 index 000000000000..73bc1ebcc3af --- /dev/null +++ b/users/azahi/OWNERS @@ -0,0 +1,3 @@ +set noparent + +azahi diff --git a/users/azahi/pkgs/bruh/default.nix b/users/azahi/pkgs/bruh/default.nix new file mode 100644 index 000000000000..5eecf94b6203 --- /dev/null +++ b/users/azahi/pkgs/bruh/default.nix @@ -0,0 +1,42 @@ +{ pkgs +, lib +, ... +}: + +let + inherit (pkgs) + alsa-utils + fetchFromGitHub + stdenv + ; +in + +stdenv.mkDerivation (finalAttrs: { + pname = "bruh"; + version = "2.1"; + + src = + with finalAttrs; + fetchFromGitHub { + owner = "kejpies"; + repo = pname; + rev = version; + hash = "sha256-Uw6Qes0IZkkfBchFnvnX9l1ZG5T5pyExmV7yUJLPOJ0="; + }; + + postPatch = '' + substituteInPlace bruh.c \ + --replace-fail "aplay" "${alsa-utils}/bin/aplay" + ''; + + makeFlags = [ "PREFIX=$(out)" ]; + + meta = with lib; { + description = "Bruh sound, but as a program"; + inherit (finalAttrs.src.meta) homepage; + license = licenses.gpl3Only; + platforms = platforms.linux; + maintainers = with maintainers; [ azahi ]; + mainProgram = "bruh"; + }; +}) diff --git a/users/emery/OWNERS b/users/emery/OWNERS new file mode 100644 index 000000000000..9e052507d2da --- /dev/null +++ b/users/emery/OWNERS @@ -0,0 +1,3 @@ +set noparent + +emery diff --git a/users/emery/eaglemode/default.nix b/users/emery/eaglemode/default.nix new file mode 100644 index 000000000000..471e8eda67f7 --- /dev/null +++ b/users/emery/eaglemode/default.nix @@ -0,0 +1,13 @@ +# Derivation for my fully configured Eagle Mode. +{ depot, ... }: + +let + config = depot.tools.eaglemode.etcDir { + extraPaths = [ + depot.tools.eaglemode.commands.B + depot.tools.eaglemode.plugins.avif + depot.tools.eaglemode.plugins.qoi + ]; + }; +in +depot.tools.eaglemode.withConfig { inherit config; } diff --git a/users/emery/pkgs/syndicate-server.nix b/users/emery/pkgs/syndicate-server.nix new file mode 100644 index 000000000000..e8bf73836f24 --- /dev/null +++ b/users/emery/pkgs/syndicate-server.nix @@ -0,0 +1,34 @@ +{ pkgs, ... }: + +let + inherit (pkgs) + rustPlatform + rust-bin + fetchFromGitea + pkg-config + openssl + ; +in + +rustPlatform.buildRustPackage rec { + pname = "syndicate-server"; + version = "0.46.0"; + src = fetchFromGitea { + domain = "git.syndicate-lang.org"; + owner = "syndicate-lang"; + repo = "syndicate-rs"; + rev = "${pname}-v${version}"; + sha256 = "sha256-bTteZIlBSoQ1o5shgd9NeKVvEhZTyG3i2zbeVojWiO8="; + }; + cargoHash = "sha256-SIpdFXTk6MC/drjCLaaa49BbGsvCMNbPGCfTxAlCo9c="; + nativeBuildInputs = [ pkg-config ]; + buildInputs = [ openssl ]; + + RUSTC_BOOTSTRAP = 1; + + meta = { + description = "Syndicate broker server"; + homepage = "https://git.syndicate-lang.org/syndicate-lang/syndicate-rs/"; + mainProgram = "syndicate-server"; + }; +} diff --git a/users/emery/workman-cyrillic.xkb b/users/emery/workman-cyrillic.xkb new file mode 100644 index 000000000000..f6783bab7b81 --- /dev/null +++ b/users/emery/workman-cyrillic.xkb @@ -0,0 +1,118 @@ +# Workman with phonetic transliteration layer for Cyrllic. +# Switch layers using Shift+CapsLock. + +partial alphanumeric_keys +xkb_symbols "workman-emery" { + + name[Group1]= "Emery"; + + include "us(euro)" + + // Alphanumeric section + key <AE01> { [ 1, exclam ] }; + key <AE02> { [ 2, at ] }; + key <AE03> { [ 3, numbersign ] }; + key <AE04> { [ 4, dollar ] }; + key <AE05> { [ 5, percent ] }; + key <AE06> { [ 6, asciicircum ] }; + key <AE07> { [ 7, ampersand ] }; + key <AE08> { [ 8, asterisk ] }; + key <AE09> { [ 9, parenleft ] }; + key <AE10> { [ 0, parenright ] }; + + key <AD01> { + [ q, Q, adiaeresis, Adiaeresis ], + [ U044B, U042B, U044c, U042C ] }; # ы Ы ь Ь + key <AD02> { + [ d, D, U0111, U0111 ], # d D đ đ + [ U0434, U0414, U0452, U0402 ] }; # д Д ђ Ђ + key <AD03> { + [ r, R, U20AC, U20AC ], + [ U0440, U0420, U20AC, U20AC ] }; # р Р + key <AD04> { + [ w, W, aring, Aring ], + [ U0447, U0427, U045B, U040B ] }; # ч Ч ћ Ћ + key <AD05> { + [ b, B, b, B ], + [ U0431, U0411 ]}; # б Б + key <AD06> { + [ j, J, U0135, U0134 ], # j J ĵ Ĵ + [ U0458, U0408 ]}; # ј Ј + key <AD07> { + [ f, F, 0x1002200, F ], # f F ∀ F + [ U0444, U0424, U0473, U0472 ]}; # ф Ф ѳ Ѳ + key <AD08> { + [ u, U, U016D, U016C ], + [ U0443, U0423, U045E, U040E ] }; # у У ў Ў + key <AD09> { + [ p, P, sterling, sterling ], + [ U043F, U041F, sterling, sterling ] }; # п П + key <AD10> { + [ semicolon, colon, paragraph, degree ] }; + + key <AC01> { + [ a, A, adiaeresis, Adiaeresis ], + [ U0430, U0410, U2248, U00B6 ] # а А ≈ ¶ + }; + key <AC02> { + [ s, S, U0161, U0160 ], + [ U0441, U0421, U0448, U0428 ] # с С ш Ш + }; + key <AC03> { + [ h, H, U010D, U010C ], + [ U0445, U0425 , U044B, U042B ] }; # х Х + key <AC04> { + [ t, T, thorn, THORN ], + [ U0442, U0422] }; # т Т + key <AC05> { + [ g, G, U011D, U011C ], + [ U0433, U0413 ] }; # г Г + key <AC06> { + [ y, Y, udiaeresis, Udiaeresis ], + [ U044f, U042f, U044D, U042D ] }; # я Я э Э + key <AC07> { + [ n, N, ntilde, Ntilde ], + [ U043D, U041D, U045A, U040A ] }; # н Н њ Њ + key <AC08> { + [ e, E, ediaeresis, Ediaeresis ], + [ U0435, U0415, U0451, U0401 ] }; # е Е ё Ё + key <AC09> { + [ o, O, odiaeresis, Odiaeresis ], + [ U043E, U041E, U044E, U042E ] }; # о О ю Ю + key <AC10> { + [ i, I, idiaeresis, Idiaeresis ], + [ U0438, U0418, U0439, U0419 ] }; # и И й + key <AC11> { + [], + [ U0447, U0427, U045B, U040B ] }; # ч Ч ћ Ћ + + key <AB01> { + [ z, Z, U017E, U017D ], + [ U0437, U0417, U0436, U0416 ] }; # з З ж Ж + key <AB02> { + [ x, X, x, X ], + [ U045F, U040F ] }; # џ Џ + key <AB03> { + [ m, M, mu, mu ], + [ U043C, U041C, mu, mu ] }; # м М + key <AB04> { + [ c, C, U0107, U0106 ], + [ U0446, U0426, U00A9, U2103 ] }; # ц Ц © ℃ + key <AB05> { + [ v, V, v, V ], + [ U0432, U0412 ]}; # в В + key <AB06> { + [ k, K, oe, OE ], + [ U043A, U041A ] }; # к К + key <AB07> { + [ l, L, U01C9, U01C8 ], + [ U043B, U041B, U0459, U0409 ] }; # л Л љ Љ + key <AB08> { [ comma, less, ellipsis, guillemotleft ] }; + key <AB09> { [ period, greater, ellipsis, guillemotright ] }; + // End alphanumeric section + + key <CAPS> { [ BackSpace, ISO_Next_Group ] }; + + key <SPCE> { [ space, minus, space, space ] }; + include "level3(ralt_switch)" +}; diff --git a/users/flokli/nixos/default.nix b/users/flokli/nixos/default.nix index 9ed223a90896..cce4801f45bd 100644 --- a/users/flokli/nixos/default.nix +++ b/users/flokli/nixos/default.nix @@ -23,6 +23,7 @@ depot.nix.readTree.drvTargets rec { deps = (depot.nix.lazy-deps { deploy-archeology-ec2.attr = "users.flokli.nixos.deploy-archeology-ec2"; + aws.attr = "third_party.nixpkgs.awscli"; }); shell = pkgs.mkShell { diff --git a/users/kranzes/wasm-hello-world/Cargo.lock b/users/kranzes/wasm-hello-world/Cargo.lock index d0ad9e38d78c..7a9956d8e2d1 100644 --- a/users/kranzes/wasm-hello-world/Cargo.lock +++ b/users/kranzes/wasm-hello-world/Cargo.lock @@ -63,19 +63,20 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -88,9 +89,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -98,9 +99,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -111,9 +112,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "wasm_hello_world" diff --git a/users/kranzes/wasm-hello-world/Cargo.nix b/users/kranzes/wasm-hello-world/Cargo.nix index 2f629a04d6e7..d590411e11eb 100644 --- a/users/kranzes/wasm-hello-world/Cargo.nix +++ b/users/kranzes/wasm-hello-world/Cargo.nix @@ -102,6 +102,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -232,6 +233,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -239,9 +241,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1a4mcw13nsk3fr8fxjzf9kk1wj88xkfsmnm0pjraw01ryqfm7qjb"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1dfr7pka5kwvky2fx82m9d060p842hc5fyyw8igryikcdb0xybm8"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -251,6 +254,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -258,7 +265,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -270,9 +276,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1nj7wxbi49f0rw9d44rjzms26xlw6r76b2mrggx8jfbdjrxphkb1"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0yypblaf94rdgqs5xw97499xfwgs1096yx026d6h88v563d9dqwx"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -314,10 +321,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.92"; - edition = "2018"; - sha256 = "09npa1srjjabd6nfph5yc03jb26sycjlxhy0c2a1pdrpx4yq5y51"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1kycd1xfx4d9xzqknvzbiqhwb5fzvjqrrn88x692q1vblj8lqp2q"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -339,9 +347,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1dqv2xs8zcyw4kjgzj84bknp2h76phmsb3n7j6hn396h4ssifkz9"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0dp8w6jmw44srym6l752nkr3hkplyw38a2fxz5f3j1ch9p3l1hxg"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -376,10 +385,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.92"; - edition = "2018"; + version = "0.2.93"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "15kyavsrna2cvy30kg03va257fraf9x00ny554vxngvpyaa0q6dg"; + sha256 = "1104bny0hv40jfap3hp8jhs0q4ya244qcrvql39i38xlghq0lan6"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -508,52 +518,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/users/picnoir/tvix-daemon/Cargo.lock b/users/picnoir/tvix-daemon/Cargo.lock index 683203f5ca1e..a7be63acd093 100644 --- a/users/picnoir/tvix-daemon/Cargo.lock +++ b/users/picnoir/tvix-daemon/Cargo.lock @@ -214,9 +214,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "cc" @@ -331,9 +331,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" @@ -659,6 +659,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + +[[package]] name = "litrs" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -693,6 +703,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] +name = "mimalloc" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" +dependencies = [ + "libmimalloc-sys", +] + +[[package]] name = "mime" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -741,11 +760,13 @@ version = "0.1.0" dependencies = [ "bitflags 2.4.2", "bstr", + "bytes", "data-encoding", "ed25519", "ed25519-dalek", "enum-primitive-derive", "glob", + "mimalloc", "nom", "num-traits", "pin-project-lite", @@ -754,6 +775,7 @@ dependencies = [ "sha2", "thiserror", "tokio", + "tracing", ] [[package]] diff --git a/users/picnoir/tvix-daemon/Cargo.nix b/users/picnoir/tvix-daemon/Cargo.nix index 2382027f9b13..b80fa0271b5f 100644 --- a/users/picnoir/tvix-daemon/Cargo.nix +++ b/users/picnoir/tvix-daemon/Cargo.nix @@ -1,4 +1,4 @@ -# This file was @generated by crate2nix 0.13.0 with the command: +# This file was @generated by crate2nix 0.14.1 with the command: # "generate" "--all-features" # See https://github.com/kolloch/crate2nix for more info. @@ -13,6 +13,8 @@ , rootFeatures ? [ "default" ] # If true, throw errors instead of issueing deprecation warnings. , strictDeprecation ? false + # Elements to add to the `-C target-feature=` argument passed to `rustc` + # (separated by `,`, prefixed with `+`). # Used for conditional compilation based on CPU feature detection. , targetFeatures ? [ ] # Whether to perform release builds: longer compile times, faster binaries. @@ -181,6 +183,7 @@ rec { version = "0.2.3"; edition = "2021"; sha256 = "134jhzrz89labrdwxxnjxqjdg06qvaflj1wkfnmyapwyldfwcnn7"; + libName = "anstyle_parse"; dependencies = [ { name = "utf8parse"; @@ -200,6 +203,7 @@ rec { version = "1.0.2"; edition = "2021"; sha256 = "0j3na4b1nma39g4x7cwvj009awxckjf3z2vkwhldgka44hqj72g2"; + libName = "anstyle_query"; dependencies = [ { name = "windows-sys"; @@ -215,6 +219,7 @@ rec { version = "3.0.2"; edition = "2021"; sha256 = "19v0fv400bmp4niqpzxnhg83vz12mmqv7l2l8vi80qcdxj0lpm8w"; + libName = "anstyle_wincon"; dependencies = [ { name = "anstyle"; @@ -234,6 +239,7 @@ rec { version = "0.3.5"; edition = "2018"; sha256 = "0l8sjq1rylkb1ak0pdyjn83b3k6x36j22myngl4sqqgg7whdsmnd"; + libName = "async_stream"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -259,6 +265,7 @@ rec { edition = "2018"; sha256 = "14q179j4y8p2z1d0ic6aqgy9fhwz8p9cai1ia8kpw4bw7q12mrhn"; procMacro = true; + libName = "async_stream_impl"; authors = [ "Carl Lerche <me@carllerche.com>" ]; @@ -285,6 +292,7 @@ rec { edition = "2021"; sha256 = "1adf1jh2yg39rkpmqjqyr9xyd6849p0d95425i6imgbhx0syx069"; procMacro = true; + libName = "async_trait"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -497,6 +505,7 @@ rec { version = "0.4.3"; edition = "2021"; sha256 = "1qx28wg4j6qdcdrisqwyaavlzc0zvbsrcwa99zf9456lfbyn6p51"; + libName = "axum_core"; dependencies = [ { name = "async-trait"; @@ -682,6 +691,7 @@ rec { version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -732,9 +742,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.6.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0lnryqfiymbq5mfflfmbsqvfnw80kkh36nk5kpiscgxb9ac1cad1"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -764,6 +774,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -902,6 +913,7 @@ rec { version = "0.9.6"; edition = "2021"; sha256 = "1y0jnqaq7p2wvspnx7qj76m7hjcqpz73qzvr9l2p9n2s51vr6if2"; + libName = "const_oid"; authors = [ "RustCrypto Developers" ]; @@ -921,7 +933,7 @@ rec { { name = "libc"; packageId = "libc"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-linux-android"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-linux-android"); } { name = "libc"; @@ -946,6 +958,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -971,6 +984,7 @@ rec { version = "4.1.2"; edition = "2021"; sha256 = "0j7kqchcgycs4a11gvlda93h9w2jr05nn4hjpfyh2kn94a4pnrqa"; + libName = "curve25519_dalek"; authors = [ "Isis Lovecruft <isis@patternsinthevoid.net>" "Henry de Valence <hdevalence@hdevalence.ca>" @@ -1043,6 +1057,7 @@ rec { edition = "2021"; sha256 = "1cry71xxrr0mcy5my3fb502cwfxy6822k4pm19cwrilrg7hq4s7l"; procMacro = true; + libName = "curve25519_dalek_derive"; dependencies = [ { name = "proc-macro2"; @@ -1062,9 +1077,10 @@ rec { }; "data-encoding" = rec { crateName = "data-encoding"; - version = "2.5.0"; + version = "2.6.0"; edition = "2018"; - sha256 = "1rcbnwfmfxhlshzbn3r7srm3azqha3mn33yxyqxkzz2wpqcjm5ky"; + sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -1149,6 +1165,7 @@ rec { edition = "2018"; sha256 = "15cvgxqngxslgllz15m8aban6wqfgsi6nlhr0g25yfsnd6nq4lpg"; procMacro = true; + libName = "document_features"; libPath = "lib.rs"; authors = [ "Slint Developers <info@slint-ui.com>" @@ -1200,6 +1217,7 @@ rec { version = "2.1.1"; edition = "2021"; sha256 = "0w88cafwglg9hjizldbmlza0ns3hls81zk1bcih3m5m3h67algaa"; + libName = "ed25519_dalek"; authors = [ "isis lovecruft <isis@patternsinthevoid.net>" "Tony Arcieri <bascule@gmail.com>" @@ -1278,6 +1296,7 @@ rec { edition = "2018"; sha256 = "0k6wcf58h5kh64yq5nfq71va53kaya0kzxwsjwbgwm2n2zd9axxs"; procMacro = true; + libName = "enum_primitive_derive"; authors = [ "Doug Goldstein <cardoe@cardoe.com>" ]; @@ -1310,6 +1329,7 @@ rec { version = "0.2.6"; edition = "2018"; sha256 = "10hkkkjynhibvchznkxx81gwxqarn9i5sgz40d6xxb8xzhsz8xhn"; + libName = "fiat_crypto"; authors = [ "Fiat Crypto library authors <jgross@mit.edu>" ]; @@ -1358,6 +1378,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -1379,6 +1400,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -1392,6 +1414,7 @@ rec { edition = "2018"; sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -1414,6 +1437,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1425,6 +1449,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -1436,6 +1461,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; dependencies = [ { name = "futures-core"; @@ -1690,6 +1716,7 @@ rec { version = "0.3.9"; edition = "2021"; sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -1735,6 +1762,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "0hyn8n3iadrbwq8y0p1rl1275s4nm49bllw5wji29g4aa3dqbb0w"; + libName = "http_body"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1757,6 +1785,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "07agldas2qgcfc05ckiarlmf9vzragbda823nqhrqrc6mjrghx84"; + libName = "http_body_util"; authors = [ "Carl Lerche <me@carllerche.com>" "Lucio Franco <luciofranco14@gmail.com>" @@ -1912,6 +1941,7 @@ rec { version = "0.1.3"; edition = "2021"; sha256 = "1akngan7j0n2n0wd25c6952mvqbkj9gp1lcwzyxjc0d37l8yyf6a"; + libName = "hyper_util"; authors = [ "Sean McArthur <sean@seanmonstar.com>" ]; @@ -2053,6 +2083,33 @@ rec { }; resolvedDefaultFeatures = [ "default" "extra_traits" "std" ]; }; + "libmimalloc-sys" = rec { + crateName = "libmimalloc-sys"; + version = "0.1.39"; + edition = "2018"; + links = "mimalloc"; + sha256 = "0i3b0dzz7cp0ik7ys66q92r16va78gwlbrnxhj5fnkdxsc8niai3"; + libName = "libmimalloc_sys"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + ]; + dependencies = [ + { + name = "libc"; + packageId = "libc"; + } + ]; + buildDependencies = [ + { + name = "cc"; + packageId = "cc"; + } + ]; + features = { + "cty" = [ "dep:cty" ]; + "extended" = [ "cty" ]; + }; + }; "litrs" = rec { crateName = "litrs"; version = "0.4.1"; @@ -2150,6 +2207,34 @@ rec { }; resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; + "mimalloc" = rec { + crateName = "mimalloc"; + version = "0.1.43"; + edition = "2018"; + sha256 = "0csnyrxc16i592gm5ffham07jyj2w98qsh9jyy1rv59lmr8474b8"; + authors = [ + "Octavian Oncescu <octavonce@gmail.com>" + "Vincent Rouillé <vincent@speedy37.fr>" + "Thom Chiovoloni <chiovolonit@gmail.com>" + ]; + dependencies = [ + { + name = "libmimalloc-sys"; + packageId = "libmimalloc-sys"; + usesDefaultFeatures = false; + } + ]; + features = { + "debug" = [ "libmimalloc-sys/debug" ]; + "debug_in_debug" = [ "libmimalloc-sys/debug_in_debug" ]; + "extended" = [ "libmimalloc-sys/extended" ]; + "local_dynamic_tls" = [ "libmimalloc-sys/local_dynamic_tls" ]; + "no_thp" = [ "libmimalloc-sys/no_thp" ]; + "override" = [ "libmimalloc-sys/override" ]; + "secure" = [ "libmimalloc-sys/secure" ]; + }; + resolvedDefaultFeatures = [ "default" ]; + }; "mime" = rec { crateName = "mime"; version = "0.3.17"; @@ -2165,6 +2250,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "16ppc5g84aijpri4jzv14rvcnslvlpphbszc7zzp6vfkddf4qdb8"; + libName = "minimal_lexical"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2286,12 +2372,8 @@ rec { version = "0.1.0"; edition = "2021"; crateBin = [ ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; } - else ../../../tvix/nix-compat; + src = lib.cleanSourceWith { filter = sourceFilter; src = ../../../tvix/nix-compat; }; + libName = "nix_compat"; dependencies = [ { name = "bitflags"; @@ -2303,6 +2385,11 @@ rec { features = [ "alloc" "unicode" "serde" ]; } { + name = "bytes"; + packageId = "bytes"; + optional = true; + } + { name = "data-encoding"; packageId = "data-encoding"; } @@ -2323,6 +2410,10 @@ rec { packageId = "glob"; } { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "nom"; packageId = "nom"; } @@ -2358,20 +2449,30 @@ rec { optional = true; features = [ "io-util" "macros" ]; } + { + name = "tracing"; + packageId = "tracing"; + } ]; devDependencies = [ { + name = "mimalloc"; + packageId = "mimalloc"; + } + { name = "serde_json"; packageId = "serde_json"; } ]; features = { "async" = [ "tokio" ]; + "bytes" = [ "dep:bytes" ]; + "default" = [ "async" "wire" ]; "pin-project-lite" = [ "dep:pin-project-lite" ]; "tokio" = [ "dep:tokio" ]; - "wire" = [ "tokio" "pin-project-lite" ]; + "wire" = [ "tokio" "pin-project-lite" "bytes" ]; }; - resolvedDefaultFeatures = [ "pin-project-lite" "tokio" "wire" ]; + resolvedDefaultFeatures = [ "async" "bytes" "default" "pin-project-lite" "tokio" "wire" ]; }; "nom" = rec { crateName = "nom"; @@ -2404,6 +2505,7 @@ rec { version = "0.46.0"; edition = "2018"; sha256 = "115sywxh53p190lyw97alm14nc004qj5jm5lvdj608z84rbida3p"; + libName = "nu_ansi_term"; authors = [ "ogham@bsago.me" "Ryan Scheel (Havvy) <ryan.havvy@gmail.com>" @@ -2432,6 +2534,7 @@ rec { version = "0.2.18"; edition = "2018"; sha256 = "0yjib8p2p9kzmaz48xwhs69w5dh1wipph9jgnillzd2x33jz03fs"; + libName = "num_traits"; authors = [ "The Rust Project Developers" ]; @@ -2602,6 +2705,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -2616,6 +2720,7 @@ rec { version = "1.1.5"; edition = "2021"; sha256 = "1cxl146x0q7lawp0m1826wsgj8mmmfs6ja8q7m6f7ff5j6vl7gxn"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -2630,6 +2735,7 @@ rec { edition = "2021"; sha256 = "0r9r4ivwiyqf45sv6b30l1dx282lxaax2f6gl84jwa3q590s8f1g"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -2652,6 +2758,7 @@ rec { version = "0.2.13"; edition = "2018"; sha256 = "0n0bwr5qxlf0mhn2xkl36sy55118s9qmvx2yl5f3ixkb007lbywa"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -2659,6 +2766,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -2718,6 +2826,7 @@ rec { version = "1.0.79"; edition = "2021"; sha256 = "0bn004ybzdqid81cqppr5c9jrvqsxv50x60sxc41cwpmk0igydg8"; + libName = "proc_macro2"; authors = [ "David Tolnay <dtolnay@gmail.com>" "Alex Crichton <alex@alexcrichton.com>" @@ -2803,6 +2912,7 @@ rec { version = "0.4.6"; edition = "2021"; sha256 = "1spaq7y4im7s56d1gxa2hi4hzf6dwswb1bv8xyavzya7k25kpf46"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -2843,6 +2953,7 @@ rec { version = "0.1.23"; edition = "2015"; sha256 = "0xnbk2bmyzshacjm2g1kd4zzv2y2az14bw3sjccq5qkpmsfvn9nn"; + libName = "rustc_demangle"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -3119,6 +3230,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "1xipjr4nqsgw34k7a2cgj9zaasl2ds6jwn89886kww93d32a637l"; + libName = "sharded_slab"; authors = [ "Eliza Weisman <eliza@buoyant.io>" ]; @@ -3137,6 +3249,7 @@ rec { version = "1.4.1"; edition = "2015"; sha256 = "18crkkw5k82bvcx088xlf5g4n3772m24qhzgfan80nda7d3rn8nq"; + libName = "signal_hook_registry"; authors = [ "Michal 'vorner' Vaner <vorner@vorner.cz>" "Masaki Hara <ackie.h.gmai@gmail.com>" @@ -3359,6 +3472,7 @@ rec { edition = "2021"; sha256 = "1xylyqcb8rv5yh2yf97hg4n4kg27qccc0ijafr1zqklrhahkn7y6"; procMacro = true; + libName = "thiserror_impl"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3513,6 +3627,7 @@ rec { version = "0.3.2"; edition = "2021"; sha256 = "00vkr1cywd2agn8jbkzwwf7y4ps3cfjm8l9ab697px2cgc97wdln"; + libName = "tokio_listener"; dependencies = [ { name = "axum"; @@ -3598,6 +3713,7 @@ rec { edition = "2021"; sha256 = "0fwjy4vdx1h9pi4g2nml72wi0fr27b5m954p13ji9anyy8l1x2jv"; procMacro = true; + libName = "tokio_macros"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3623,6 +3739,7 @@ rec { version = "0.1.14"; edition = "2021"; sha256 = "0hi8hcwavh5sdi1ivc9qc4yvyr32f153c212dpd7sb366y6rhz1r"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3666,6 +3783,7 @@ rec { version = "0.4.4"; edition = "2021"; sha256 = "1xzri2m3dg8nzdyznm77nymvil9cyh1gfdfrbnska51iqfmvls14"; + libName = "tokio_test"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3706,6 +3824,7 @@ rec { version = "0.7.10"; edition = "2021"; sha256 = "058y6x4mf0fsqji9rfyb77qbfyc50y4pk2spqgj6xsyr693z66al"; + libName = "tokio_util"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3867,6 +3986,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "1l7i17k9vlssrdg4s3b0ia5jjkmmxsvv8s9y9ih0jfi8ssz8s362"; + libName = "tower_layer"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -3877,6 +3997,7 @@ rec { version = "0.3.2"; edition = "2018"; sha256 = "0lmfzmmvid2yp2l36mbavhmqgsvzqf7r2wiwz73ml4xmwaf1rg5n"; + libName = "tower_service"; authors = [ "Tower Maintainers <team@tower-rs.com>" ]; @@ -3935,6 +4056,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -3963,6 +4085,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -3993,6 +4116,7 @@ rec { version = "0.2.0"; edition = "2018"; sha256 = "1hs77z026k730ij1a9dhahzrl0s073gfa2hm5p0fbl0b80gmz1gf"; + libName = "tracing_log"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4024,6 +4148,7 @@ rec { version = "0.3.18"; edition = "2018"; sha256 = "12vs1bwk4kig1l2qqjbbn2nm5amwiqmkcmnznylzmnfvjy6083xd"; + libName = "tracing_subscriber"; authors = [ "Eliza Weisman <eliza@buoyant.io>" "David Barsky <me@davidbarsky.com>" @@ -4110,12 +4235,7 @@ rec { requiredFeatures = [ ]; } ]; - # We can't filter paths with references in Nix 2.4 - # See https://github.com/NixOS/nix/issues/5410 - src = - if ((lib.versionOlder builtins.nixVersion "2.4pre20211007") || (lib.versionOlder "2.5" builtins.nixVersion)) - then lib.cleanSourceWith { filter = sourceFilter; src = ./.; } - else ./.; + src = lib.cleanSourceWith { filter = sourceFilter; src = ./.; }; dependencies = [ { name = "clap"; @@ -4173,6 +4293,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -4242,12 +4363,12 @@ rec { { name = "winapi-i686-pc-windows-gnu"; packageId = "winapi-i686-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "i686-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "i686-pc-windows-gnu"); } { name = "winapi-x86_64-pc-windows-gnu"; packageId = "winapi-x86_64-pc-windows-gnu"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnu"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnu"); } ]; features = { @@ -4260,6 +4381,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -4270,6 +4392,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -4280,6 +4403,7 @@ rec { version = "0.48.0"; edition = "2018"; sha256 = "1aan23v5gs7gya1lc46hqn9mdh8yph3fhxmhxlw36pn6pqc28zb7"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -4573,6 +4697,7 @@ rec { version = "0.52.0"; edition = "2021"; sha256 = "0gd3v4ji88490zgb6b5mq5zgbvwv7zx1ibn8v3x83rwcdbryaar8"; + libName = "windows_sys"; authors = [ "Microsoft" ]; @@ -4820,6 +4945,7 @@ rec { version = "0.48.5"; edition = "2018"; sha256 = "034ljxqshifs1lan89xwpcy1hp0lhdh4b5n0d2z4fwjx2piacbws"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -4827,7 +4953,7 @@ rec { { name = "windows_aarch64_gnullvm"; packageId = "windows_aarch64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; @@ -4852,7 +4978,7 @@ rec { { name = "windows_x86_64_gnullvm"; packageId = "windows_x86_64_gnullvm 0.48.5"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; @@ -4867,6 +4993,7 @@ rec { version = "0.52.4"; edition = "2021"; sha256 = "06sdd7fin3dj9cmlg6n1dw0n1l10jhn9b8ckz1cqf0drb9z7plvx"; + libName = "windows_targets"; authors = [ "Microsoft" ]; @@ -4874,7 +5001,7 @@ rec { { name = "windows_aarch64_gnullvm"; packageId = "windows_aarch64_gnullvm 0.52.4"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "aarch64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "aarch64-pc-windows-gnullvm"); } { name = "windows_aarch64_msvc"; @@ -4899,7 +5026,7 @@ rec { { name = "windows_x86_64_gnullvm"; packageId = "windows_x86_64_gnullvm 0.52.4"; - target = { target, features }: (pkgs.rust.lib.toRustTarget stdenv.hostPlatform == "x86_64-pc-windows-gnullvm"); + target = { target, features }: (stdenv.hostPlatform.rust.rustcTarget == "x86_64-pc-windows-gnullvm"); } { name = "windows_x86_64_msvc"; @@ -5081,14 +5208,11 @@ rec { fuchsia = true; test = false; - /* We are choosing an arbitrary rust version to grab `lib` from, - which is unfortunate, but `lib` has been version-agnostic the - whole time so this is good enough for now. - */ - os = pkgs.rust.lib.toTargetOs platform; - arch = pkgs.rust.lib.toTargetArch platform; - family = pkgs.rust.lib.toTargetFamily platform; - vendor = pkgs.rust.lib.toTargetVendor platform; + inherit (platform.rust.platform) + arch + os + vendor; + family = platform.rust.platform.target-family; env = "gnu"; endian = if platform.parsed.cpu.significantByte.name == "littleEndian" @@ -5178,51 +5302,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot` - # do exist but it's very hard to reason about them, so let's wait until the first bug report. - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { @@ -5331,7 +5445,7 @@ rec { let self = { crates = lib.mapAttrs (packageId: value: buildByPackageIdForPkgsImpl self pkgs packageId) crateConfigs; - target = makeTarget pkgs.stdenv.hostPlatform; + target = makeTarget stdenv.hostPlatform; build = mkBuiltByPackageIdByPkgs pkgs.buildPackages; }; in @@ -5406,8 +5520,6 @@ rec { buildRustCrateForPkgsFunc pkgs ( crateConfig // { - # https://github.com/NixOS/nixpkgs/issues/218712 - dontStrip = stdenv.hostPlatform.isDarwin; src = crateConfig.src or ( pkgs.fetchurl rec { name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz"; diff --git a/users/picnoir/tvix-daemon/default.nix b/users/picnoir/tvix-daemon/default.nix index 78b9aa9a1d1c..d970ac3608f3 100644 --- a/users/picnoir/tvix-daemon/default.nix +++ b/users/picnoir/tvix-daemon/default.nix @@ -36,8 +36,18 @@ in buildPhase = "cargo clippy --tests --all-features --benches --examples | tee $out"; }; + crate2nix-check = + let + crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; + in + crate2nix-check.command.overrideAttrs { + meta.ci.extraSteps = { + inherit crate2nix-check; + }; + }; meta.ci.targets = [ "tvix-daemon" "shell" + "crate2nix-check" ]; } diff --git a/users/sterni/machines/ingeborg/http/code.sterni.lv.nix b/users/sterni/machines/ingeborg/http/code.sterni.lv.nix index 3b080b9dc8b5..24ce218d48d6 100644 --- a/users/sterni/machines/ingeborg/http/code.sterni.lv.nix +++ b/users/sterni/machines/ingeborg/http/code.sterni.lv.nix @@ -170,7 +170,7 @@ in ]; config = { - services.fcgiwrap.cgit = { + services.fcgiwrap.instances.cgit = { process = { user = "http"; group = "http"; @@ -197,7 +197,7 @@ in fastcgi_param QUERY_STRING $args; fastcgi_param HTTP_HOST $server_name; fastcgi_param CGIT_CONFIG ${cgitConfig}; - fastcgi_pass unix:${toString config.services.fcgiwrap.cgit.socket.address}; + fastcgi_pass unix:${toString config.services.fcgiwrap.instances.cgit.socket.address}; } ''; }; diff --git a/users/sterni/modules/backup-minecraft-fabric.nix b/users/sterni/modules/backup-minecraft-fabric.nix index a80a7f51a9ef..5dad2b8825c2 100644 --- a/users/sterni/modules/backup-minecraft-fabric.nix +++ b/users/sterni/modules/backup-minecraft-fabric.nix @@ -10,7 +10,8 @@ let inherit (depot.nix) getBins; bins = getBins pkgs.borgbackup [ "borg" ] - // getBins pkgs.mcrcon [ "mcrcon" ]; + // getBins pkgs.mcrcon [ "mcrcon" ] + // getBins pkgs.systemd [ "systemd-creds" ]; unvaried = ls: builtins.all (l: l == builtins.head ls) ls; @@ -29,7 +30,7 @@ let export MCRCON_HOST="localhost" export MCRCON_PORT="${toString instanceCfg.serverProperties."rcon.port"}" # Unfortunately, mcrcon can't read the password from a file - export MCRCON_PASS="$(cat "''${CREDENTIALS_DIRECTORY}/${instanceName}-rcon-password")" + export MCRCON_PASS="$(${bins.systemd-creds} cat "${instanceName}-rcon-password")" ${bins.mcrcon} save-all unset MCRCON_PASS diff --git a/users/tazjin/cursed/default.nix b/users/tazjin/cursed/default.nix new file mode 100644 index 000000000000..fa1ae9271fee --- /dev/null +++ b/users/tazjin/cursed/default.nix @@ -0,0 +1,9 @@ +{ depot, ... }: + +let + inherit (depot.web) bubblegum; +in +bubblegum.writeCGI +{ + name = "cursed"; +} ./responder.nix diff --git a/users/tazjin/cursed/responder.nix b/users/tazjin/cursed/responder.nix new file mode 100644 index 000000000000..9aa6a2d55807 --- /dev/null +++ b/users/tazjin/cursed/responder.nix @@ -0,0 +1,76 @@ +{ depot, ... }: + +let + inherit (depot.users.sterni.nix.html) + __findFile + esc + withDoctype + ; + + # CGI envvars: https://www.instanet.com/cgi/env.html + method = builtins.getEnv "REQUEST_METHOD"; + path = builtins.getEnv "PATH_INFO"; + + rawQuery = builtins.getEnv "QUERY_STRING"; + query = with builtins; let + pairs = (filter (s: isString s && s != "") (split "&" rawQuery)); + tuples = filter (l: length l > 0) (map (p: filter (s: isString s) (split "=" p)) pairs); + mkAttr = t: { + name = elemAt t 0; + value = elemAt t 1; + }; + in + listToAttrs (map mkAttr tuples); + + default = let { + hasQuery = if builtins.length (builtins.attrNames query) > 0 then "?" else ""; + body = (withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "some cursed nix") + ]) + (<body> { } [ + (<p> { } "hello volgasprint") + (<p> { } [ method " " path hasQuery rawQuery ]) + (<p> { } (builtins.toJSON query)) + ]) + ])); + }; + + greeter = withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "hello there") + ]) + (<body> { } [ + (<p> { } "hello ${query.name or "unknown"}") + ]) + ]); + + weather = let { + town = query.town or "Kazan"; + w = builtins.fetchurl "https://wttr.in/${town}?"; + rendered = with depot.third_party.nixpkgs; runCommand "weather-${town}" { } '' + cat ${w} | ${ansi2html}/bin/ansi2html > $out + ''; + + body = builtins.readFile "${rendered}"; + }; + + routes = { + "/other" = (withDoctype (<html> { lang = "en"; } [ + (<head> { } [ + (<title> { } "other endpoint") + ]) + (<body> { } [ + (<p> { } "this is another route") + ]) + ])); + "/greeter" = greeter; + "/weather" = weather; + }."${path}" or default; + +in +depot.web.bubblegum.respond "OK" +{ + "Content-Type" = "text/html"; +} + routes diff --git a/users/tazjin/dotfiles/.skip-subtree b/users/tazjin/dotfiles/.skip-subtree new file mode 100644 index 000000000000..954981f436ee --- /dev/null +++ b/users/tazjin/dotfiles/.skip-subtree @@ -0,0 +1 @@ +Stuff below here is managed manually, without readTree. diff --git a/users/tazjin/dotfiles/default.nix b/users/tazjin/dotfiles/default.nix index 9b783a9c857c..d536d3a494cd 100644 --- a/users/tazjin/dotfiles/default.nix +++ b/users/tazjin/dotfiles/default.nix @@ -1,3 +1,8 @@ -_: { +args: { dunstrc = ./dunstrc; + niri = ./niri.config.kdl; + waybar = { + config = import ./waybar/config.nix args; + style = ./waybar/style.css; + }; } diff --git a/users/tazjin/dotfiles/niri.config.kdl b/users/tazjin/dotfiles/niri.config.kdl new file mode 100644 index 000000000000..2ccc56413655 --- /dev/null +++ b/users/tazjin/dotfiles/niri.config.kdl @@ -0,0 +1,132 @@ +// https://github.com/YaLTeR/niri/wiki/Configuration:-Overview + +input { + keyboard { + xkb { + layout "us,ru" + variant "hyper" + options "grp:win_space_toggle,compose:ralt,caps:hyper" + } + } + + touchpad { + tap + } +} + +layout { + gaps 14 + center-focused-column "never" + + preset-column-widths { + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + } + + default-column-width {} + + focus-ring { + off + } + + border { + off + } +} + +spawn-at-startup "xwayland-satellite" +spawn-at-startup "xrandr --output eDP-1 --primary" +spawn-at-startup "wpaperd" "-d" +spawn-at-startup "systemctl --user start xss-lock" + +environment { + QT_QPA_PLATFORM "wayland" + DISPLAY ":0" + EDITOR "emacsclient" +} + +hotkey-overlay { + skip-at-startup +} + +screenshot-path "~/screenshots/screenshot-%Y-%m-%d_%H-%M-%S.png" + +animations { + slowdown 0.3 +} + +binds { + Mod+Shift+Slash { show-hotkey-overlay; } + + Mod+T { spawn "emacsclient" "--no-wait" "--create-frame" "--eval" "(vterm)"; } + Mod+Shift+T { spawn "alacritty"; } // fallback terminal + Mod+D { spawn "xfce4-appfinder" "--disable-server"; } + Super+Alt+L { spawn "swaylock" "-fFkl" "-c" "#008080"; } + + // Volume control + XF86AudioRaiseVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn "wpctl" "set-volume" "@DEFAULT_AUDIO_SINK@" "0.1-"; } + XF86AudioMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SINK@" "toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn "wpctl" "set-mute" "@DEFAULT_AUDIO_SOURCE@" "toggle"; } + + // Brightness control + XF86MonBrightnessUp allow-when-locked=true { spawn "light" "-A" "5"; } + Shift+XF86MonBrightnessUp allow-when-locked=true { spawn "light" "-A" "1"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "light" "-U" "5"; } + Shift+XF86MonBrightnessDown allow-when-locked=true { spawn "light" "-U" "1"; } + + Mod+Q { close-window; } + + Mod+Left { focus-column-or-monitor-left; } + Mod+Right { focus-column-or-monitor-right; } + Mod+Down { focus-column-or-monitor-right; } + Mod+Up { focus-column-or-monitor-left; } + Mod+J { focus-column-or-monitor-left; } + Mod+K { focus-column-or-monitor-right; } + Mod+L { focus-window-up; } + Mod+Semicolon { focus-window-down; } + + Mod+Ctrl+Left { move-column-left-or-to-monitor-left; } + Mod+Ctrl+Right { move-column-right-or-to-monitor-right; } + Mod+Ctrl+J { move-column-left-or-to-monitor-left; } + Mod+Ctrl+K { move-column-right-or-to-monitor-right; } + + Mod+Home { focus-column-first; } + Mod+End { focus-column-last; } + + Mod+Ctrl+Home { move-column-to-first; } + Mod+Ctrl+End { move-column-to-last; } + + // Scroll (or move windows) between columns when holding the modifier down. + Mod+WheelScrollDown cooldown-ms=150 { focus-column-or-monitor-right; } + Mod+WheelScrollUp cooldown-ms=150 { focus-column-or-monitor-left; } + Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-right-or-to-monitor-right; } + Mod+Ctrl+WheelScrollUp cooldown-ms=150 { move-column-left-or-to-monitor-left; } + + Mod+Comma { consume-window-into-column; } + Mod+Period { expel-window-from-column; } + + // There are also commands that consume or expel a single window to the side. + // Mod+BracketLeft { consume-or-expel-window-left; } + // Mod+BracketRight { consume-or-expel-window-right; } + + Mod+R { switch-preset-column-width; } + Mod+Shift+R { reset-window-height; } + Mod+F { maximize-column; } + Mod+Shift+F { fullscreen-window; } + Mod+C { center-column; } + + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + // Finer height adjustments when in column with other windows. + Mod+Shift+Minus { set-window-height "-2%"; } + Mod+Shift+Equal { set-window-height "+2%"; } + + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + Alt+Print { screenshot-window; } + + Mod+Shift+E { quit; } +} diff --git a/users/tazjin/dotfiles/waybar/config.nix b/users/tazjin/dotfiles/waybar/config.nix new file mode 100644 index 000000000000..e65edabe7d19 --- /dev/null +++ b/users/tazjin/dotfiles/waybar/config.nix @@ -0,0 +1,51 @@ +{ depot, pkgs, ... }: + +let + launcher = "${pkgs.xfce4-appfinder}/bin/xfce4-appfinder --disable-server"; +in +{ + mainBar = { + layer = "top"; + position = "bottom"; + modules-left = [ "image#start" "custom/start" ]; + + "image#start" = { + path = "${depot.third_party.chicago95}/share/icons/Chicago95/panel/24/start-here.png"; + size = 24; + on-click = "xfce4-appfinder --disable-server"; + }; + + "custom/start" = { + format = " Start"; + on-click = "xfce4-appfinder --disable-server"; + }; + + modules-right = [ "pulseaudio" "backlight" "battery" "tray" "clock" ]; + + pulseaudio = { + on-click = "pavucontrol"; + # Font "Awesome" speaker icons can't be made to render, I don't care why, emoji time. + format = "{volume}% 🎧"; + format-muted = "{volume}% "; + }; + + battery = { + format = "{capacity}% {icon}"; + format-icons = [ "" "" "" "" "" ]; + }; + + backlight = { + format = "{percent}% {icon}"; + format-icons = [ "" ]; + on-scroll-up = "light -A 1"; + on-scroll-down = "light -U 1"; + }; + + clock.format-alt = "{:%a, %d. %b %H:%M}"; + + tray = { + icon-size = 20; + spacing = 10; + }; + }; +} diff --git a/users/tazjin/dotfiles/waybar/style.css b/users/tazjin/dotfiles/waybar/style.css new file mode 100644 index 000000000000..319ef695e23e --- /dev/null +++ b/users/tazjin/dotfiles/waybar/style.css @@ -0,0 +1,162 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: FontAwesome, Unifont; + font-size: 16px; +} + +window#waybar { + background-color: #c0c0c0; + border-top: 3px solid #dfdfdf; + color: #000000; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +window#waybar.termite { + background-color: #3F3F3F; +} + +window#waybar.chromium { + background-color: #000000; + border: none; +} + +button { + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -3px transparent; + /* Avoid rounded borders under each button name */ + border: none; + border-radius: 0; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +button:hover { + background: inherit; + box-shadow: inset 0 -3px #ffffff; +} + +/* you can set a style on hover for any module like this */ +#pulseaudio:hover { + background-color: #a37800; +} + +#mode { + background-color: #64727D; + box-shadow: inset 0 -3px #ffffff; +} + +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#mpd { + padding: 0 5px; + padding-top: 0px; + padding-bottom: 0px; + /* color: #ffffff; */ +} + +#window, +#workspaces { + margin: 0 4px; +} + +#custom-start { + padding-bottom: 1px; + margin-right: 1px; +} + +/* pop out left "modules" (start button) */ +.modules-left { + margin: 3px; + border-right: 1px solid gray; + border-bottom: 1px solid gray; + border-left: 1px solid white; + border-top: 1px solid white; + font-weight: bold; +} + +/* indent right modules like in the original */ +.modules-right { + margin: 3px; + border-top: 1px solid gray; + border-left: 1px solid gray; + border-right: 1px solid white; + border-bottom: 1px solid white; +} + +/* If workspaces is the leftmost module, omit left margin */ +.modules-left > widget:first-child > #workspaces { + margin-left: 0; +} + +/* If workspaces is the rightmost module, omit right margin */ +.modules-right > widget:last-child > #workspaces { + margin-right: 0; +} + +#battery.charging, #battery.plugged { + color: #ffffff; + background-color: #208C71; +} + +@keyframes blink { + to { + background-color: #ffffff; + color: #000000; + } +} + +/* Using steps() instead of linear as a timing function to limit cpu usage */ +#battery.critical:not(.charging) { + background-color: #e35f5f; + color: #ffffff; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: steps(12); + animation-iteration-count: infinite; + animation-direction: alternate; +} + +label:focus { + background-color: #000000; +} + +#pulseaudio.muted { + background-color: #808080; + color: #000000; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + background-color: #e35f5f; +} + +#idle_inhibitor { + background-color: #2d3436; +} + +#idle_inhibitor.activated { + background-color: #ecf0f1; + color: #2d3436; +} diff --git a/users/tazjin/eaglemode/default.nix b/users/tazjin/eaglemode/default.nix new file mode 100644 index 000000000000..9f59695a40b8 --- /dev/null +++ b/users/tazjin/eaglemode/default.nix @@ -0,0 +1,16 @@ +# Derivation for my fully configured Eagle Mode. +{ depot, ... }: + +with depot.tools.eaglemode; + +withConfig { + config = etcDir { + extraPaths = [ + commands.emacsclient + plugins.example + plugins.yatracker + plugins.qoi + plugins.avif + ]; + }; +} diff --git a/users/tazjin/emacs/config/init.el b/users/tazjin/emacs/config/init.el index 2af68a9f746e..a0adcf6cfaec 100644 --- a/users/tazjin/emacs/config/init.el +++ b/users/tazjin/emacs/config/init.el @@ -72,7 +72,8 @@ (use-package rainbow-mode) (use-package s) (use-package string-edit-at-point) -(use-package term-switcher) +(use-package term-switcher + :bind (:map global-map ("<f5>" . #'ts/switch-to-terminal))) (use-package undo-tree :config (global-undo-tree-mode) @@ -166,7 +167,7 @@ (setq common-lisp-hyperspec-root "file:///home/tazjin/docs/lisp/")) (use-package telega - :bind (:map global-map ("s-c" . (lambda (p) (interactive "P") + :bind (:map global-map ("C-x c" . (lambda (p) (interactive "P") (if p (call-interactively #'telega-chat-with) (telega)))) :map telega-chat-button-map ("a" . ignore)) @@ -238,8 +239,7 @@ ;; Load all other Emacs configuration. These configurations are ;; added to `load-path' by Nix. -(mapc 'require '(desktop - mail-setup +(mapc 'require '(mail-setup look-and-feel functions settings diff --git a/users/tazjin/emacs/default.nix b/users/tazjin/emacs/default.nix index 17973b8b4869..80db7610a107 100644 --- a/users/tazjin/emacs/default.nix +++ b/users/tazjin/emacs/default.nix @@ -3,7 +3,7 @@ { depot, lib, pkgs, ... }: pkgs.makeOverridable - ({ emacs ? pkgs.emacs29 }: + ({ emacs ? pkgs.emacs29-pgtk }: let emacsPackages = (pkgs.emacsPackagesFor emacs); emacsWithPackages = emacsPackages.emacsWithPackages; @@ -41,6 +41,7 @@ pkgs.makeOverridable tree-sitter-rust tree-sitter-sql tree-sitter-toml + tree-sitter-typescript tree-sitter-yaml ]); diff --git a/users/tazjin/german-string/.gitignore b/users/tazjin/german-string/.gitignore new file mode 100644 index 000000000000..2f7896d1d136 --- /dev/null +++ b/users/tazjin/german-string/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/users/tazjin/german-string/Cargo.lock b/users/tazjin/german-string/Cargo.lock new file mode 100644 index 000000000000..ffd73ea32472 --- /dev/null +++ b/users/tazjin/german-string/Cargo.lock @@ -0,0 +1,399 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "german-string" +version = "0.1.0" +dependencies = [ + "proptest", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[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.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "syn" +version = "2.0.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/users/tazjin/german-string/Cargo.toml b/users/tazjin/german-string/Cargo.toml new file mode 100644 index 000000000000..8eec963f071a --- /dev/null +++ b/users/tazjin/german-string/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "german-string" +version = "0.1.0" +edition = "2021" + +[dev-dependencies] +proptest = "1.5.0" diff --git a/users/tazjin/german-string/default.nix b/users/tazjin/german-string/default.nix new file mode 100644 index 000000000000..c6cbc8c3c2d0 --- /dev/null +++ b/users/tazjin/german-string/default.nix @@ -0,0 +1,5 @@ +{ depot, pkgs, ... }: + +depot.third_party.naersk.buildPackage { + src = ./.; +} diff --git a/users/tazjin/german-string/src/lib.rs b/users/tazjin/german-string/src/lib.rs new file mode 100644 index 000000000000..328eca309f38 --- /dev/null +++ b/users/tazjin/german-string/src/lib.rs @@ -0,0 +1,435 @@ +use std::alloc::Layout; +use std::cmp::Ordering; +use std::fmt::{Debug, Formatter}; + +#[derive(Clone, Copy)] +#[repr(C)] +struct GSSmall { + len: u32, + data: [u8; 12], +} + +#[derive(Clone, Copy)] +#[repr(transparent)] +struct StorageClassPtr(usize); + +impl StorageClassPtr { + fn transient(ptr: *const u8) -> Self { + debug_assert!( + (ptr as usize & 0b1) == 0, + "pointer must be at least 2-byte aligned" + ); + Self(ptr as usize) + } + + fn persistent(ptr: *const u8) -> Self { + debug_assert!( + (ptr as usize & 0b1) == 0, + "pointer must be at least 2-byte aligned" + ); + Self((ptr as usize) | 0b1) + } + + fn as_ptr(&self) -> *const u8 { + (self.0 & !0b1) as *const u8 + } + + unsafe fn as_mut_ptr(&self) -> *mut u8 { + (self.0 & !0b1) as *mut u8 + } + + fn is_transient(&self) -> bool { + (self.0 & 0b1) == 0 + } +} + +#[derive(Clone, Copy)] +#[repr(C)] +struct GSLarge { + len: u32, + prefix: [u8; 4], + data: StorageClassPtr, +} + +const _ASSERT_VARIANTS_SIZE: () = assert!( + std::mem::size_of::<GSSmall>() == std::mem::size_of::<GSLarge>(), + "German String variants must have the same size" +); + +union GSRepr { + small: GSSmall, + large: GSLarge, +} + +#[repr(transparent)] +pub struct GermanString(GSRepr); + +const _ASSERT_GSTRING_SIZE: () = assert!( + std::mem::size_of::<GermanString>() == 16, + "German String should be 16 bytes in size", +); + +impl GermanString { + /// Creates a new transient German String from the given slice, copying the + /// data in the process. + pub fn transient(bytes: &[u8]) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + s.data[..bytes.len()].copy_from_slice(bytes); + GermanString(GSRepr { small: s }) + } else { + let layout = Layout::array::<u8>(bytes.len()).unwrap(); + let mut large = GSLarge { + len: bytes.len() as u32, + prefix: [0u8; 4], + data: unsafe { + let ptr = std::alloc::alloc(layout); + if ptr.is_null() { + std::alloc::handle_alloc_error(layout); + } + std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len()); + StorageClassPtr::transient(ptr) + }, + }; + + large.prefix.copy_from_slice(&bytes[..4]); + + GermanString(GSRepr { large }) + } + } + + /// Creates a new transient German String from the given owned bytes. Short + /// strings will be copied into the string representation, long strings will + /// be moved out of the given vector without additional allocations. + pub fn transient_from_owned(bytes: Vec<u8>) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let md = std::mem::ManuallyDrop::new(bytes); + let mut large = GSLarge { + len: md.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::transient(md.as_ptr()), + }; + + large.prefix.copy_from_slice(&md[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String from a static data buffer. + pub fn persistent(bytes: &'static [u8]) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let mut large = GSLarge { + len: bytes.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::persistent(bytes.as_ptr()), + }; + + large.prefix.copy_from_slice(&bytes[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String by leaking the provided data. + pub fn persistent_leak(bytes: Vec<u8>) -> GermanString { + if bytes.len() > u32::MAX as usize { + panic!("GermanString maximum length is {} bytes", u32::MAX); + } + + if bytes.len() <= 12 { + let mut s = GSSmall { + len: bytes.len() as u32, + data: [0u8; 12], + }; + + s.data[..bytes.len()].copy_from_slice(&bytes); + GermanString(GSRepr { small: s }) + } else { + let md = std::mem::ManuallyDrop::new(bytes); + let mut large = GSLarge { + len: md.len() as u32, + prefix: [0u8; 4], + data: StorageClassPtr::persistent(md.as_ptr()), + }; + + large.prefix.copy_from_slice(&md[..4]); + GermanString(GSRepr { large }) + } + } + + /// Creates a persistent German String from a static data buffer. + pub fn persistent_from_str(s: &'static str) -> GermanString { + GermanString::persistent(s.as_bytes()) + } + + pub fn len(&self) -> usize { + // SAFETY: The length field is located in the same location for both + // variants, reading it from either is safe. + unsafe { self.0.small.len as usize } + } + + pub fn as_bytes(&self) -> &[u8] { + if self.len() > 12 { + unsafe { std::slice::from_raw_parts(self.0.large.data.as_ptr(), self.len()) } + } else { + unsafe { &self.0.small.data.as_ref()[..self.len()] } + } + } + + pub fn as_str(&self) -> Result<&str, std::str::Utf8Error> { + std::str::from_utf8(self.as_bytes()) + } +} + +impl Drop for GermanString { + fn drop(&mut self) { + unsafe { + if self.len() > 12 && self.0.large.data.is_transient() { + let layout = Layout::array::<u8>(self.len()).unwrap(); + std::alloc::dealloc(self.0.large.data.as_mut_ptr(), layout); + } + } + } +} + +impl PartialEq for GermanString { + fn eq(&self, other: &GermanString) -> bool { + if self.len() != other.len() { + return false; + } + + unsafe { + if self.len() <= 12 { + return self.0.small.data[..self.len()] == other.0.small.data[..other.len()]; + } + return self.0.large.data.as_ptr() == other.0.large.data.as_ptr() + || (self.0.large.prefix == other.0.large.prefix + && self.as_bytes() == other.as_bytes()); + } + } +} + +impl Eq for GermanString {} + +impl Ord for GermanString { + fn cmp(&self, other: &GermanString) -> Ordering { + match (self.len().cmp(&12), other.len().cmp(&12)) { + // two small strings + (Ordering::Less | Ordering::Equal, Ordering::Less | Ordering::Equal) => unsafe { + self.0.small.data[..self.len()].cmp(&other.0.small.data[..other.len()]) + }, + // two large strings + (Ordering::Greater, Ordering::Greater) => unsafe { + match self.0.large.prefix.cmp(&other.0.large.prefix) { + Ordering::Equal => self.as_bytes().cmp(other.as_bytes()), + ordering => ordering, + } + }, + + // LHS large, RHS small + (Ordering::Greater, _) => { + let prefix_ordering = + unsafe { self.0.large.prefix.as_slice().cmp(&other.0.small.data[..4]) }; + + if prefix_ordering != Ordering::Equal { + return prefix_ordering; + } + + self.as_bytes().cmp(other.as_bytes()) + } + + // LHS small, RHS large + (_, Ordering::Greater) => { + let prefix_ordering = + unsafe { self.0.small.data[..4].cmp(other.0.large.prefix.as_slice()) }; + + if prefix_ordering != Ordering::Equal { + return prefix_ordering; + } + + self.as_bytes().cmp(other.as_bytes()) + } + } + } +} + +impl PartialOrd for GermanString { + fn partial_cmp(&self, other: &GermanString) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Debug for GermanString { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + String::from_utf8_lossy(self.as_bytes()).fmt(f) + } +} + +impl Clone for GermanString { + fn clone(&self) -> Self { + unsafe { + if self.len() <= 12 { + return GermanString(GSRepr { + small: self.0.small.clone(), + }); + } + + if self.0.large.data.is_transient() { + return GermanString::transient(self.as_bytes()); + } + + return GermanString(GSRepr { + large: self.0.large.clone(), + }); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use proptest::prelude::*; + + impl Arbitrary for GermanString { + type Parameters = <String as Arbitrary>::Parameters; + type Strategy = BoxedStrategy<Self>; + + fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { + any_with::<String>(args) + .prop_map(|s| GermanString::transient(s.as_bytes())) + .boxed() + } + } + + #[test] + fn test_empty_string() { + let empty = GermanString::transient(b""); + + assert_eq!(empty.len(), 0, "empty string should be empty"); + assert_eq!(empty.as_bytes(), b"", "empty string should contain nothing"); + assert_eq!( + empty.as_str().expect("empty string is valid UTF-8"), + "", + "empty string should contain empty string" + ); + } + + #[test] + fn test_short_string() { + let short = GermanString::transient(b"meow"); + + assert_eq!(short.len(), 4, "'meow' is four characters"); + assert_eq!( + short.as_bytes(), + b"meow", + "short string returns correct bytes" + ); + assert_eq!( + short.as_str().expect("'meow' is valid UTF-8"), + "meow", + "short string returns correct string" + ); + } + + #[test] + fn test_long_string() { + let input: &str = "This code was written at https://signal.live"; + let long = GermanString::transient(input.as_bytes()); + + assert_eq!(long.len(), 44, "long string has correct length"); + assert_eq!( + long.as_bytes(), + input.as_bytes(), + "long string returns correct bytes" + ); + + assert_eq!( + long.as_str().expect("input is valid UTF-8"), + input, + "long string returns correct string" + ); + } + + proptest! { + #[test] + fn test_roundtrip_vec(input: Vec<u8>) { + let gs = GermanString::transient_from_owned(input.clone()); + assert_eq!(input.len(), gs.len(), "length should match"); + + let out = gs.as_bytes().to_owned(); + assert_eq!(input, out, "roundtrip should yield same bytes"); + } + + #[test] + fn test_roundtrip_string(input: String) { + let gs = GermanString::transient_from_owned(input.clone().into_bytes()); + assert_eq!(input.len(), gs.len(), "length should match"); + + let out = String::from_utf8(gs.as_bytes().to_owned()) + .expect("string should be valid after roundtrip"); + + assert_eq!(input, out, "roundtrip should yield same string"); + } + + // Test [`Eq`] implementation. + #[test] + fn test_eq(lhs: Vec<u8>, rhs: Vec<u8>) { + let lhs_gs = GermanString::transient(lhs.as_slice()); + let rhs_gs = GermanString::transient(rhs.as_slice()); + + assert_eq!( + (lhs == rhs), + (lhs_gs == rhs_gs), + "Eq should match between std::String and GermanString ({:?} == {:?})", + lhs, rhs, + ); + } + + #[test] + fn test_reflexivity(x: GermanString) { + prop_assert!(x == x); + } + + #[test] + fn test_symmetry(x: GermanString, y: GermanString) { + prop_assert_eq!(x == y, y == x); + } + + #[test] + fn test_transitivity(x: GermanString, y: GermanString, z: GermanString) { + if x == y && y == z { + assert!(x == z); + } + } + } +} diff --git a/users/tazjin/home/shared.nix b/users/tazjin/home/shared.nix index 38d8add4ac2f..a5aa5296a132 100644 --- a/users/tazjin/home/shared.nix +++ b/users/tazjin/home/shared.nix @@ -5,6 +5,8 @@ let + inherit (depot.third_party) chicago95; + # URL handler to open `tg://` URLs in telega.el telega-launcher = pkgs.writeShellScriptBin "telega-launcher" '' echo "Opening ''${1} in telega.el ..." @@ -38,12 +40,6 @@ in ''; }; - services.screen-locker = { - enable = true; - inactiveInterval = 10; # minutes - lockCmd = "${depot.users.tazjin.screenLock}/bin/tazjin-screen-lock"; - }; - home.packages = [ telega-launcher ]; xdg.desktopEntries.telega-launcher = { @@ -65,13 +61,35 @@ in }; }; - services.picom = { + programs.wpaperd = { + enable = true; + settings = { + default = { + duration = "1d"; + mode = "center"; + sorting = "random"; + }; + + any.path = ../wallpapers; + }; + }; + + programs.waybar = { enable = true; - vSync = true; - backend = "glx"; + settings = depot.users.tazjin.dotfiles.waybar.config; + style = depot.users.tazjin.dotfiles.waybar.style; + systemd.enable = true; }; + systemd.user.services.waybar.Unit.After = lib.mkForce [ "niri.service" ]; - services.syncthing.enable = true; + + services.swayidle = let cmd = "${pkgs.swaylock}/bin/swaylock -fFkl -c 008080"; in { + enable = true; + events = [ + { event = "before-sleep"; command = cmd; } + { event = "lock"; command = cmd; } + ]; + }; # Enable the dunst notification daemon, but force the # configuration file separately instead of going via the strange @@ -84,6 +102,18 @@ in ''; }; + gtk = { + enable = true; + theme.name = "Chicago95"; + theme.package = chicago95; + + iconTheme.name = "Chicago95-tux"; + iconTheme.package = chicago95; + + cursorTheme.name = lib.mkDefault "Chicago95_Animated_Hourglass_Cursors"; + cursorTheme.package = chicago95; + }; + systemd.user.startServices = true; # Previous default version, see https://github.com/nix-community/home-manager/blob/master/docs/release-notes/rl-2211.adoc diff --git a/users/tazjin/home/zamalek.nix b/users/tazjin/home/zamalek.nix index d24de945bb28..98da5e6b233e 100644 --- a/users/tazjin/home/zamalek.nix +++ b/users/tazjin/home/zamalek.nix @@ -8,4 +8,6 @@ depot.users.tazjin.home.shared depot.users.tazjin.home.persistence ]; + + gtk.cursorTheme.name = lib.mkForce "Chicago95_Animated_Hourglass_Cursors_HiDPI"; } diff --git a/users/tazjin/niri-reap/.gitignore b/users/tazjin/niri-reap/.gitignore new file mode 100644 index 000000000000..2f7896d1d136 --- /dev/null +++ b/users/tazjin/niri-reap/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/users/tazjin/niri-reap/Cargo.lock b/users/tazjin/niri-reap/Cargo.lock new file mode 100644 index 000000000000..d2f5c53075f2 --- /dev/null +++ b/users/tazjin/niri-reap/Cargo.lock @@ -0,0 +1,104 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "niri-ipc" +version = "0.1.8" +source = "git+https://github.com/YaLTeR/niri.git#370fd4e172ec3daf9dc9c75dc0555fe91182f731" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "niri-reap" +version = "0.1.0" +dependencies = [ + "niri-ipc", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/users/tazjin/niri-reap/Cargo.toml b/users/tazjin/niri-reap/Cargo.toml new file mode 100644 index 000000000000..20512685b48d --- /dev/null +++ b/users/tazjin/niri-reap/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "niri-reap" +version = "0.1.0" +edition = "2021" + +[dependencies] +niri-ipc = { git = "https://github.com/YaLTeR/niri.git", version = "0.1.8" } diff --git a/users/tazjin/niri-reap/default.nix b/users/tazjin/niri-reap/default.nix new file mode 100644 index 000000000000..b2a0594b7748 --- /dev/null +++ b/users/tazjin/niri-reap/default.nix @@ -0,0 +1,13 @@ +{ depot, pkgs, ... }: + +pkgs.rustPlatform.buildRustPackage { + name = "niri-reap"; + src = depot.third_party.gitignoreSource ./.; + + cargoLock = { + lockFile = ./Cargo.lock; + outputHashes = { + "niri-ipc-0.1.8" = "sha256:0wyl0mpk9hg67bvj7q120wanrdqn3ls9zv9vjv9yxp11kan5pi1q"; + }; + }; +} diff --git a/users/tazjin/niri-reap/src/main.rs b/users/tazjin/niri-reap/src/main.rs new file mode 100644 index 000000000000..d89b18fc57cf --- /dev/null +++ b/users/tazjin/niri-reap/src/main.rs @@ -0,0 +1,76 @@ +use niri_ipc::socket::Socket; +use niri_ipc::{Action, Reply, Request, Response, Window, Workspace}; + +fn sock() -> Socket { + Socket::connect().expect("could not connect to Niri socket") +} + +fn list_workspaces() -> Vec<Workspace> { + let (reply, _) = sock() + .send(Request::Workspaces) + .expect("failed to send workspace request"); + + match reply { + Reply::Err(err) => panic!("failed to list workspaces: {}", err), + Reply::Ok(Response::Workspaces(w)) => w, + Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other), + } +} + +fn list_windows() -> Vec<Window> { + let (reply, _) = sock() + .send(Request::Windows) + .expect("failed to send window request"); + + match reply { + Reply::Err(err) => panic!("failed to list windows: {}", err), + Reply::Ok(Response::Windows(w)) => w, + Reply::Ok(other) => panic!("unexpected reply from Niri: {:#?}", other), + } +} + +fn reap_window(window: u64, workspace: u64) { + let (reply, _) = sock() + .send(Request::Action(Action::MoveWindowToWorkspace { + window_id: Some(window), + reference: niri_ipc::WorkspaceReferenceArg::Id(workspace), + })) + .expect("failed to send window move request"); + + reply.expect("failed to move window to workspace"); +} + +fn main() { + let workspaces = list_workspaces(); + + let active_workspace = workspaces + .iter() + .filter(|w| w.is_focused) + .next() + .expect("expected an active workspace"); + + let orphan_workspaces = workspaces + .iter() + .filter(|w| w.output == active_workspace.output) + // Only select workspaces that are further down, to avoid issues with + // indices changing during the operation. + .filter(|w| w.idx > active_workspace.idx) + .map(|w| w.id) + .collect::<Vec<_>>(); + + if orphan_workspaces.is_empty() { + return; + } + + let reapable = list_windows() + .into_iter() + .filter(|w| match w.workspace_id { + Some(id) => orphan_workspaces.contains(&id), + None => true, + }) + .collect::<Vec<_>>(); + + for window in reapable.iter().rev() { + reap_window(window.id, active_workspace.id); + } +} diff --git a/users/tazjin/nixos/arbat/default.nix b/users/tazjin/nixos/arbat/default.nix index 73bed4573ac1..c87aa445c29c 100644 --- a/users/tazjin/nixos/arbat/default.nix +++ b/users/tazjin/nixos/arbat/default.nix @@ -55,7 +55,7 @@ in hardware = { enableRedistributableFirmware = true; - opengl.enable = true; + graphics.enable = true; bluetooth.enable = true; }; @@ -66,8 +66,6 @@ in mouse.naturalScrolling = false; mouse.disableWhileTyping = true; }; - # services.xserver.libinput.touchpad.clickMethod = "clickfinger"; - # services.xserver.libinput.touchpad.tapping = false; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; system.stateVersion = "24.11"; diff --git a/users/tazjin/nixos/default.nix b/users/tazjin/nixos/default.nix index 29b6a0e83b10..6bca09d8f129 100644 --- a/users/tazjin/nixos/default.nix +++ b/users/tazjin/nixos/default.nix @@ -4,10 +4,12 @@ let systemFor = sys: (depot.ops.nixos.nixosFor sys).system; in depot.nix.readTree.drvTargets { arbatSystem = systemFor depot.users.tazjin.nixos.arbat; camdenSystem = systemFor depot.users.tazjin.nixos.camden; - frogSystem = systemFor depot.users.tazjin.nixos.frog; tverskoySystem = systemFor depot.users.tazjin.nixos.tverskoy; zamalekSystem = systemFor depot.users.tazjin.nixos.zamalek; koptevoRaw = depot.ops.nixos.nixosFor depot.users.tazjin.nixos.koptevo; koptevoSystem = systemFor depot.users.tazjin.nixos.koptevo; khamovnikSystem = systemFor depot.users.tazjin.nixos.khamovnik; + + # no need to build this while the machine is in storage + # frogSystem = systemFor depot.users.tazjin.nixos.frog; } diff --git a/users/tazjin/nixos/frog/default.nix b/users/tazjin/nixos/frog/default.nix index 349c5eb6d81a..ce82d749f408 100644 --- a/users/tazjin/nixos/frog/default.nix +++ b/users/tazjin/nixos/frog/default.nix @@ -41,9 +41,9 @@ lib.fix (self: { hardware = { cpu.amd.updateMicrocode = true; enableRedistributableFirmware = true; - opengl = { + graphics = { enable = true; - driSupport32Bit = true; + enable32Bit = true; }; pulseaudio = { diff --git a/users/tazjin/nixos/khamovnik/default.nix b/users/tazjin/nixos/khamovnik/default.nix index 19d7f5822b4a..dcb19be2ae9f 100644 --- a/users/tazjin/nixos/khamovnik/default.nix +++ b/users/tazjin/nixos/khamovnik/default.nix @@ -43,6 +43,8 @@ in "rtsx_pci_sdmmc" ]; kernelModules = [ "kvm-intel" ]; + + tmp.cleanOnBoot = true; }; fileSystems = { @@ -64,12 +66,13 @@ in tvl.cache.enable = true; networking.hostName = "khamovnik"; + networking.networkmanager.enable = true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; hardware.cpu.intel.updateMicrocode = true; hardware.enableRedistributableFirmware = true; - hardware.opengl.extraPackages = with pkgs; [ + hardware.graphics.extraPackages = with pkgs; [ intel-compute-runtime intel-media-driver intel-vaapi-driver @@ -116,6 +119,13 @@ in # Try to work around Intel CPU throttling bugs services.throttled.enable = true; + # Try to get suspend to work more reliably + services.logind = { + lidSwitch = "suspend"; + lidSwitchDocked = "suspend"; + lidSwitchExternalPower = "suspend"; + }; + virtualisation.docker.enable = true; hardware.bluetooth.enable = true; @@ -128,5 +138,7 @@ in protobuf ]; + programs.adb.enable = true; + system.stateVersion = "23.05"; # Did you read the comment? } diff --git a/users/tazjin/nixos/koptevo/default.nix b/users/tazjin/nixos/koptevo/default.nix index ea8dfd4bd809..d1fe793915a7 100644 --- a/users/tazjin/nixos/koptevo/default.nix +++ b/users/tazjin/nixos/koptevo/default.nix @@ -11,12 +11,12 @@ in imports = [ (mod "quassel.nix") (mod "www/base.nix") - (mod "www/tazj.in.nix") (usermod "airsonic.nix") (usermod "geesefs.nix") + (usermod "homepage.nix") + (usermod "miniflux.nix") (usermod "predlozhnik.nix") (usermod "tgsa.nix") - (usermod "miniflux.nix") (depot.third_party.agenix.src + "/modules/age.nix") ]; @@ -62,7 +62,7 @@ in domain = "tazj.in"; useDHCP = true; firewall.enable = true; - firewall.allowedTCPPorts = [ 22 80 443 ]; + firewall.allowedTCPPorts = [ 22 80 443 8776 9443 ]; wireless.enable = true; wireless.networks."How do I computer fast?" = { @@ -72,8 +72,22 @@ in time.timeZone = "UTC"; - security.acme.acceptTerms = true; - security.acme.defaults.email = lib.mkForce "acme@tazj.in"; + security.acme = { + acceptTerms = true; + defaults.email = lib.mkForce "acme@tazj.in"; + + # wildcard cert for usage with Yggdrasil services + certs."y.tazj.in" = { + dnsProvider = "yandexcloud"; + credentialFiles.YANDEX_CLOUD_IAM_TOKEN_FILE = "/run/agenix/lego-yandex"; + extraDomainNames = [ "*.y.tazj.in" ]; + + # folder tvl/tazjin-private/default + environmentFile = builtins.toFile "lego-yandex-env" '' + YANDEX_CLOUD_FOLDER_ID=b1gq41rsbggeum4qafnh + ''; + }; + }; programs.fish.enable = true; @@ -84,11 +98,14 @@ in openssh.authorizedKeys.keys = depot.users.tazjin.keys.all; }; + users.users.nginx.extraGroups = [ "acme" ]; + age.secrets = let secretFile = name: depot.users.tazjin.secrets."${name}.age"; in { + lego-yandex.file = secretFile "lego-yandex"; tgsa-yandex.file = secretFile "tgsa-yandex"; }; @@ -169,16 +186,116 @@ in # List packages installed in system profile. To search, run: # $ nix search wget environment.systemPackages = with pkgs; [ + bat curl + emacs-nox htop jq - nmap - bat - emacs-nox nano + nmap + radicle-node wget ]; + # configure Yggdrasil network + services.yggdrasil = { + enable = true; + persistentKeys = true; + openMulticastPort = true; + + settings = { + Listen = [ "tls://[::]:9443" ]; # yggd + IfName = "ygg0"; + Peers = [ + "quic://ygg-msk-1.averyan.ru:8364" + "tls://ekb.itrus.su:7992" + "tls://s-mow-1.sergeysedoy97.ru:65534" + ]; + + MulticastInterfaces = [{ + Regex = "enp.*"; + Beacon = true; + Listen = true; + Port = 0; + }]; + + AllowedPublicKeys = [ + "573fd89392e2741ead4edd85034c91c88f1e560d991bbdbf1fccb6233db4d325" # khamovnik + ]; + }; + }; + + # TODO(tazjin): move this to a module for radicle stuff + services.radicle = { + enable = true; + publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILHs6jSvMdtu9oJCt48etEs8ExjfGY5PmWQsRzFleogS"; + privateKeyFile = "/etc/secrets/radicle"; # TODO: to manage, or not to manage ... + + settings = { + web.pinned.repositories = [ + "rad:z3r5zMi9U3az3i4cPKxMcA3K7xx9L" # depot + "rad:z2mdnBK1tX6pibdBfRct3ThCgheHu" # tvix-go + ]; + + node = { + alias = "rad.tazj.in"; + seedingPolicy.default = "block"; + }; + }; + + node = { + openFirewall = true; + listenAddress = "[::]"; + }; + + httpd = { + enable = true; + listenAddress = "127.0.0.1"; + listenPort = 7235; # radl + }; + }; + + services.nginx.virtualHosts."rad.tazj.in" = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://127.0.0.1:7235"; + }; + + services.nginx.virtualHosts."rad.y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + locations = config.services.nginx.virtualHosts."rad.tazj.in".locations; + }; + + services.nginx.virtualHosts."src.tazj.in" = { + enableACME = true; + forceSSL = true; + root = depot.third_party.radicle-explorer.withPreferredSeeds [{ + hostname = "rad.tazj.in"; + port = 443; + scheme = "https"; + }]; + + locations."/" = { + index = "index.html"; + extraConfig = '' + try_files $uri $uri/ /index.html; + ''; + }; + }; + + services.nginx.virtualHosts."src.y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + root = depot.third_party.radicle-explorer.withPreferredSeeds [{ + hostname = "rad.y.tazj.in"; + port = 443; + scheme = "https"; + }]; + + locations = config.services.nginx.virtualHosts."src.tazj.in".locations; + }; + programs.mtr.enable = true; programs.mosh.enable = true; zramSwap.enable = true; diff --git a/users/tazjin/nixos/modules/desktop.nix b/users/tazjin/nixos/modules/desktop.nix index 296960a44345..dfbc12dfd8e9 100644 --- a/users/tazjin/nixos/modules/desktop.nix +++ b/users/tazjin/nixos/modules/desktop.nix @@ -10,43 +10,62 @@ pulse.enable = true; }; - redshift.enable = true; blueman.enable = true; libinput.enable = true; xserver = { - enable = true; - xkb.layout = "us"; - xkb.options = "caps:super"; - - displayManager = { - # Give EXWM permission to control the session. - sessionCommands = "${pkgs.xorg.xhost}/bin/xhost +SI:localuser:$USER"; - lightdm.enable = true; - # lightdm.greeters.gtk.clock-format = "%H:%M"; # TODO(tazjin): TZ? - }; - - windowManager.session = lib.singleton { - name = "exwm"; - start = "${config.tazjin.emacs}/bin/tazjins-emacs --internal-border=0 --border-width=0"; + enable = true; # wayland doesn't work otherwise ...?! + displayManager.gdm = { + enable = true; + wayland = true; }; - desktopManager.xfce.enable = true; }; }; - # Set variables to enable EXWM-XIM and other Emacs features. - environment.sessionVariables = { - XMODIFIERS = "@im=exwm-xim"; - GTK_IM_MODULE = "xim"; - QT_IM_MODULE = "xim"; - CLUTTER_IM_MODULE = "xim"; - EDITOR = "emacsclient"; - _JAVA_AWT_WM_NONREPARENTING = "1"; - }; + services.displayManager.sessionPackages = [ pkgs.niri ]; + + programs.xwayland.enable = true; + + environment.systemPackages = with pkgs; [ + # core packages + niri + xwayland-satellite + swaylock + + # support tooling + alacritty + qt5.qtwayland + swayidle + waybar + wdisplays + wl-mirror + xfce.xfce4-appfinder + ]; # Do not restart the display manager automatically systemd.services.display-manager.restartIfChanged = lib.mkForce false; + # pipewire MUST start before niri, otherwise screen sharing doesn't work + systemd.user.services.pipewire.wantedBy = [ "niri.service" ]; + systemd.user.services.pipewire.before = [ "niri.service" ]; + + # enable "desktop portals", which are important somehow + xdg.portal = { + enable = true; + extraPortals = with pkgs; [ + xdg-desktop-portal-gtk + xdg-desktop-portal-gnome + ]; + config.common.default = "*"; + }; + + # swaylock needs an empty PAM configuration, otherwise it locks the user out + security.pam.services.swaylock = { }; + + # enable theming support for Qt that is compatible with Chicago95 theme + qt.enable = true; + qt.platformTheme = "qt5ct"; + # If something needs more than 10s to stop it should probably be # killed. systemd.extraConfig = '' diff --git a/users/tazjin/nixos/modules/fonts.nix b/users/tazjin/nixos/modules/fonts.nix index ee1b84e581f1..36b4cbe969ce 100644 --- a/users/tazjin/nixos/modules/fonts.nix +++ b/users/tazjin/nixos/modules/fonts.nix @@ -1,15 +1,17 @@ # Attempt at configuring reasonable font-rendering. -{ pkgs, ... }: +{ depot, pkgs, ... }: { fonts = { packages = with pkgs; [ corefonts dejavu_fonts + font-awesome jetbrains-mono noto-fonts-cjk - noto-fonts-emoji + noto-fonts-color-emoji + noto-fonts-monochrome-emoji ]; fontconfig = { diff --git a/users/tazjin/nixos/modules/home-config.nix b/users/tazjin/nixos/modules/home-config.nix index 77fe3f69bcd2..9aa1cab46d66 100644 --- a/users/tazjin/nixos/modules/home-config.nix +++ b/users/tazjin/nixos/modules/home-config.nix @@ -6,7 +6,7 @@ users.users.tazjin = { isNormalUser = true; createHome = true; - extraGroups = [ "wheel" "networkmanager" "video" "adbusers" ]; + extraGroups = [ "wheel" "networkmanager" "video" "adbusers" "yggdrasil" ]; uid = 1000; shell = pkgs.fish; initialHashedPassword = "$2b$05$1eBPdoIgan/C/L8JFqIHBuVscQyTKw1L/4VBlzlLvLBEf6CXS3EW6"; diff --git a/users/tazjin/nixos/modules/homepage.nix b/users/tazjin/nixos/modules/homepage.nix new file mode 100644 index 000000000000..65191d6e7087 --- /dev/null +++ b/users/tazjin/nixos/modules/homepage.nix @@ -0,0 +1,59 @@ +# serve tazjin's website & blog +{ depot, config, lib, pkgs, ... }: + +let + extraConfig = '' + location = /en/rss.xml { + return 301 https://tazj.in/feed.atom; + } + + ${depot.users.tazjin.blog.oldRedirects} + location /blog/ { + alias ${depot.users.tazjin.blog.rendered}/; + + if ($request_uri ~ ^/(.*)\.html$) { + return 302 /$1; + } + + try_files $uri $uri.html $uri/ =404; + } + + location = /predlozhnik { + return 302 https://predlozhnik.ru; + } + + # redirect for easier entry on a TV + location = /tv { + return 302 https://tazj.in/blobs/play.html; + } + + # Temporary place for serving static files. + location /blobs/ { + alias /var/lib/tazjins-blobs/; + } + ''; +in +{ + config = { + services.nginx.virtualHosts."tazj.in" = { + enableACME = true; + forceSSL = true; + root = depot.users.tazjin.homepage; + serverAliases = [ "www.tazj.in" ]; + inherit extraConfig; + }; + + services.nginx.virtualHosts."y.tazj.in" = { + enableSSL = true; + useACMEHost = "y.tazj.in"; + root = depot.users.tazjin.homepage; + inherit extraConfig; + }; + + services.nginx.virtualHosts."git.tazj.in" = { + enableACME = true; + forceSSL = true; + extraConfig = "return 301 https://code.tvl.fyi$request_uri;"; + }; + }; +} diff --git a/users/tazjin/nixos/modules/physical.nix b/users/tazjin/nixos/modules/physical.nix index 5ec527fa7cf7..92b22112d4f4 100644 --- a/users/tazjin/nixos/modules/physical.nix +++ b/users/tazjin/nixos/modules/physical.nix @@ -20,11 +20,12 @@ in environment.systemPackages = # programs from the depot (with depot; [ - users.tazjin.screenLock - users.tazjin.chase-geese config.tazjin.emacs third_party.agenix.cli tools.when + users.tazjin.chase-geese + users.tazjin.eaglemode + users.tazjin.screenLock ]) ++ # programs from nixpkgs @@ -74,6 +75,7 @@ in pulseaudio # for pactl pwgen quasselClient + radicle-node rink ripgrep rustup @@ -100,6 +102,13 @@ in # run manually patchelfed binaries environment.stub-ld.enable = false; + # Enable yggdrasil network. + services.yggdrasil = { + enable = true; + persistentKeys = true; + settings.IfName = "ygg0"; + }; + programs = { fish.enable = true; mosh.enable = true; diff --git a/users/tazjin/nixos/tverskoy/default.nix b/users/tazjin/nixos/tverskoy/default.nix index 733929219a3a..c074fd9c5d70 100644 --- a/users/tazjin/nixos/tverskoy/default.nix +++ b/users/tazjin/nixos/tverskoy/default.nix @@ -93,9 +93,9 @@ lib.fix (self: { enableRedistributableFirmware = true; bluetooth.enable = true; - opengl = { + graphics = { enable = true; - driSupport32Bit = true; + enable32Bit = true; extraPackages = with pkgs; [ vaapiVdpau diff --git a/users/tazjin/nixos/zamalek/default.nix b/users/tazjin/nixos/zamalek/default.nix index 29effaa9bdd7..ebaf2d2cfa6d 100644 --- a/users/tazjin/nixos/zamalek/default.nix +++ b/users/tazjin/nixos/zamalek/default.nix @@ -71,11 +71,11 @@ in cpu.intel.updateMicrocode = true; bluetooth.enable = true; enableRedistributableFirmware = true; - opengl.enable = true; + graphics.enable = true; }; - services.xserver.libinput.touchpad.clickMethod = "clickfinger"; - services.xserver.libinput.touchpad.tapping = false; + services.libinput.touchpad.clickMethod = "clickfinger"; + services.libinput.touchpad.tapping = false; services.avahi.enable = true; services.tailscale.enable = true; diff --git a/users/tazjin/secrets/lego-yandex.age b/users/tazjin/secrets/lego-yandex.age new file mode 100644 index 000000000000..10524a9577c2 --- /dev/null +++ b/users/tazjin/secrets/lego-yandex.age Binary files differdiff --git a/users/tazjin/secrets/secrets.nix b/users/tazjin/secrets/secrets.nix index 12f12f721c6c..a29bd30b7766 100644 --- a/users/tazjin/secrets/secrets.nix +++ b/users/tazjin/secrets/secrets.nix @@ -13,4 +13,5 @@ in "geesefs-tazjins-files.age".publicKeys = allKeys; "miniflux.age".publicKeys = allKeys; "tgsa-yandex.age".publicKeys = allKeys; + "lego-yandex.age".publicKeys = allKeys; } diff --git a/users/tazjin/wallpapers/alphasoft.webp b/users/tazjin/wallpapers/alphasoft.webp new file mode 100644 index 000000000000..10c404eff0ab --- /dev/null +++ b/users/tazjin/wallpapers/alphasoft.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_02_big.webp b/users/tazjin/wallpapers/svema_02_big.webp new file mode 100644 index 000000000000..5b7f18715c9d --- /dev/null +++ b/users/tazjin/wallpapers/svema_02_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_07_big.webp b/users/tazjin/wallpapers/svema_07_big.webp new file mode 100644 index 000000000000..0706543473e5 --- /dev/null +++ b/users/tazjin/wallpapers/svema_07_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_09_big.webp b/users/tazjin/wallpapers/svema_09_big.webp new file mode 100644 index 000000000000..4983efef29b8 --- /dev/null +++ b/users/tazjin/wallpapers/svema_09_big.webp Binary files differdiff --git a/users/tazjin/wallpapers/svema_14_big.webp b/users/tazjin/wallpapers/svema_14_big.webp new file mode 100644 index 000000000000..c74542807c29 --- /dev/null +++ b/users/tazjin/wallpapers/svema_14_big.webp Binary files differdiff --git a/users/wpcarro/nixos/ava/default.nix b/users/wpcarro/nixos/ava/default.nix index d2f743503da4..457947607e7e 100644 --- a/users/wpcarro/nixos/ava/default.nix +++ b/users/wpcarro/nixos/ava/default.nix @@ -76,9 +76,6 @@ in }; }; - # Enable sound. - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ iphone diff --git a/users/wpcarro/nixos/kyoko/default.nix b/users/wpcarro/nixos/kyoko/default.nix index 323f57eeb210..024276afddaf 100644 --- a/users/wpcarro/nixos/kyoko/default.nix +++ b/users/wpcarro/nixos/kyoko/default.nix @@ -79,9 +79,6 @@ in }; }; - # Enable sound. - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ iphone diff --git a/users/wpcarro/nixos/marcus/default.nix b/users/wpcarro/nixos/marcus/default.nix index 22bc1ca5e2ce..491c010ac871 100644 --- a/users/wpcarro/nixos/marcus/default.nix +++ b/users/wpcarro/nixos/marcus/default.nix @@ -50,13 +50,14 @@ in interval = "1d"; }; + libinput = { + enable = true; + touchpad.naturalScrolling = false; + touchpad.tapping = false; + }; + xserver = { enable = true; - libinput = { - enable = true; - touchpad.naturalScrolling = false; - touchpad.tapping = false; - }; xkb.layout = "us"; xkb.options = "caps:escape"; displayManager = { @@ -78,9 +79,6 @@ in }; }; - # Enable sound. - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.wpcarro = { isNormalUser = true; diff --git a/users/wpcarro/nixos/tarasco/default.nix b/users/wpcarro/nixos/tarasco/default.nix index 257201a6c6db..75f19aa6e3d6 100644 --- a/users/wpcarro/nixos/tarasco/default.nix +++ b/users/wpcarro/nixos/tarasco/default.nix @@ -72,9 +72,6 @@ in }; }; - # Enable sound. - hardware.pulseaudio.enable = true; - users.mutableUsers = true; users.users.root.openssh.authorizedKeys.keys = with wpcarro.keys; [ ava diff --git a/users/yl3dy/OWNERS b/users/yl3dy/OWNERS new file mode 100644 index 000000000000..686f0179a665 --- /dev/null +++ b/users/yl3dy/OWNERS @@ -0,0 +1,3 @@ +set noparent + +yl3dy diff --git a/users/yl3dy/test.txt b/users/yl3dy/test.txt new file mode 100644 index 000000000000..57a1fac55ce4 --- /dev/null +++ b/users/yl3dy/test.txt @@ -0,0 +1 @@ +Some gpg-signed text diff --git a/views/README.md b/views/README.md index a6ebd93a7788..57fcbb476e38 100644 --- a/views/README.md +++ b/views/README.md @@ -8,9 +8,8 @@ individual content and usage information. Testing changes locally ----------------------- -Generally, when iterating on these files, it's best to locally invoke `josh- -filter` (from `//third_party//josh`) locally to inspect how the workspace would -look like: +Generally, when iterating on these files, it's best to invoke `josh-filter` +(from the `josh` package) locally to inspect how the workspace would look like: - Commit your changes. This is required, as `josh-filter` operates on your `HEAD`, not working directory state. diff --git a/web/atward/indexHtml/default.nix b/web/atward/indexHtml/default.nix index 3af808b89831..801faf57dcf2 100644 --- a/web/atward/indexHtml/default.nix +++ b/web/atward/indexHtml/default.nix @@ -35,65 +35,13 @@ depot.web.tvl.template { <kbd>cl</kbd>), atward will redirect to the appropriate `tvl.fyi` domain. - ### Configuration - - Some behaviour of atward can be configured by adding query - parameters to the search string: - - * <kbd>cs=true</kbd> - use Sourcegraph instead of cgit to view code - - - In some browsers (like Firefox) users can not edit query - parameters for search engines. As an alternative configuration can - be supplied via cookies with the same names as the configuration - parameters. - - The form below can set this configuration: - <form class="cheddar-callout cheddar-todo"> - <input type="checkbox" - id="cs-setting" - name="cs-setting" - onchange="saveSetting(this, 'cs');"> - <label for="cs-setting">Use Sourcegraph instead of cgit</label> - </form> - - <noscript> - <p class="cheddar-callout cheddar-warning"> - The form above only works with Javascript enabled. Only a few - lines of Javascript are used, and they are licensed under a - free-software license (MIT). - </p> - </noscript> - ### Source code atward's source code lives at [//web/atward](https://at.tvl.fyi/?q=%2F%2Fweb%2Fatward). ''; - extraHead = '' - <script> - /* Initialise the state of all settings. */ - function loadSettings() { - loadSetting(document.getElementById('cs-setting'), 'cs'); - } - - /* Initialise the state of a setting from a cookie. */ - function loadSetting(checkbox, name) { - if (document.cookie.split(';').some(function(cookie) { - return cookie.indexOf(`''${name}=true`) >= 0; - })) { - checkbox.checked = true; - } - } - /* Persist the state of a checkbox in a cookie */ - function saveSetting(checkbox, name) { - console.log(`setting atward parameter '''''${name}' to ''${checkbox.checked.toString()}`); - document.cookie = `''${name}=''${checkbox.checked.toString()};`; - } - - document.addEventListener('DOMContentLoaded', loadSettings); - </script> + extraHead = '' <link rel="search" type="application/opensearchdescription+xml" title="TVL Search" href="https://at.tvl.fyi/opensearch.xml"> ''; } diff --git a/web/atward/src/main.rs b/web/atward/src/main.rs index eb2603a226c6..13aeff0e27d8 100644 --- a/web/atward/src/main.rs +++ b/web/atward/src/main.rs @@ -5,7 +5,6 @@ //! browsers and attempts to send users to useful locations based on //! their search query (falling back to another search engine). use regex::Regex; -use rouille::input::cookies; use rouille::{Request, Response}; #[cfg(test)] @@ -31,43 +30,14 @@ struct Handler { struct Query { /// Query string itself. query: String, - - /// Should Sourcegraph be used instead of cgit? - cs: bool, -} - -/// Helper function for setting a parameter based on a query -/// parameter. -fn query_setting(req: &Request, config: &mut bool, param: &str) { - match req.get_param(param) { - Some(s) if s == "true" => *config = true, - Some(s) if s == "false" => *config = false, - _ => {} - } } impl Query { fn from_request(req: &Request) -> Option<Query> { - // First extract the actual search query ... - let mut query = match req.get_param("q") { - Some(query) => Query { query, cs: false }, + match req.get_param("q") { + Some(query) => Some(Query { query }), None => return None, - }; - - // ... then apply settings to it. Settings in query parameters - // take precedence over cookies. - for cookie in cookies(req) { - match cookie { - ("cs", "true") => { - query.cs = true; - } - _ => {} - } } - - query_setting(req, &mut query.cs, "cs"); - - Some(query) } } @@ -76,7 +46,6 @@ impl From<&str> for Query { fn from(query: &str) -> Query { Query { query: query.to_string(), - cs: false, } } } @@ -90,10 +59,6 @@ fn cgit_url(path: &str) -> String { } } -/// Create a URL to a path in Sourcegraph. -fn sourcegraph_path_url(path: &str) -> String { - format!("https://cs.tvl.fyi/depot/-/tree/{}", path) -} /// Definition of all supported query handlers in atward. fn handlers() -> Vec<Handler> { vec![ @@ -126,16 +91,11 @@ fn handlers() -> Vec<Handler> { // TODO(tazjin): Add support for specifying lines in a query parameter Handler { pattern: Regex::new("^//(?P<path>[a-zA-Z].*)?$").unwrap(), - target: |query, captures| { + target: |_, captures| { // Pass an empty string if the path is missing, to // redirect to the depot root. let path = captures.name("path").map(|m| m.as_str()).unwrap_or(""); - - if query.cs { - Some(sourcegraph_path_url(path)) - } else { - Some(cgit_url(path)) - } + Some(cgit_url(path)) }, }, ] diff --git a/web/atward/src/tests.rs b/web/atward/src/tests.rs index a23f96ee9a74..eb205fdf9810 100644 --- a/web/atward/src/tests.rs +++ b/web/atward/src/tests.rs @@ -44,38 +44,12 @@ fn depot_path_cgit_query() { } #[test] -fn depot_path_sourcegraph_query() { - assert_eq!( - dispatch( - &handlers(), - &Query { - query: "//web/atward/default.nix".to_string(), - cs: true, - } - ), - Some("https://cs.tvl.fyi/depot/-/tree/web/atward/default.nix".to_string()), - ); - - assert_eq!( - dispatch( - &handlers(), - &Query { - query: "/not/a/depot/path".to_string(), - cs: true, - } - ), - None - ); -} - -#[test] fn depot_root_cgit_query() { assert_eq!( dispatch( &handlers(), &Query { query: "//".to_string(), - cs: false, } ), Some("https://code.tvl.fyi/tree/".to_string()), @@ -112,7 +86,6 @@ fn request_to_query() { .expect("request should parse to a query"), Query { query: "b/42".to_string(), - cs: false, }, ); @@ -123,55 +96,6 @@ fn request_to_query() { } #[test] -fn settings_from_cookie() { - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42", - vec![("Cookie".to_string(), "cs=true;".to_string())], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: true, - }, - ); -} - -#[test] -fn settings_from_query_parameter() { - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42&cs=true", - vec![], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: true, - }, - ); - - // Query parameter should override cookie - assert_eq!( - Query::from_request(&Request::fake_http( - "GET", - "/?q=b%2F42&cs=false", - vec![("Cookie".to_string(), "cs=true;".to_string())], - vec![] - )) - .expect("request should parse to a query"), - Query { - query: "b/42".to_string(), - cs: false, - }, - ); -} - -#[test] fn depot_revision_query() { assert_eq!( dispatch(&handlers(), &"r/3002".into()), diff --git a/web/bubblegum/default.nix b/web/bubblegum/default.nix index ed9ab616804d..b7e1ce81ebd0 100644 --- a/web/bubblegum/default.nix +++ b/web/bubblegum/default.nix @@ -21,6 +21,7 @@ let # nixpkgs for lib and packages "third_party/nixpkgs" "third_party/overlays" + "third_party/sources" # bubblegum and its dependencies "web/bubblegum" "nix/runExecline" diff --git a/web/cgit-tvl/default.nix b/web/cgit-tvl/default.nix index d26de9a5ebe7..1be2f29b81f0 100644 --- a/web/cgit-tvl/default.nix +++ b/web/cgit-tvl/default.nix @@ -15,7 +15,7 @@ let source-filter=${depot.tools.cheddar}/bin/cheddar enable-log-filecount=1 enable-log-linecount=1 - enable-follow-links=1 + enable-follow-links=0 enable-blame=1 mimetype-file=${pkgs.mime-types}/etc/mime.types logo=https://static.tvl.fyi/${depot.web.static.drvHash}/logo-animated.svg diff --git a/web/pwcrypt/Cargo.lock b/web/pwcrypt/Cargo.lock index 2a88ec59d5a6..75b2d8c9c69f 100644 --- a/web/pwcrypt/Cargo.lock +++ b/web/pwcrypt/Cargo.lock @@ -818,19 +818,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -855,9 +856,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -865,9 +866,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -878,9 +879,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/web/pwcrypt/Cargo.toml b/web/pwcrypt/Cargo.toml index 488dcad19e15..48c73081f1ee 100644 --- a/web/pwcrypt/Cargo.toml +++ b/web/pwcrypt/Cargo.toml @@ -8,6 +8,6 @@ argon2 = "0.5.0" getrandom = { version = "0.2.10", features = ["js"] } gloo = "0.8.0" rand_core = { version = "0.6.4", features = ["getrandom"] } -wasm-bindgen = "= 0.2.92" +wasm-bindgen = "= 0.2.93" web-sys = "0.3" yew = { version = "0.20.0", features = [ "csr" ]} diff --git a/web/tvixbolt/Cargo.lock b/web/tvixbolt/Cargo.lock index 82162469dee9..f67dbb9f9846 100644 --- a/web/tvixbolt/Cargo.lock +++ b/web/tvixbolt/Cargo.lock @@ -75,12 +75,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] -name = "bitmaps" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703642b98a00b3b90513279a8ede3fcfa479c126c5fb46e78f3051522f021403" - -[[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -97,9 +91,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" [[package]] name = "bstr" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -114,9 +108,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" @@ -745,29 +739,6 @@ dependencies = [ ] [[package]] -name = "imbl" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be8d8cd36f33a46b1849f31f837c44d9fa87223baee3b4bd96b8f11df81eb" -dependencies = [ - "bitmaps", - "imbl-sized-chunks", - "rand_core", - "rand_xoshiro", - "serde", - "version_check", -] - -[[package]] -name = "imbl-sized-chunks" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6957ea0b2541c5ca561d3ef4538044af79f8a05a1eb3a3b148936aaceaa1076" -dependencies = [ - "bitmaps", -] - -[[package]] name = "implicit-clone" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -809,9 +780,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -833,9 +804,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lexical-core" @@ -959,6 +930,12 @@ dependencies = [ ] [[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] name = "nom8" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1128,29 +1105,14 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] [[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] name = "redox_syscall" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1172,9 +1134,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1184,9 +1146,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1259,9 +1221,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -1290,9 +1252,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1364,9 +1326,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -1557,11 +1519,11 @@ dependencies = [ "data-encoding", "dirs", "genawaiter", - "imbl", "itertools", "lazy_static", "lexical-core", "md-5", + "nohash-hasher", "os_str_bytes", "path-clean", "regex", @@ -1576,6 +1538,7 @@ dependencies = [ "tabwriter", "toml", "tvix-eval-builtin-macros", + "vu128", ] [[package]] @@ -1630,6 +1593,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] +name = "vu128" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18da3bd753c6f4373511e5f025423986560dfe4a5e7d642cc9a0266847f9fdd" + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1637,19 +1606,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -1674,9 +1644,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1684,9 +1654,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -1697,9 +1667,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" diff --git a/web/tvixbolt/Cargo.nix b/web/tvixbolt/Cargo.nix index a2ad6cc33e80..ceec2d582cca 100644 --- a/web/tvixbolt/Cargo.nix +++ b/web/tvixbolt/Cargo.nix @@ -150,7 +150,7 @@ rec { "perf-literal" = [ "dep:memchr" ]; "std" = [ "memchr?/std" ]; }; - resolvedDefaultFeatures = [ "default" "perf-literal" "std" ]; + resolvedDefaultFeatures = [ "perf-literal" "std" ]; }; "anymap2" = rec { crateName = "anymap2"; @@ -283,24 +283,12 @@ rec { "serde" = [ "dep:serde" ]; }; }; - "bitmaps" = rec { - crateName = "bitmaps"; - version = "3.2.0"; - edition = "2021"; - sha256 = "00ql08pm4l9hizkldyy54v0pk96g7zg8x6i72c2vkcq0iawl4dkh"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - ]; - features = { - "default" = [ "std" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "block-buffer" = rec { crateName = "block-buffer"; version = "0.10.4"; edition = "2018"; sha256 = "0w9sa2ypmrsqqvc20nhwr75wbb5cjr4kkyhpjm1z1lv2kdicfy1h"; + libName = "block_buffer"; authors = [ "RustCrypto Developers" ]; @@ -324,9 +312,9 @@ rec { }; "bstr" = rec { crateName = "bstr"; - version = "1.9.0"; + version = "1.10.0"; edition = "2021"; - sha256 = "1p6hzf3wqwwynv6w4pn17jg21amfafph9kb5sfvf1idlli8h13y4"; + sha256 = "036wwrchd5gq3q4k6w1j2bfl2bk2ff8c0dsa9y7w7aw7nf7knwj0"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -375,9 +363,9 @@ rec { }; "bytes" = rec { crateName = "bytes"; - version = "1.5.0"; + version = "1.7.1"; edition = "2018"; - sha256 = "08w2i8ac912l8vlvkv3q51cd4gr09pwlg3sjsjffcizlrb0i5gd2"; + sha256 = "0l5sf69avjxcw41cznyzxsnymwmkpmk08q0sm7fgicvvn0ysa643"; authors = [ "Carl Lerche <me@carllerche.com>" "Sean McArthur <sean@seanmonstar.com>" @@ -405,6 +393,7 @@ rec { version = "1.0.0"; edition = "2018"; sha256 = "1za0vb97n4brpzpv8lsbnzmq5r8f2b0cpqqr0sy8h5bn751xxwds"; + libName = "cfg_if"; authors = [ "Alex Crichton <alex@alexcrichton.com>" ]; @@ -429,6 +418,7 @@ rec { version = "0.1.2"; edition = "2015"; sha256 = "08l1b84bn8r8a72rbvyi2v8a5i0j0kk0a5gr7fb6lmjvw05pf86c"; + libName = "codemap_diagnostic"; authors = [ "Kevin Mehall <km@kevinmehall.net>" "The Rust Project Developers" @@ -518,6 +508,7 @@ rec { version = "0.1.6"; edition = "2018"; sha256 = "1cvby95a6xg7kxdz5ln3rl9xh66nz66w46mm3g56ri1z5x815yqv"; + libName = "crypto_common"; authors = [ "RustCrypto Developers" ]; @@ -543,6 +534,7 @@ rec { version = "2.6.0"; edition = "2018"; sha256 = "1qnn68n4vragxaxlkqcb1r28d3hhj43wch67lm4rpxlw89wnjmp8"; + libName = "data_encoding"; authors = [ "Julien Cretin <git@ia0.eu>" ]; @@ -607,6 +599,7 @@ rec { version = "0.3.7"; edition = "2015"; sha256 = "19md1cnkazham8a6kh22v12d8hh3raqahfk6yb043vrjr68is78v"; + libName = "dirs_sys"; authors = [ "Simon Ochsenreither <simon@ochsenreither.de>" ]; @@ -748,6 +741,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0y6b7xxqdjm9hlcjpakcg41qfl7lihf6gavk8fyqijsxhvbzgj7a"; + libName = "futures_channel"; dependencies = [ { name = "futures-core"; @@ -775,6 +769,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "07aslayrn3lbggj54kci0ishmd1pr367fp7iks7adia1p05miinz"; + libName = "futures_core"; features = { "default" = [ "std" ]; "portable-atomic" = [ "dep:portable-atomic" ]; @@ -787,6 +782,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1hgh25isvsr4ybibywhr4dpys8mjnscw4wfxxwca70cn1gi26im4"; + libName = "futures_io"; features = { "default" = [ "std" ]; }; @@ -798,6 +794,7 @@ rec { edition = "2018"; sha256 = "1b49qh9d402y8nka4q6wvvj0c88qq91wbr192mdn5h54nzs0qxc7"; procMacro = true; + libName = "futures_macro"; dependencies = [ { name = "proc-macro2"; @@ -820,6 +817,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "1dag8xyyaya8n8mh8smx7x6w2dpmafg2din145v973a3hw7f1f4z"; + libName = "futures_sink"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -831,6 +829,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "013h1724454hj8qczp8vvs10qfiqrxr937qsrv6rhii68ahlzn1q"; + libName = "futures_task"; features = { "default" = [ "std" ]; "std" = [ "alloc" ]; @@ -842,6 +841,7 @@ rec { version = "0.3.30"; edition = "2018"; sha256 = "0j0xqhcir1zf2dcbpd421kgw6wvsk0rpxflylcysn1rlp3g02r1x"; + libName = "futures_util"; dependencies = [ { name = "futures-channel"; @@ -950,6 +950,7 @@ rec { version = "0.99.1"; edition = "2018"; sha256 = "1g6zmr88fk48f1ksz9ik1i2mwjsiam9s4p9aybhvs2zwzphxychb"; + libName = "genawaiter_macro"; authors = [ "Devin R <devin.ragotzy@gmail.com>" ]; @@ -1240,6 +1241,7 @@ rec { version = "0.2.3"; edition = "2018"; sha256 = "0gqd35vn0i5y6hzfrsb2i032p1j832c08sar6dr19gny0lycxdw2"; + libName = "gloo_console"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1275,6 +1277,7 @@ rec { version = "0.3.0"; edition = "2021"; sha256 = "0qg24wbvql0bsr980hbrm0pi11c3jmlwpj0pgdklz8mlas7qc5ra"; + libName = "gloo_console"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1310,6 +1313,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "1rh2j0l8rbj8pbypxqy99qi2x3hq52sclijs8h47zlkjmij261k7"; + libName = "gloo_dialogs"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1331,6 +1335,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "1pqmg2z3x4c3id25jd0p8rjwy5qjbc4k1x8gflsi9c1207hlhixz"; + libName = "gloo_dialogs"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1352,6 +1357,7 @@ rec { version = "0.1.2"; edition = "2018"; sha256 = "1z4j14r2lim77s0jm1dpk306jyycmx2kirid33j0b0gdmgw0gcb8"; + libName = "gloo_events"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1380,6 +1386,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0h8yr4n1pvwp4rr87835w14kjdkycyn8gypmh2lmnf3wbys6zhi7"; + libName = "gloo_events"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1408,6 +1415,7 @@ rec { version = "0.2.3"; edition = "2018"; sha256 = "1mxnd7l8gglv5yqhah6ny329hc0c98vn7h5xg0yv8f0aax75dmd8"; + libName = "gloo_file"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1449,6 +1457,7 @@ rec { version = "0.3.0"; edition = "2021"; sha256 = "07xxainnnrg6l3ccw2bvqiz4m76ih557aklp5r5q5cizhrqksmlp"; + libName = "gloo_file"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1495,6 +1504,7 @@ rec { version = "0.1.5"; edition = "2018"; sha256 = "0zsy3m5bgah8hyd95sc9b68afn1nhs7g43lkndip1m0fpy85swl5"; + libName = "gloo_history"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1549,6 +1559,7 @@ rec { version = "0.2.2"; edition = "2021"; sha256 = "1mhphqywgbqj4agpi4zyc4hah12nys7085jymiz44d5swlml6gwh"; + libName = "gloo_history"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1609,6 +1620,7 @@ rec { version = "0.3.1"; edition = "2018"; sha256 = "0866ih3bff7dwxdfc813pk5nwz2ayyqwi5vbzlax7n4ygly4wsx6"; + libName = "gloo_net"; authors = [ "Rust and WebAssembly Working Group" "Muhammad Hamza <muhammadhamza1311@gmail.com>" @@ -1701,6 +1713,7 @@ rec { version = "0.4.0"; edition = "2021"; sha256 = "1i3x5fvp07valrxjsa25ycq1b2p3pxqaqmw6kzx35ip2i8lfijca"; + libName = "gloo_net"; authors = [ "Rust and WebAssembly Working Group" "Muhammad Hamza <muhammadhamza1311@gmail.com>" @@ -1793,6 +1806,7 @@ rec { version = "0.1.1"; edition = "2018"; sha256 = "0r3pxj22l489ldakj6521a0f0n1r9v8xrai3k12d9kv7xxm31n9g"; + libName = "gloo_render"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1814,6 +1828,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "0cwqcka7l5p29idq174c6mi5cgal0rywngdck26qwfki8ikqn02n"; + libName = "gloo_render"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1835,6 +1850,7 @@ rec { version = "0.2.2"; edition = "2018"; sha256 = "1074j754a6c21sbmqws5qwaha0a13fikv17ps476zzfvyl5vcsjx"; + libName = "gloo_storage"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1883,6 +1899,7 @@ rec { version = "0.3.0"; edition = "2021"; sha256 = "0yi7740iza6nyg6n8sxzzhy6yg6xpbxhig7r2bwqlxcjihg07j7v"; + libName = "gloo_storage"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1931,6 +1948,7 @@ rec { version = "0.2.6"; edition = "2018"; sha256 = "0p2yqcxw0q9kclhwpgshq1r4ijns07nmmagll3lvrgl7pdk5m6cv"; + libName = "gloo_timers"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1956,6 +1974,7 @@ rec { version = "0.3.0"; edition = "2021"; sha256 = "1519157n7xppkk6pdw5w52vy1llzn5iljkqd7q1h5609jv7l7cdv"; + libName = "gloo_timers"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -1991,6 +2010,7 @@ rec { version = "0.1.7"; edition = "2018"; sha256 = "13m59g36spynspvhx0xsaahbkdshn1v03gcjf87s7cvc443wnzq3"; + libName = "gloo_utils"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -2030,6 +2050,7 @@ rec { version = "0.2.0"; edition = "2021"; sha256 = "1am31cd6889shb7158bg9zzsjcpvyzxrhfhxgia8rc8k84smam8b"; + libName = "gloo_utils"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -2069,6 +2090,7 @@ rec { version = "0.2.1"; edition = "2018"; sha256 = "0sjiw13069i7bpiyb03w3kyddn3q07fmj4vd60l1l1kqva21aiqk"; + libName = "gloo_worker"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -2120,6 +2142,7 @@ rec { version = "0.4.0"; edition = "2021"; sha256 = "00744js1jcwdndzf22c8gzml7aqql4ymjfpsd2i1vrbxv0ymsjbn"; + libName = "gloo_worker"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -2182,6 +2205,7 @@ rec { edition = "2021"; sha256 = "1rs0f6b34mkhlmpmhqi747c34000sd5mxma92yacjyw5sicalv4m"; procMacro = true; + libName = "gloo_worker_macros"; authors = [ "Rust and WebAssembly Working Group" ]; @@ -2257,6 +2281,7 @@ rec { version = "0.3.9"; edition = "2021"; sha256 = "092hxjbjnq5fmz66grd9plxd0sh6ssg5fhgwwwqbrzgzkjwdycfj"; + libName = "hermit_abi"; authors = [ "Stefan Lankes" ]; @@ -2294,91 +2319,12 @@ rec { ]; }; - "imbl" = rec { - crateName = "imbl"; - version = "3.0.0"; - edition = "2018"; - sha256 = "1sw1vw8qysyr9cxyxfi3fal9ykf46zw337w4n533mwrnrpcfhfxw"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - } - { - name = "imbl-sized-chunks"; - packageId = "imbl-sized-chunks"; - } - { - name = "rand_core"; - packageId = "rand_core"; - } - { - name = "rand_xoshiro"; - packageId = "rand_xoshiro"; - } - { - name = "serde"; - packageId = "serde"; - optional = true; - } - ]; - buildDependencies = [ - { - name = "version_check"; - packageId = "version_check"; - } - ]; - devDependencies = [ - { - name = "serde"; - packageId = "serde"; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "proptest" = [ "dep:proptest" ]; - "quickcheck" = [ "dep:quickcheck" ]; - "rayon" = [ "dep:rayon" ]; - "refpool" = [ "dep:refpool" ]; - "serde" = [ "dep:serde" ]; - "triomphe" = [ "dep:triomphe" ]; - }; - resolvedDefaultFeatures = [ "serde" ]; - }; - "imbl-sized-chunks" = rec { - crateName = "imbl-sized-chunks"; - version = "0.1.1"; - edition = "2021"; - sha256 = "0xhhmb7aldl92hxkmsx10n59zxsa0hw4bvykc6jmq72lnah7x5g6"; - authors = [ - "Bodil Stokke <bodil@bodil.org>" - "Joe Neeman <joeneeman@gmail.com>" - ]; - dependencies = [ - { - name = "bitmaps"; - packageId = "bitmaps"; - usesDefaultFeatures = false; - } - ]; - features = { - "arbitrary" = [ "dep:arbitrary" ]; - "array-ops" = [ "dep:array-ops" ]; - "default" = [ "std" ]; - "refpool" = [ "dep:refpool" ]; - "ringbuffer" = [ "array-ops" ]; - }; - resolvedDefaultFeatures = [ "default" "std" ]; - }; "implicit-clone" = rec { crateName = "implicit-clone"; version = "0.4.9"; edition = "2021"; sha256 = "113agd9bqk7c0s2rqgarzkfp3wgbzl3q59mp6sv72nkv3iwsmagq"; + libName = "implicit_clone"; authors = [ "Cecile Tonglet <cecile.tonglet@cecton.com>" ]; @@ -2410,6 +2356,7 @@ rec { edition = "2021"; sha256 = "0fsfj6n56mg92f3899gcdck1dqlsmgyd52k0n2xhhj53p5g6h4ck"; procMacro = true; + libName = "implicit_clone_derive"; authors = [ "Cecile Tonglet <cecile.tonglet@cecton.com>" ]; @@ -2485,9 +2432,9 @@ rec { }; "itertools" = rec { crateName = "itertools"; - version = "0.12.0"; + version = "0.12.1"; edition = "2018"; - sha256 = "1c07gzdlc6a1c8p8jrvvw3gs52bss3y58cs2s21d9i978l36pnr5"; + sha256 = "0s95jbb3ndj1lvfxyq5wanc0fm0r6hg6q4ngb92qlfdxvci10ads"; authors = [ "bluss" ]; @@ -2521,6 +2468,7 @@ rec { version = "0.3.69"; edition = "2018"; sha256 = "0v99rz97asnzapb0jsc3jjhvxpfxr7h7qd97yqyrf9i7viimbh99"; + libName = "js_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -2534,9 +2482,9 @@ rec { }; "lazy_static" = rec { crateName = "lazy_static"; - version = "1.4.0"; + version = "1.5.0"; edition = "2015"; - sha256 = "0in6ikhw8mgl33wjv6q6xfrb5b9jr16q8ygjy803fay4zcisvaz2"; + sha256 = "1zk6dqqni0193xg6iijh7i3i44sryglwgvx20spdvwk3r6sbrlmv"; authors = [ "Marvin Löbel <loebel.marvin@gmail.com>" ]; @@ -2550,6 +2498,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ihf0x3vrk25fq3bv9q35m0xax0wmvwkh0j0pjm2yk4ddvh5vpic"; + libName = "lexical_core"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2612,6 +2561,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0py0gp8hlzcrlvjqmqlpl2v1as65iiqxq2xsabxvhc01pmg3lfv8"; + libName = "lexical_parse_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2652,6 +2602,7 @@ rec { version = "0.8.6"; edition = "2018"; sha256 = "1sayji3mpvb2xsjq56qcq3whfz8px9a6fxk5v7v15hyhbr4982bd"; + libName = "lexical_parse_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2683,6 +2634,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "1z73qkv7yxhsbc4aiginn1dqmsj8jarkrdlyxc88g2gz2vzvjmaj"; + libName = "lexical_util"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2709,6 +2661,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0qk825l0csvnksh9sywb51996cjc2bylq6rxjaiha7sqqjhvmjmc"; + libName = "lexical_write_float"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2749,6 +2702,7 @@ rec { version = "0.8.5"; edition = "2018"; sha256 = "0ii4hmvqrg6pd4j9y1pkhkp0nw2wpivjzmljh6v6ca22yk8z7dp1"; + libName = "lexical_write_integer"; authors = [ "Alex Huszagh <ahuszagh@gmail.com>" ]; @@ -2939,6 +2893,20 @@ rec { "simd-adler32" = [ "dep:simd-adler32" ]; }; }; + "nohash-hasher" = rec { + crateName = "nohash-hasher"; + version = "0.2.0"; + edition = "2018"; + sha256 = "0lf4p6k01w4wm7zn4grnihzj8s7zd5qczjmzng7wviwxawih5x9b"; + libName = "nohash_hasher"; + authors = [ + "Parity Technologies <admin@parity.io>" + ]; + features = { + "default" = [ "std" ]; + }; + resolvedDefaultFeatures = [ "default" "std" ]; + }; "nom8" = rec { crateName = "nom8"; version = "0.2.0"; @@ -3062,6 +3030,7 @@ rec { version = "0.1.0"; edition = "2015"; sha256 = "1pcgqxw0mgg3ha5hi5xkjhyjf488bw5rw1g3qlr9awbq4szh3fpc"; + libName = "path_clean"; authors = [ "Dan Reeves <hey@danreev.es>" ]; @@ -3072,6 +3041,7 @@ rec { version = "2.3.1"; edition = "2018"; sha256 = "0gi8wgx0dcy8rnv1kywdv98lwcx67hz0a0zwpib5v2i08r88y573"; + libName = "percent_encoding"; authors = [ "The rust-url developers" ]; @@ -3086,6 +3056,7 @@ rec { version = "1.1.5"; edition = "2021"; sha256 = "1cxl146x0q7lawp0m1826wsgj8mmmfs6ja8q7m6f7ff5j6vl7gxn"; + libName = "pin_project"; dependencies = [ { name = "pin-project-internal"; @@ -3100,6 +3071,7 @@ rec { edition = "2021"; sha256 = "0r9r4ivwiyqf45sv6b30l1dx282lxaax2f6gl84jwa3q590s8f1g"; procMacro = true; + libName = "pin_project_internal"; dependencies = [ { name = "proc-macro2"; @@ -3122,6 +3094,7 @@ rec { version = "0.2.14"; edition = "2018"; sha256 = "00nx3f04agwjlsmd3mc5rx5haibj2v8q9b52b0kwn63wcv4nz9mx"; + libName = "pin_project_lite"; }; "pin-utils" = rec { @@ -3129,6 +3102,7 @@ rec { version = "0.1.0"; edition = "2018"; sha256 = "117ir7vslsl2z1a7qzhws4pd01cg2d3338c47swjyvqv2n60v1wb"; + libName = "pin_utils"; authors = [ "Josef Brandl <mail@josefbrandl.de>" ]; @@ -3204,6 +3178,7 @@ rec { version = "1.3.1"; edition = "2021"; sha256 = "069r1k56bvgk0f58dm5swlssfcp79im230affwk6d9ck20g04k3z"; + libName = "proc_macro_crate"; authors = [ "Bastian Köcher <git@kchr.de>" ]; @@ -3224,6 +3199,7 @@ rec { version = "1.0.4"; edition = "2018"; sha256 = "1373bhxaf0pagd8zkyd03kkx6bchzf6g0dkwrwzsnal9z47lj9fs"; + libName = "proc_macro_error"; authors = [ "CreepySkeleton <creepy-skeleton@yandex.ru>" ]; @@ -3266,6 +3242,7 @@ rec { edition = "2018"; sha256 = "0sgq6m5jfmasmwwy8x4mjygx5l7kp8s4j60bv25ckv2j1qc41gm1"; procMacro = true; + libName = "proc_macro_error_attr"; authors = [ "CreepySkeleton <creepy-skeleton@yandex.ru>" ]; @@ -3377,9 +3354,9 @@ rec { }; "quote" = rec { crateName = "quote"; - version = "1.0.36"; + version = "1.0.37"; edition = "2018"; - sha256 = "19xcmh445bg6simirnnd4fvkmp6v2qiwxh5f6rw4a70h76pnm9qg"; + sha256 = "1brklraw2g34bxy9y4q1nbrccn7bv36ylihv12c9vlcii55x7fdm"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -3396,41 +3373,6 @@ rec { }; resolvedDefaultFeatures = [ "default" "proc-macro" ]; }; - "rand_core" = rec { - crateName = "rand_core"; - version = "0.6.4"; - edition = "2018"; - sha256 = "0b4j2v4cb5krak1pv6kakv4sz6xcwbrmy2zckc32hsigbrwy82zc"; - authors = [ - "The Rand Project Developers" - "The Rust Project Developers" - ]; - features = { - "getrandom" = [ "dep:getrandom" ]; - "serde" = [ "dep:serde" ]; - "serde1" = [ "serde" ]; - "std" = [ "alloc" "getrandom" "getrandom/std" ]; - }; - }; - "rand_xoshiro" = rec { - crateName = "rand_xoshiro"; - version = "0.6.0"; - edition = "2018"; - sha256 = "1ajsic84rzwz5qr0mzlay8vi17swqi684bqvwqyiim3flfrcv5vg"; - authors = [ - "The Rand Project Developers" - ]; - dependencies = [ - { - name = "rand_core"; - packageId = "rand_core"; - } - ]; - features = { - "serde" = [ "dep:serde" ]; - "serde1" = [ "serde" ]; - }; - }; "redox_syscall" = rec { crateName = "redox_syscall"; version = "0.4.1"; @@ -3486,9 +3428,9 @@ rec { }; "regex" = rec { crateName = "regex"; - version = "1.10.2"; + version = "1.10.6"; edition = "2021"; - sha256 = "0hxkd814n4irind8im5c9am221ri6bprx49nc7yxv02ykhd9a2rq"; + sha256 = "06cnlxwzyqfbw1za1i7ks89ns4i2kr0lpg5ykx56b8v7dd6df6a2"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -3498,11 +3440,13 @@ rec { name = "aho-corasick"; packageId = "aho-corasick"; optional = true; + usesDefaultFeatures = false; } { name = "memchr"; packageId = "memchr"; optional = true; + usesDefaultFeatures = false; } { name = "regex-automata"; @@ -3542,9 +3486,10 @@ rec { }; "regex-automata" = rec { crateName = "regex-automata"; - version = "0.4.3"; + version = "0.4.7"; edition = "2021"; - sha256 = "0gs8q9yhd3kcg4pr00ag4viqxnh5l7jpyb9fsfr8hzh451w4r02z"; + sha256 = "1pwjdi4jckpbaivpl6x4v5g4crb37zr2wac93wlfsbzgqn6gbjiq"; + libName = "regex_automata"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -3605,6 +3550,7 @@ rec { version = "0.8.2"; edition = "2021"; sha256 = "17rd2s8xbiyf6lb4aj2nfi44zqlj98g2ays8zzj2vfs743k79360"; + libName = "regex_syntax"; authors = [ "The Rust Project Developers" "Andrew Gallant <jamslam@gmail.com>" @@ -3637,6 +3583,7 @@ rec { version = "0.3.1"; edition = "2018"; sha256 = "0ikp3blbina00jdbifxw1c9whg6mljli24lq5pv82iar53xr9axg"; + libName = "route_recognizer"; authors = [ "wycats" "rustasync" @@ -3700,6 +3647,7 @@ rec { version = "1.1.0"; edition = "2015"; sha256 = "1qkc5khrmv5pqi5l5ca9p5nl5hs742cagrndhbrlk3dhlrx3zm08"; + libName = "rustc_hash"; authors = [ "The Rust Project Developers" ]; @@ -3713,6 +3661,7 @@ rec { version = "2.0.0"; edition = "2021"; sha256 = "0lni0lf846bzrf3jvci6jaf4142n1mdqxvcpczk5ch9pfgyk8c2q"; + libName = "rustc_hash"; authors = [ "The Rust Project Developers" ]; @@ -3748,9 +3697,9 @@ rec { }; "serde" = rec { crateName = "serde"; - version = "1.0.204"; + version = "1.0.210"; edition = "2018"; - sha256 = "04kwpwqz559xlhxkggmm8rjxqgywy5swam3kscwsicnbw1cgaxmw"; + sha256 = "0flc0z8wgax1k4j5bf2zyq48bgzyv425jkd5w0i6wbh7f8j5kqy8"; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" "David Tolnay <dtolnay@gmail.com>" @@ -3785,6 +3734,7 @@ rec { version = "0.5.0"; edition = "2018"; sha256 = "03m01y4l2kqz63pb1bip52j8bqilzlhhsa7asfdanmrwhgi47cgk"; + libName = "serde_wasm_bindgen"; authors = [ "Ingvar Stepanyan <me@rreverser.com>" ]; @@ -3816,6 +3766,7 @@ rec { version = "0.6.5"; edition = "2018"; sha256 = "0sz1l4v8059hiizf5z7r2spm6ws6sqcrs4qgqwww3p7dy1ly20l3"; + libName = "serde_wasm_bindgen"; authors = [ "Ingvar Stepanyan <me@rreverser.com>" ]; @@ -3838,9 +3789,9 @@ rec { }; "serde_derive" = rec { crateName = "serde_derive"; - version = "1.0.204"; + version = "1.0.210"; edition = "2015"; - sha256 = "08p25262mbmhsr2cg0508d5b1wvljj956rvpg0v3qgg6gc8pxkg0"; + sha256 = "07yzy4wafk79ps0hmbqmsqh5xjna4pm4q57wc847bb8gl3nh4f94"; procMacro = true; authors = [ "Erick Tryzelaar <erick.tryzelaar@gmail.com>" @@ -4061,9 +4012,9 @@ rec { }; "smol_str" = rec { crateName = "smol_str"; - version = "0.2.0"; + version = "0.2.2"; edition = "2018"; - sha256 = "1779hpx5ipbcvkdj5zw8zqk3ynn160qvls1gkcr54hwsprmjw8bl"; + sha256 = "1bfylqf2vnqaglw58930vpxm2rfzji5gjp15a2c0kh8aj6v8ylyx"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" ]; @@ -4206,6 +4157,7 @@ rec { version = "1.1.1"; edition = "2018"; sha256 = "0cwjbkl7w3xc8mnkhg1nwij6p5y2qkcfldgss8ddnawvhf3s32pi"; + libName = "text_size"; authors = [ "Aleksey Kladov <aleksey.kladov@gmail.com>" "Christopher Durham (CAD97) <cad97@cad97.com>" @@ -4301,6 +4253,7 @@ rec { version = "0.1.15"; edition = "2021"; sha256 = "1brpbsqyg8yfmfc4y0j9zxvc8xsxjc31d48kb0g6jvpc1fgchyi6"; + libName = "tokio_stream"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4530,6 +4483,7 @@ rec { edition = "2018"; sha256 = "1rvb5dn9z6d0xdj14r403z0af0bbaqhg02hq4jc97g5wds6lqw1l"; procMacro = true; + libName = "tracing_attributes"; authors = [ "Tokio Contributors <team@tokio.rs>" "Eliza Weisman <eliza@buoyant.io>" @@ -4558,6 +4512,7 @@ rec { version = "0.1.32"; edition = "2018"; sha256 = "0m5aglin3cdwxpvbg6kz0r9r0k31j48n0kcfwsp6l49z26k3svf0"; + libName = "tracing_core"; authors = [ "Tokio Contributors <team@tokio.rs>" ]; @@ -4614,11 +4569,6 @@ rec { usesDefaultFeatures = false; } { - name = "imbl"; - packageId = "imbl"; - features = [ "serde" ]; - } - { name = "itertools"; packageId = "itertools"; } @@ -4636,6 +4586,10 @@ rec { packageId = "md-5"; } { + name = "nohash-hasher"; + packageId = "nohash-hasher"; + } + { name = "os_str_bytes"; packageId = "os_str_bytes"; features = [ "conversions" ]; @@ -4694,6 +4648,10 @@ rec { packageId = "tvix-eval-builtin-macros"; rename = "builtin-macros"; } + { + name = "vu128"; + packageId = "vu128"; + } ]; devDependencies = [ { @@ -4702,7 +4660,7 @@ rec { } ]; features = { - "arbitrary" = [ "proptest" "test-strategy" "imbl/proptest" ]; + "arbitrary" = [ "proptest" "test-strategy" ]; "default" = [ "impure" "arbitrary" "nix_tests" ]; "proptest" = [ "dep:proptest" ]; "test-strategy" = [ "dep:test-strategy" ]; @@ -4714,6 +4672,7 @@ rec { edition = "2021"; src = lib.cleanSourceWith { filter = sourceFilter; src = ../../tvix/eval/builtin-macros; }; procMacro = true; + libName = "tvix_eval_builtin_macros"; authors = [ "Griffin Smith <root@gws.fyi>" ]; @@ -4792,6 +4751,7 @@ rec { version = "1.0.12"; edition = "2018"; sha256 = "0jzf1znfpb2gx8nr8mvmyqs1crnv79l57nxnbiszc7xf7ynbjm1k"; + libName = "unicode_ident"; authors = [ "David Tolnay <dtolnay@gmail.com>" ]; @@ -4802,6 +4762,7 @@ rec { version = "0.1.11"; edition = "2015"; sha256 = "11ds4ydhg8g7l06rlmh712q41qsrd0j0h00n1jm74kww3kqk65z5"; + libName = "unicode_width"; authors = [ "kwantam <kwantam@gmail.com>" "Manish Goregaokar <manishsmail@gmail.com>" @@ -4835,6 +4796,17 @@ rec { ]; }; + "vu128" = rec { + crateName = "vu128"; + version = "1.1.0"; + edition = "2018"; + sha256 = "1pczgy26c0lsri1ddrx5wkgn0rcq4da04pqya5rl6vrwfnys73di"; + libPath = "vu128/vu128.rs"; + authors = [ + "John Millikin <john@john-millikin.com>" + ]; + + }; "wasi" = rec { crateName = "wasi"; version = "0.11.0+wasi-snapshot-preview1"; @@ -4853,9 +4825,10 @@ rec { }; "wasm-bindgen" = rec { crateName = "wasm-bindgen"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1a4mcw13nsk3fr8fxjzf9kk1wj88xkfsmnm0pjraw01ryqfm7qjb"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1dfr7pka5kwvky2fx82m9d060p842hc5fyyw8igryikcdb0xybm8"; + libName = "wasm_bindgen"; authors = [ "The wasm-bindgen Developers" ]; @@ -4865,6 +4838,10 @@ rec { packageId = "cfg-if"; } { + name = "once_cell"; + packageId = "once_cell"; + } + { name = "wasm-bindgen-macro"; packageId = "wasm-bindgen-macro"; } @@ -4872,7 +4849,6 @@ rec { features = { "default" = [ "spans" "std" ]; "enable-interning" = [ "std" ]; - "gg-alloc" = [ "wasm-bindgen-test/gg-alloc" ]; "serde" = [ "dep:serde" ]; "serde-serialize" = [ "serde" "serde_json" "std" ]; "serde_json" = [ "dep:serde_json" ]; @@ -4884,9 +4860,10 @@ rec { }; "wasm-bindgen-backend" = rec { crateName = "wasm-bindgen-backend"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1nj7wxbi49f0rw9d44rjzms26xlw6r76b2mrggx8jfbdjrxphkb1"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0yypblaf94rdgqs5xw97499xfwgs1096yx026d6h88v563d9dqwx"; + libName = "wasm_bindgen_backend"; authors = [ "The wasm-bindgen Developers" ]; @@ -4931,6 +4908,7 @@ rec { version = "0.4.42"; edition = "2018"; sha256 = "1h322zjvpjllcpj7dahfxjsv6inkr6y0baw7nkdwivr1c4v19g3n"; + libName = "wasm_bindgen_futures"; authors = [ "The wasm-bindgen Developers" ]; @@ -4961,10 +4939,11 @@ rec { }; "wasm-bindgen-macro" = rec { crateName = "wasm-bindgen-macro"; - version = "0.2.92"; - edition = "2018"; - sha256 = "09npa1srjjabd6nfph5yc03jb26sycjlxhy0c2a1pdrpx4yq5y51"; + version = "0.2.93"; + edition = "2021"; + sha256 = "1kycd1xfx4d9xzqknvzbiqhwb5fzvjqrrn88x692q1vblj8lqp2q"; procMacro = true; + libName = "wasm_bindgen_macro"; authors = [ "The wasm-bindgen Developers" ]; @@ -4986,9 +4965,10 @@ rec { }; "wasm-bindgen-macro-support" = rec { crateName = "wasm-bindgen-macro-support"; - version = "0.2.92"; - edition = "2018"; - sha256 = "1dqv2xs8zcyw4kjgzj84bknp2h76phmsb3n7j6hn396h4ssifkz9"; + version = "0.2.93"; + edition = "2021"; + sha256 = "0dp8w6jmw44srym6l752nkr3hkplyw38a2fxz5f3j1ch9p3l1hxg"; + libName = "wasm_bindgen_macro_support"; authors = [ "The wasm-bindgen Developers" ]; @@ -5023,10 +5003,11 @@ rec { }; "wasm-bindgen-shared" = rec { crateName = "wasm-bindgen-shared"; - version = "0.2.92"; - edition = "2018"; + version = "0.2.93"; + edition = "2021"; links = "wasm_bindgen"; - sha256 = "15kyavsrna2cvy30kg03va257fraf9x00ny554vxngvpyaa0q6dg"; + sha256 = "1104bny0hv40jfap3hp8jhs0q4ya244qcrvql39i38xlghq0lan6"; + libName = "wasm_bindgen_shared"; authors = [ "The wasm-bindgen Developers" ]; @@ -5037,6 +5018,7 @@ rec { version = "0.3.69"; edition = "2018"; sha256 = "1vqkxk935xa8zcnsi4bd88sb267ly2i24xl1yiq26d1n32hskbvp"; + libName = "web_sys"; authors = [ "The wasm-bindgen Developers" ]; @@ -5532,6 +5514,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "1dmpa6mvcvzz16zg6d5vrfy4bxgg541wxrcip7cnshi06v38ffxc"; + libName = "winapi_i686_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5542,6 +5525,7 @@ rec { version = "0.1.6"; edition = "2021"; sha256 = "15i5lm39wd44004i9d5qspry2cynkrpvwzghr6s2c3dsk28nz7pj"; + libName = "winapi_util"; authors = [ "Andrew Gallant <jamslam@gmail.com>" ]; @@ -5560,6 +5544,7 @@ rec { version = "0.4.0"; edition = "2015"; sha256 = "0gqq64czqb64kskjryj8isp62m2sgvx25yyj3kpc2myh85w24bki"; + libName = "winapi_x86_64_pc_windows_gnu"; authors = [ "Peter Atashian <retep998@gmail.com>" ]; @@ -5709,6 +5694,7 @@ rec { edition = "2021"; sha256 = "1qix6k8f8gzxb750icxvxknm3xrg8g7a4035g6gyasbd2sjqrz82"; procMacro = true; + libName = "yew_macro"; authors = [ "Justin Starry <justin@yew.rs>" ]; @@ -5750,6 +5736,7 @@ rec { version = "0.18.0"; edition = "2021"; sha256 = "1ip071apn35gbycpki768ba5hxsrxnnsh2b29lmpdrln5h2xb8ac"; + libName = "yew_router"; authors = [ "Hamza <muhammadhamza1311@gmail.com>" ]; @@ -5827,6 +5814,7 @@ rec { edition = "2021"; sha256 = "134pcmiyi5x6v8s8rnr3fg03v033qhx2piflgkgcza3wl28d3gs2"; procMacro = true; + libName = "yew_router_macro"; authors = [ "Hamza <muhammadhamza1311@gmail.com>" ]; @@ -5956,52 +5944,41 @@ rec { testPostRun ]); in - pkgs.runCommand "run-tests-${testCrate.name}" - { - inherit testCrateFlags; - buildInputs = testInputs; - } '' - set -e + pkgs.stdenvNoCC.mkDerivation { + name = "run-tests-${testCrate.name}"; - export RUST_BACKTRACE=1 + inherit (crate) src; - # recreate a file hierarchy as when running tests with cargo + inherit testCrateFlags; - # the source for test data - # It's necessary to locate the source in $NIX_BUILD_TOP/source/ - # instead of $NIX_BUILD_TOP/ - # because we compiled those test binaries in the former and not the latter. - # So all paths will expect source tree to be there and not in the build top directly. - # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself. - # NOTE: There could be edge cases if `crate.sourceRoot` does exist but - # it's very hard to reason about them. - # Open a bug if you run into this! - mkdir -p source/ - cd source/ + buildInputs = testInputs; - ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src} + buildPhase = '' + set -e + export RUST_BACKTRACE=1 - # build outputs - testRoot=target/debug - mkdir -p $testRoot + # build outputs + testRoot=target/debug + mkdir -p $testRoot - # executables of the crate - # we copy to prevent std::env::current_exe() to resolve to a store location - for i in ${crate}/bin/*; do - cp "$i" "$testRoot" - done - chmod +w -R . + # executables of the crate + # we copy to prevent std::env::current_exe() to resolve to a store location + for i in ${crate}/bin/*; do + cp "$i" "$testRoot" + done + chmod +w -R . - # test harness executables are suffixed with a hash, like cargo does - # this allows to prevent name collision with the main - # executables of the crate - hash=$(basename $out) - for file in ${drv}/tests/*; do - f=$testRoot/$(basename $file)-$hash - cp $file $f - ${testCommand} - done - ''; + # test harness executables are suffixed with a hash, like cargo does + # this allows to prevent name collision with the main + # executables of the crate + hash=$(basename $out) + for file in ${drv}/tests/*; do + f=$testRoot/$(basename $file)-$hash + cp $file $f + ${testCommand} + done + ''; + }; in pkgs.runCommand "${crate.name}-linked" { diff --git a/web/tvixbolt/default.nix b/web/tvixbolt/default.nix index 33c6622717d5..a3ce1662ff52 100644 --- a/web/tvixbolt/default.nix +++ b/web/tvixbolt/default.nix @@ -27,4 +27,6 @@ in "$@" \ ${depot.web.tvixbolt} ''; + + meta.ci.extraSteps.crate2nix-check = depot.tvix.utils.mkCrate2nixCheck ./Cargo.nix; }) diff --git a/web/tvl/blog/2024-08-tvix-update.md b/web/tvl/blog/2024-08-tvix-update.md index 7307c3927a2f..5fc15c02d164 100644 --- a/web/tvl/blog/2024-08-tvix-update.md +++ b/web/tvl/blog/2024-08-tvix-update.md @@ -45,7 +45,7 @@ file from the internet, clone of a git repo). These needed to be implemented for completeness. We implemented pretty much all downloads of Tarballs, NARs and plain files, except git repositories, which are left for later. -Instead of doing these fetches immediately, we added a generic `Fetch` struct +Instead of doing these fetches immediately, we added a generic `Fetch` type that allows describing such fetches *before actually doing them*, similar to being able to describe builds, and use the same "Drive builds on IO" machinery to delay these fetches to the point where it's needed. We also show progress @@ -53,7 +53,7 @@ bars when doing fetches. Very early, during bootstrapping, nixpkgs relies on some `builtin:fetchurl` "fake" Derivation, which has some special handling logic in Nix. We implemented -these quirks, by converting it to our generic `Fetch` struct and dealing with +these quirks, by converting it to instances of our `Fetch` type and dealing with it there in a consistent fashion. ### More fixes, Refscan @@ -159,8 +159,8 @@ store backends as the rest of Tvix. We landed some fixes in [crate2nix][crate2nix], the tool we're using to for per-crate incremental builds of Tvix. -It now supports the corner cases needed to build WASM - so now [Tvixbolt] -[tvixbolt] is built with it, too. +It now supports the corner cases needed to build WASM - so now +[Tvixbolt][tvixbolt] is built with it, too. We also fixed some bugs in how test directories are prepared, which unlocked running some more tests for filesystem related builtins such as `readDir` in our test suite. |