diff --git a/Cargo.lock b/Cargo.lock index aa0ad30f33..8cab6615e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[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 = "ahash" @@ -32,13 +32,19 @@ dependencies = [ [[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 = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "anes" version = "0.1.6" @@ -56,57 +62,58 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "arbitrary" @@ -126,6 +133,12 @@ dependencies = [ "arbitrary", ] +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "archery" version = "1.2.1" @@ -143,9 +156,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "ascii-canvas" @@ -158,13 +171,14 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.0.14" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed72493ac66d5804837f480ab3766c72bdfab91a65e565fc54fa9e42db0073a8" +checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" dependencies = [ "anstyle", "bstr", "doc-comment", + "libc", "predicates", "predicates-core", "predicates-tree", @@ -177,6 +191,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -190,30 +210,36 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "beef" @@ -253,9 +279,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bitmaps" @@ -274,9 +300,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "regex-automata", @@ -291,9 +317,27 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + +[[package]] +name = "bytesize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc" [[package]] name = "cast" @@ -357,9 +401,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.2" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -367,36 +411,36 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", - "clap_lex 0.7.0", + "clap_lex 0.7.2", "strsim 0.11.1", "terminal_size", ] [[package]] name = "clap_complete" -version = "4.5.1" +version = "4.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "885e4d7d5af40bfb99ae6f9433e292feac98d452dcb3ec3d25dfe7552b77da8c" +checksum = "07a13ab5b8cb13dbe35e68b83f6c12f9293b2f601797b71bc9f23befdb329feb" dependencies = [ - "clap 4.5.2", + "clap 4.5.20", ] [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] @@ -410,9 +454,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -425,6 +469,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "clru" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" + [[package]] name = "codespan" version = "0.11.1" @@ -448,9 +498,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "comrak" @@ -458,7 +508,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a972c8ec1be8065f7b597b5f7f5b3be535db780280644aebdcd1966decf58dc" dependencies = [ - "clap 4.5.2", + "clap 4.5.20", "derive_builder", "entities", "memchr", @@ -499,29 +549,45 @@ dependencies = [ "crossterm", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "cpp_demangle" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" dependencies = [ "cfg-if", ] [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] @@ -561,7 +627,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.2", + "clap 4.5.20", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -603,9 +669,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] @@ -640,9 +706,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossterm" @@ -653,7 +719,7 @@ dependencies = [ "bitflags 1.3.2", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot", "signal-hook", "signal-hook-mio", @@ -708,9 +774,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.119" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "635179be18797d7e10edb9cd06c859580237750c7351f39ed9b298bfc17544ad" +checksum = "cbdc8cca144dce1c4981b5c9ab748761619979e515c3d53b5df385c677d1d007" dependencies = [ "cc", "cxxbridge-flags", @@ -720,41 +786,41 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.119" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9324397d262f63ef77eb795d900c0d682a34a43ac0932bec049ed73055d52f63" +checksum = "c5764c3142ab44fcf857101d12c0ddf09c34499900557c764f5ad0597159d1fc" dependencies = [ "cc", "codespan-reporting", "once_cell", - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "scratch", - "syn 2.0.52", + "syn 2.0.85", ] [[package]] name = "cxxbridge-flags" -version = "1.0.119" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a87ff7342ffaa54b7c61618e0ce2bbcf827eba6d55b923b83d82551acbbecfe5" +checksum = "d422aff542b4fa28c2ce8e5cc202d42dbf24702345c1fba3087b2d3f8a1b90ff" [[package]] name = "cxxbridge-macro" -version = "1.0.119" +version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70b5b86cf65fa0626d85720619d80b288013477a91a0389fa8bc716bf4903ad1" +checksum = "a1719100f31492cd6adeeab9a0f46cdbc846e615fdb66d7b398aa46ec7fdd06f" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", @@ -762,27 +828,41 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "strsim 0.11.1", - "syn 2.0.52", + "syn 2.0.85", ] [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", - "quote 1.0.35", - "syn 2.0.52", + "quote 1.0.37", + "syn 2.0.85", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -809,60 +889,60 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "derive_builder" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0350b5cb0331628a5916d6c5c0b72e97393b8b6b03b47a9284f4e7f5a405ffd7" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "derive_builder_macro" -version = "0.20.0" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.52", + "syn 2.0.85", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "rustc_version", - "syn 1.0.109", + "syn 2.0.85", ] [[package]] name = "deunicode" -version = "1.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6e854126756c496b8c81dec88f9a706b15b875c5849d4097a3854476b9fdf94" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" [[package]] name = "diff" @@ -933,17 +1013,23 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" -version = "1.10.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "ena" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" dependencies = [ "log", ] @@ -954,6 +1040,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + [[package]] name = "endian-type" version = "0.1.2" @@ -987,9 +1082,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1015,11 +1110,17 @@ dependencies = [ "regex", ] +[[package]] +name = "faster-hex" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" + [[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 = "fd-lock" @@ -1032,6 +1133,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "filetime" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.59.0", +] + [[package]] name = "findshlibs" version = "0.10.2" @@ -1052,9 +1165,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -1077,9 +1190,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1092,9 +1205,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1102,15 +1215,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1119,38 +1232,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1176,9 +1289,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1187,9 +1300,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git-version" @@ -1206,179 +1319,1234 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", +] + +[[package]] +name = "gix" +version = "0.63.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "984c5018adfa7a4536ade67990b3ebc6e11ab57b3d6cd9968de0947ca99b4b06" +dependencies = [ + "gix-actor", + "gix-archive", + "gix-attributes", + "gix-command", + "gix-commitgraph", + "gix-config", + "gix-credentials", + "gix-date 0.8.7", + "gix-diff", + "gix-dir", + "gix-discover", + "gix-features", + "gix-filter", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-hashtable", + "gix-ignore", + "gix-index", + "gix-lock", + "gix-macros", + "gix-mailmap", + "gix-negotiate", + "gix-object", + "gix-odb", + "gix-pack", + "gix-path", + "gix-pathspec", + "gix-prompt", + "gix-protocol", + "gix-ref", + "gix-refspec", + "gix-revision", + "gix-revwalk", + "gix-sec", + "gix-status", + "gix-submodule", + "gix-tempfile", + "gix-trace", + "gix-transport", + "gix-traverse", + "gix-url", + "gix-utils", + "gix-validate", + "gix-worktree", + "gix-worktree-state", + "gix-worktree-stream", + "once_cell", + "parking_lot", + "regex", + "signal-hook", + "smallvec", + "thiserror", ] [[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "half" -version = "2.4.0" +name = "gix-actor" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +checksum = "a0e454357e34b833cc3a00b6efbbd3dd4d18b24b9fb0c023876ec2645e8aa3f2" dependencies = [ - "cfg-if", - "crunchy", + "bstr", + "gix-date 0.8.7", + "gix-utils", + "itoa", + "thiserror", + "winnow", ] [[package]] -name = "hashbrown" -version = "0.12.3" +name = "gix-archive" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "63b6bbebdf0223d1d4a69d6027e8b2482daad8eb1a8d3ec97176c7ec58e796d4" +dependencies = [ + "bstr", + "gix-date 0.8.7", + "gix-object", + "gix-worktree-stream", + "thiserror", +] [[package]] -name = "hashbrown" -version = "0.13.1" +name = "gix-attributes" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +checksum = "ebccbf25aa4a973dd352564a9000af69edca90623e8a16dad9cbc03713131311" dependencies = [ - "ahash", + "bstr", + "gix-glob", + "gix-path", + "gix-quote", + "gix-trace", + "kstring", + "smallvec", + "thiserror", + "unicode-bom", ] [[package]] -name = "hashbrown" -version = "0.14.3" +name = "gix-bitmap" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "10f78312288bd02052be5dbc2ecbc342c9f4eb791986d86c0a5c06b92dc72efa" dependencies = [ - "ahash", + "thiserror", ] [[package]] -name = "heck" -version = "0.4.1" +name = "gix-chunk" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "6c28b58ba04f0c004722344390af9dbc85888fbb84be1981afb934da4114d4cf" +dependencies = [ + "thiserror", +] [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "gix-command" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +checksum = "c201d2b9e9cce2365a6638fd0a966f751ed92d74be5c0727ac331e6a29ef5846" dependencies = [ - "libc", + "bstr", + "gix-path", + "gix-trace", + "shell-words", ] [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "gix-commitgraph" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "133b06f67f565836ec0c473e2116a60fb74f80b6435e21d88013ac0e3c60fc78" +dependencies = [ + "bstr", + "gix-chunk", + "gix-features", + "gix-hash", + "memmap2 0.9.5", + "thiserror", +] [[package]] -name = "humantime" -version = "2.1.0" +name = "gix-config" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "53fafe42957e11d98e354a66b6bd70aeea00faf2f62dd11164188224a507c840" +dependencies = [ + "bstr", + "gix-config-value", + "gix-features", + "gix-glob", + "gix-path", + "gix-ref", + "gix-sec", + "memchr", + "once_cell", + "smallvec", + "thiserror", + "unicode-bom", + "winnow", +] [[package]] -name = "ident_case" -version = "1.0.1" +name = "gix-config-value" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +checksum = "f3de3fdca9c75fa4b83a76583d265fa49b1de6b088ebcd210749c24ceeb74660" +dependencies = [ + "bitflags 2.6.0", + "bstr", + "gix-path", + "libc", + "thiserror", +] [[package]] -name = "idna" -version = "0.5.0" +name = "gix-credentials" +version = "0.24.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "8ce391d305968782f1ae301c4a3d42c5701df7ff1d8bc03740300f6fd12bce78" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "bstr", + "gix-command", + "gix-config-value", + "gix-path", + "gix-prompt", + "gix-sec", + "gix-trace", + "gix-url", + "thiserror", ] [[package]] -name = "imbl-sized-chunks" -version = "0.1.2" +name = "gix-date" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" +checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0" dependencies = [ - "bitmaps", + "bstr", + "itoa", + "thiserror", + "time", ] [[package]] -name = "indexmap" -version = "1.9.3" +name = "gix-date" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "d10d543ac13c97292a15e8e8b7889cd006faf739777437ed95362504b8fe81a0" dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", + "bstr", + "itoa", + "jiff", + "thiserror", ] [[package]] -name = "indexmap" -version = "2.2.5" +name = "gix-diff" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "1996d5c8a305b59709467d80617c9fde48d9d75fd1f4179ea970912630886c9d" dependencies = [ - "equivalent", - "hashbrown 0.14.3", + "bstr", + "gix-command", + "gix-filter", + "gix-fs", + "gix-hash", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-trace", + "gix-worktree", + "imara-diff", + "thiserror", ] [[package]] -name = "indoc" -version = "1.0.9" +name = "gix-dir" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "60c99f8c545abd63abe541d20ab6cda347de406c0a3f1c80aadc12d9b0e94974" +dependencies = [ + "bstr", + "gix-discover", + "gix-fs", + "gix-ignore", + "gix-index", + "gix-object", + "gix-path", + "gix-pathspec", + "gix-trace", + "gix-utils", + "gix-worktree", + "thiserror", +] [[package]] -name = "indoc" -version = "2.0.4" +name = "gix-discover" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" +checksum = "fc27c699b63da66b50d50c00668bc0b7e90c3a382ef302865e891559935f3dbf" +dependencies = [ + "bstr", + "dunce", + "gix-fs", + "gix-hash", + "gix-path", + "gix-ref", + "gix-sec", + "thiserror", +] [[package]] -name = "inferno" -version = "0.11.19" +name = "gix-features" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" +checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" dependencies = [ - "ahash", - "indexmap 2.2.5", - "is-terminal", - "itoa", - "log", - "num-format", + "bytes", + "bytesize", + "crc32fast", + "crossbeam-channel", + "flate2", + "gix-hash", + "gix-trace", + "gix-utils", + "jwalk", + "libc", "once_cell", - "quick-xml 0.26.0", - "rgb", - "str_stack", + "parking_lot", + "prodash", + "sha1_smol", + "thiserror", + "walkdir", ] [[package]] -name = "insta" -version = "1.36.1" +name = "gix-filter" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +checksum = "e6547738da28275f4dff4e9f3a0f28509f53f94dd6bd822733c91cb306bca61a" dependencies = [ - "console", - "lazy_static", - "linked-hash-map", - "regex", - "similar", - "yaml-rust", + "bstr", + "encoding_rs", + "gix-attributes", + "gix-command", + "gix-hash", + "gix-object", + "gix-packetline-blocking", + "gix-path", + "gix-quote", + "gix-trace", + "gix-utils", + "smallvec", + "thiserror", ] [[package]] -name = "is-terminal" -version = "0.4.12" +name = "gix-fs" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bfe6249cfea6d0c0e0990d5226a4cb36f030444ba9e35e0639275db8f98575" +dependencies = [ + "fastrand", + "gix-features", + "gix-utils", +] + +[[package]] +name = "gix-glob" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74908b4bbc0a0a40852737e5d7889f676f081e340d5451a16e5b4c50d592f111" +dependencies = [ + "bitflags 2.6.0", + "bstr", + "gix-features", + "gix-path", +] + +[[package]] +name = "gix-hash" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" +dependencies = [ + "faster-hex", + "thiserror", +] + +[[package]] +name = "gix-hashtable" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" +dependencies = [ + "gix-hash", + "hashbrown 0.14.5", + "parking_lot", +] + +[[package]] +name = "gix-ignore" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e447cd96598460f5906a0f6c75e950a39f98c2705fc755ad2f2020c9e937fab7" +dependencies = [ + "bstr", + "gix-glob", + "gix-path", + "gix-trace", + "unicode-bom", +] + +[[package]] +name = "gix-index" +version = "0.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a9a44eb55bd84bb48f8a44980e951968ced21e171b22d115d1cdcef82a7d73f" +dependencies = [ + "bitflags 2.6.0", + "bstr", + "filetime", + "fnv", + "gix-bitmap", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-traverse", + "gix-utils", + "gix-validate", + "hashbrown 0.14.5", + "itoa", + "libc", + "memmap2 0.9.5", + "rustix", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-lock" +version = "14.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" +dependencies = [ + "gix-tempfile", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-macros" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17" +dependencies = [ + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", +] + +[[package]] +name = "gix-mailmap" +version = "0.23.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6daca6edb6a590c7c0533f3f8e75c54663eb56ce08f46f0891db9fc6f09208" +dependencies = [ + "bstr", + "gix-actor", + "gix-date 0.8.7", + "thiserror", +] + +[[package]] +name = "gix-negotiate" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ec879fb6307bb63519ba89be0024c6f61b4b9d61f1a91fd2ce572d89fe9c224" +dependencies = [ + "bitflags 2.6.0", + "gix-commitgraph", + "gix-date 0.8.7", + "gix-hash", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-object" +version = "0.42.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25da2f46b4e7c2fa7b413ce4dffb87f69eaf89c2057e386491f4c55cadbfe386" +dependencies = [ + "bstr", + "gix-actor", + "gix-date 0.8.7", + "gix-features", + "gix-hash", + "gix-utils", + "gix-validate", + "itoa", + "smallvec", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-odb" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d384fe541d93d8a3bb7d5d5ef210780d6df4f50c4e684ccba32665a5e3bc9b" +dependencies = [ + "arc-swap", + "gix-date 0.8.7", + "gix-features", + "gix-fs", + "gix-hash", + "gix-object", + "gix-pack", + "gix-path", + "gix-quote", + "parking_lot", + "tempfile", + "thiserror", +] + +[[package]] +name = "gix-pack" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0594491fffe55df94ba1c111a6566b7f56b3f8d2e1efc750e77d572f5f5229" +dependencies = [ + "clru", + "gix-chunk", + "gix-features", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-path", + "gix-tempfile", + "memmap2 0.9.5", + "parking_lot", + "smallvec", + "thiserror", + "uluru", +] + +[[package]] +name = "gix-packetline" +version = "0.17.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c43ef4d5fe2fa222c606731c8bdbf4481413ee4ef46d61340ec39e4df4c5e49" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror", +] + +[[package]] +name = "gix-packetline-blocking" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9802304baa798dd6f5ff8008a2b6516d54b74a69ca2d3a2b9e2d6c3b5556b40" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror", +] + +[[package]] +name = "gix-path" +version = "0.10.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c04e5a94fdb56b1e91eb7df2658ad16832428b8eeda24ff1a0f0288de2bce554" +dependencies = [ + "bstr", + "gix-trace", + "home", + "once_cell", + "thiserror", +] + +[[package]] +name = "gix-pathspec" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d23bf239532b4414d0e63b8ab3a65481881f7237ed9647bb10c1e3cc54c5ceb" +dependencies = [ + "bitflags 2.6.0", + "bstr", + "gix-attributes", + "gix-config-value", + "gix-glob", + "gix-path", + "thiserror", +] + +[[package]] +name = "gix-prompt" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57944bbdb87f7a9893907032276e99ff4eba3640d8db1bdfb1eba8c07edfd006" +dependencies = [ + "gix-command", + "gix-config-value", + "parking_lot", + "rustix", + "thiserror", +] + +[[package]] +name = "gix-protocol" +version = "0.45.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc43a1006f01b5efee22a003928c9eb83dde2f52779ded9d4c0732ad93164e3e" +dependencies = [ + "bstr", + "gix-credentials", + "gix-date 0.9.1", + "gix-features", + "gix-hash", + "gix-transport", + "gix-utils", + "maybe-async", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-quote" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89f9a1525dcfd9639e282ea939f5ab0d09d93cf2b90c1fc6104f1b9582a8e49" +dependencies = [ + "bstr", + "gix-utils", + "thiserror", +] + +[[package]] +name = "gix-ref" +version = "0.44.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3394a2997e5bc6b22ebc1e1a87b41eeefbcfcff3dbfa7c4bd73cb0ac8f1f3e2e" +dependencies = [ + "gix-actor", + "gix-date 0.8.7", + "gix-features", + "gix-fs", + "gix-hash", + "gix-lock", + "gix-object", + "gix-path", + "gix-tempfile", + "gix-utils", + "gix-validate", + "memmap2 0.9.5", + "thiserror", + "winnow", +] + +[[package]] +name = "gix-refspec" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6868f8cd2e62555d1f7c78b784bece43ace40dd2a462daf3b588d5416e603f37" +dependencies = [ + "bstr", + "gix-hash", + "gix-revision", + "gix-validate", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-revision" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b13e43c2118c4b0537ddac7d0821ae0dfa90b7b8dbf20c711e153fb749adce" +dependencies = [ + "bstr", + "gix-date 0.8.7", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "gix-trace", + "thiserror", +] + +[[package]] +name = "gix-revwalk" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b030ccaab71af141f537e0225f19b9e74f25fefdba0372246b844491cab43e0" +dependencies = [ + "gix-commitgraph", + "gix-date 0.8.7", + "gix-hash", + "gix-hashtable", + "gix-object", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-sec" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2007538eda296445c07949cf04f4a767307d887184d6b3e83e2d636533ddc6e" +dependencies = [ + "bitflags 2.6.0", + "gix-path", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "gix-status" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4373d989713809554d136f51bc7da565adf45c91aa4d86ef6a79801621bfc8" +dependencies = [ + "bstr", + "filetime", + "gix-diff", + "gix-dir", + "gix-features", + "gix-filter", + "gix-fs", + "gix-hash", + "gix-index", + "gix-object", + "gix-path", + "gix-pathspec", + "gix-worktree", + "thiserror", +] + +[[package]] +name = "gix-submodule" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921cd49924ac14b6611b22e5fb7bbba74d8780dc7ad26153304b64d1272460ac" +dependencies = [ + "bstr", + "gix-config", + "gix-path", + "gix-pathspec", + "gix-refspec", + "gix-url", + "thiserror", +] + +[[package]] +name = "gix-tempfile" +version = "14.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046b4927969fa816a150a0cda2e62c80016fe11fb3c3184e4dddf4e542f108aa" +dependencies = [ + "dashmap", + "gix-fs", + "libc", + "once_cell", + "parking_lot", + "signal-hook", + "signal-hook-registry", + "tempfile", +] + +[[package]] +name = "gix-trace" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04bdde120c29f1fc23a24d3e115aeeea3d60d8e65bab92cc5f9d90d9302eb952" + +[[package]] +name = "gix-transport" +version = "0.42.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "421dcccab01b41a15d97b226ad97a8f9262295044e34fbd37b10e493b0a6481f" +dependencies = [ + "base64", + "bstr", + "gix-command", + "gix-credentials", + "gix-features", + "gix-packetline", + "gix-quote", + "gix-sec", + "gix-url", + "reqwest", + "thiserror", +] + +[[package]] +name = "gix-traverse" +version = "0.39.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e499a18c511e71cf4a20413b743b9f5bcf64b3d9e81e9c3c6cd399eae55a8840" +dependencies = [ + "bitflags 2.6.0", + "gix-commitgraph", + "gix-date 0.8.7", + "gix-hash", + "gix-hashtable", + "gix-object", + "gix-revwalk", + "smallvec", + "thiserror", +] + +[[package]] +name = "gix-url" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd280c5e84fb22e128ed2a053a0daeacb6379469be6a85e3d518a0636e160c89" +dependencies = [ + "bstr", + "gix-features", + "gix-path", + "home", + "thiserror", + "url", +] + +[[package]] +name = "gix-utils" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba427e3e9599508ed98a6ddf8ed05493db114564e338e41f6a996d2e4790335f" +dependencies = [ + "bstr", + "fastrand", + "unicode-normalization", +] + +[[package]] +name = "gix-validate" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf" +dependencies = [ + "bstr", + "thiserror", +] + +[[package]] +name = "gix-worktree" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26f7326ebe0b9172220694ea69d344c536009a9b98fb0f9de092c440f3efe7a6" +dependencies = [ + "bstr", + "gix-attributes", + "gix-features", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-ignore", + "gix-index", + "gix-object", + "gix-path", + "gix-validate", +] + +[[package]] +name = "gix-worktree-state" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ed6205b5f51067a485b11843babcf3304c0799e265a06eb0dde7f69cd85cd8" +dependencies = [ + "bstr", + "gix-features", + "gix-filter", + "gix-fs", + "gix-glob", + "gix-hash", + "gix-index", + "gix-object", + "gix-path", + "gix-worktree", + "io-close", + "thiserror", +] + +[[package]] +name = "gix-worktree-stream" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35d4896249a41856f44571d94d7583b9f3b9cd1a75eaef4f34a4aa2981bed21" +dependencies = [ + "gix-attributes", + "gix-features", + "gix-filter", + "gix-fs", + "gix-hash", + "gix-object", + "gix-path", + "gix-traverse", + "parking_lot", + "thiserror", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.6.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[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.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "human_format" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c3b1f728c459d27b12448862017b96ad4767b1ec2ec5e6434e99f1577f085b8" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "imara-diff" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc9da1a252bd44cd341657203722352efc9bc0c847d06ea6d2dc1cd1135e0a01" +dependencies = [ + "ahash", + "hashbrown 0.14.5", +] + +[[package]] +name = "imbl-sized-chunks" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" dependencies = [ - "hermit-abi 0.3.9", + "bitmaps", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "indoc" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" + +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + +[[package]] +name = "inferno" +version = "0.11.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" +dependencies = [ + "ahash", + "indexmap 2.6.0", + "is-terminal", + "itoa", + "log", + "num-format", + "once_cell", + "quick-xml 0.26.0", + "rgb", + "str_stack", +] + +[[package]] +name = "insta" +version = "1.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f72d3e19488cf7d8ea52d2fc0f8754fc933398b337cd3cbdb28aaeb35159ef" +dependencies = [ + "console", + "lazy_static", + "linked-hash-map", + "regex", + "similar", +] + +[[package]] +name = "io-close" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi 0.4.0", "libc", "windows-sys 0.52.0", ] +[[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" @@ -1399,9 +2567,34 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jiff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a45489186a6123c128fdf6016183fcfab7113e1820eb813127e036e287233fb" +dependencies = [ + "jiff-tzdb-platform", + "windows-sys 0.59.0", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +dependencies = [ + "jiff-tzdb", +] [[package]] name = "js-sys" @@ -1412,6 +2605,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2735847566356cd2179a2a38264839308f7079fa96e6bd5a42d740460e003c56" +dependencies = [ + "crossbeam", + "rayon", +] + +[[package]] +name = "kstring" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" +dependencies = [ + "static_assertions", +] + [[package]] name = "lalrpop" version = "0.20.2" @@ -1430,7 +2642,7 @@ dependencies = [ "string_cache", "term", "tiny-keccak", - "unicode-xid 0.2.4", + "unicode-xid 0.2.6", "walkdir", ] @@ -1445,42 +2657,33 @@ 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.153" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "3bda4c6077b0b08da2c48b172195795498381a7c8988c9e6212a6c55c5b9bd70" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "libc", "redox_syscall", ] -[[package]] -name = "line-wrap" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] - [[package]] name = "link-cplusplus" version = "1.0.9" @@ -1498,15 +2701,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[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 = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1514,9 +2717,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "logos" @@ -1535,8 +2738,8 @@ checksum = "a1d849148dbaf9661a6151d1ca82b13bb4c4c128146a88d05253b38d4e2f496c" dependencies = [ "beef", "fnv", - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "regex-syntax 0.6.29", "syn 1.0.109", ] @@ -1561,9 +2764,9 @@ dependencies = [ [[package]] name = "lsp-server" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248f65b78f6db5d8e1b1604b4098a28b43d21a8eb1deeca22b1c421b276c7095" +checksum = "550446e84739dcaf6d48a4a093973850669e13e8a34d8f8d64851041be267cd9" dependencies = [ "crossbeam-channel", "log", @@ -1573,9 +2776,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.95.0" +version = "0.95.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984" +checksum = "8e34d33a8e9b006cd3fc4fe69a921affa097bae4bb65f76271f4644f9a334365" dependencies = [ "bitflags 1.3.2", "serde", @@ -1595,9 +2798,9 @@ dependencies = [ [[package]] name = "malachite" -version = "0.4.5" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53ff327de42075f680ba15c5cb3c417687eb7241ce2063a91d0186ce5c5e77ee" +checksum = "5616515d632967cd329b6f6db96be9a03ea0b3a49cdbc45b0016803dad8a77b7" dependencies = [ "malachite-base", "malachite-float", @@ -1607,11 +2810,11 @@ dependencies = [ [[package]] name = "malachite-base" -version = "0.4.5" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e960ee0e7e1b8eec9229f5b20d6b191762574225144ea638eb961d065c97b55d" +checksum = "46059721011b0458b7bd6d9179be5d0b60294281c23320c207adceaecc54d13b" dependencies = [ - "hashbrown 0.14.3", + "hashbrown 0.14.5", "itertools 0.11.0", "libm", "ryu", @@ -1619,9 +2822,9 @@ dependencies = [ [[package]] name = "malachite-float" -version = "0.4.5" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd21e0e005798917fb37c87ef9b0787e3ad490b378df987b78dfa44669b895fe" +checksum = "a9bfda4e3628f09bf7c42242d590b5d0cc04ff0a29c820d81e9afa25db7b089e" dependencies = [ "itertools 0.11.0", "malachite-base", @@ -1632,9 +2835,9 @@ dependencies = [ [[package]] name = "malachite-nz" -version = "0.4.5" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770aaf1a4d59a82ed3d8644eb66aff7492a6dd7476def275a922d04d77ca8e57" +checksum = "1503b27e825cabd1c3d0ff1e95a39fb2ec9eab6fd3da6cfa41aec7091d273e78" dependencies = [ "itertools 0.11.0", "libm", @@ -1644,9 +2847,9 @@ dependencies = [ [[package]] name = "malachite-q" -version = "0.4.5" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a9dfca114f6b582595990ccfc287cace633aa95f890ade5b1fc099b7175d3b" +checksum = "a475503a70a3679dbe3b9b230a23622516742528ba614a7b2490f180ea9cb514" dependencies = [ "itertools 0.11.0", "malachite-base", @@ -1654,6 +2857,17 @@ dependencies = [ "serde", ] +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", +] + [[package]] name = "md-5" version = "0.10.6" @@ -1666,9 +2880,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1679,6 +2893,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.6.5" @@ -1705,9 +2928,9 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b4faf00617defe497754acde3024865bc143d44a86799b24e191ecff91354f" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] @@ -1729,6 +2952,12 @@ dependencies = [ "sketches-ddsketch", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimad" version = "0.12.0" @@ -1740,11 +2969,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -1759,11 +2988,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nibble_vec" @@ -1778,7 +3019,7 @@ dependencies = [ name = "nickel-lang-cli" version = "1.8.0" dependencies = [ - "clap 4.5.2", + "clap 4.5.20", "clap_complete", "comrak", "directories", @@ -1787,9 +3028,11 @@ dependencies = [ "metrics", "metrics-util", "nickel-lang-core", + "nickel-lang-package", "nickel-lang-utils", "once_cell", "regex", + "semver", "serde", "serde_json", "tempfile", @@ -1802,16 +3045,18 @@ version = "0.9.0" dependencies = [ "ansi_term", "assert_matches", + "base16", "bumpalo", - "clap 4.5.2", + "clap 4.5.20", "codespan", "codespan-reporting", "comrak", "criterion 0.4.0", "cxx", "cxx-build", + "directories", "indexmap 1.9.3", - "indoc 2.0.4", + "indoc 2.0.5", "js-sys", "lalrpop", "lalrpop-util", @@ -1862,7 +3107,7 @@ dependencies = [ "assert_cmd", "assert_matches", "bincode", - "clap 4.5.2", + "clap 4.5.20", "codespan", "codespan-reporting", "criterion 0.4.0", @@ -1892,6 +3137,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nickel-lang-package" +version = "0.1.0" +dependencies = [ + "anyhow", + "directories", + "gix", + "nickel-lang-core", + "pubgrub", + "semver", + "serde", + "serde_json", + "tempfile", +] + [[package]] name = "nickel-lang-utils" version = "0.1.0" @@ -1946,15 +3206,15 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.6", "itoa", ] [[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", ] @@ -1969,20 +3229,29 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "onig" @@ -2008,9 +3277,9 @@ dependencies = [ [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "ordered-float" @@ -2038,9 +3307,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -2048,15 +3317,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2067,12 +3336,12 @@ 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.2.5", + "indexmap 2.6.0", ] [[package]] @@ -2092,9 +3361,9 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2104,29 +3373,28 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[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", - "indexmap 2.2.5", - "line-wrap", - "quick-xml 0.31.0", + "indexmap 2.6.0", + "quick-xml 0.32.0", "serde", "time", ] [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -2137,24 +3405,24 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -2184,6 +3452,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -2192,9 +3469,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", @@ -2203,15 +3480,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -2231,9 +3508,9 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" dependencies = [ "diff", "yansi", @@ -2260,13 +3537,33 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] +[[package]] +name = "prodash" +version = "28.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" +dependencies = [ + "bytesize", + "human_format", +] + +[[package]] +name = "pubgrub" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd14552ad5f5d743a323c10d576f26822a044355d6601f377d813ece46f38fd" +dependencies = [ + "rustc-hash 1.1.0", + "thiserror", +] + [[package]] name = "pyckel" version = "1.8.0" @@ -2320,9 +3617,9 @@ version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94144a1266e236b1c932682136dc35a9dee8d3589728f68130c7c3861ef96b28" dependencies = [ - "proc-macro2 1.0.78", + "proc-macro2 1.0.89", "pyo3-macros-backend", - "quote 1.0.35", + "quote 1.0.37", "syn 1.0.109", ] @@ -2332,8 +3629,8 @@ version = "0.17.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8df9be978a2d2f0cdebabb03206ed73b11314701a5bfe71b0d753b81997777f" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "syn 1.0.109", ] @@ -2364,13 +3661,61 @@ dependencies = [ [[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 = "quinn" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.0.0", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash 2.0.0", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "0.6.13" @@ -2382,21 +3727,51 @@ 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 1.0.78", + "proc-macro2 1.0.89", ] [[package]] name = "radix_trie" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[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 = [ - "endian-type", - "nibble_vec", + "getrandom", ] [[package]] @@ -2410,9 +3785,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2430,18 +3805,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", @@ -2483,15 +3858,76 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "windows-registry", +] + [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" dependencies = [ "bytemuck", ] +[[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", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rpds" version = "1.1.0" @@ -2503,37 +3939,89 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" [[package]] name = "rustyline" @@ -2564,22 +4052,16 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8218eaf5d960e3c478a1b0f129fa888dd3d8d22eb3de097e9af14c1ab4438024" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "syn 1.0.109", ] [[package]] name = "ryu" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" - -[[package]] -name = "safemem" -version = "0.3.3" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2604,15 +4086,18 @@ checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "serde" -version = "1.0.197" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] @@ -2630,53 +4115,66 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" +checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ + "form_urlencoded", + "itoa", + "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -2694,6 +4192,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + [[package]] name = "sha2" version = "0.10.8" @@ -2729,29 +4233,29 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "similar" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" +checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "simple-counter" @@ -2782,9 +4286,9 @@ dependencies = [ [[package]] name = "slug" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4" +checksum = "882a80f72ee45de3cc9a5afeb2da0331d58df69e4e7d8eeb5d3c7784ae67e724" dependencies = [ "deunicode", "wasm-bindgen", @@ -2796,12 +4300,34 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "str-buf" version = "1.0.6" @@ -2848,6 +4374,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "symbolic-common" version = "10.2.1" @@ -2855,7 +4387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b55cdc318ede251d0957f07afe5fed912119b8c1bc5a7804151826db999e737" dependencies = [ "debugid", - "memmap2", + "memmap2 0.5.10", "stable_deref_trait", "uuid", ] @@ -2888,22 +4420,31 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.52" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] + [[package]] name = "syntect" version = "5.2.0" @@ -2927,22 +4468,44 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" -version = "3.10.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2981,12 +4544,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" +checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef" dependencies = [ "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3015,33 +4578,35 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] [[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", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -3056,9 +4621,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", @@ -3100,31 +4665,60 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.36.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", + "bytes", + "libc", + "mio 1.0.2", "pin-project-lite", + "socket2", "tokio-macros", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", ] [[package]] name = "toml" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -3134,20 +4728,20 @@ 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", ] [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.6.0", "serde", "serde_spanned", "toml_datetime", @@ -3203,6 +4797,31 @@ dependencies = [ "web-sys", ] +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[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 = "tree-sitter" version = "0.22.6" @@ -3225,9 +4844,15 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.13" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" + +[[package]] +name = "try-lock" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6631e42e10b40c0690bf92f404ebcfe6e1fdb480391d15f17cc8e96eeed5369" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typed-arena" @@ -3241,38 +4866,53 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "uluru" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c8a2469e56e6e5095c82ccd3afb98dad95f7af7929aab6d8ba8d6e0f73657da" +dependencies = [ + "arrayvec 0.7.6", +] + [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-bom" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" @@ -3282,9 +4922,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unicode_categories" @@ -3300,15 +4940,21 @@ checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +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", @@ -3318,21 +4964,21 @@ 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 = "uuid" -version = "1.7.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[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 = "void" @@ -3352,12 +4998,12 @@ dependencies = [ [[package]] name = "vte_generate_state_changes" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", + "proc-macro2 1.0.89", + "quote 1.0.37", ] [[package]] @@ -3379,6 +5025,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -3406,9 +5061,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -3430,7 +5085,7 @@ version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed" dependencies = [ - "quote 1.0.35", + "quote 1.0.37", "wasm-bindgen-macro-support", ] @@ -3440,9 +5095,9 @@ version = "0.2.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3463,6 +5118,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3481,11 +5145,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]] @@ -3494,6 +5158,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "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", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3509,7 +5203,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "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]] @@ -3529,17 +5232,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "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]] @@ -3550,9 +5254,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3562,9 +5266,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3574,9 +5278,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +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" @@ -3586,9 +5296,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3598,9 +5308,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3610,9 +5320,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3622,15 +5332,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.11" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3652,26 +5362,33 @@ dependencies = [ [[package]] name = "yansi" -version = "0.5.1" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.52", + "proc-macro2 1.0.89", + "quote 1.0.37", + "syn 2.0.85", ] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml index 0074a844f5..93a68e374d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "vector", "lsp/nls", "lsp/lsp-harness", + "package", "utils", "wasm-repl", "pyckel", @@ -23,6 +24,7 @@ readme = "README.md" [workspace.dependencies] nickel-lang-core = { version = "0.9.0", path = "./core", default-features = false } +nickel-lang-package = { version = "0.1.0", path = "./package" } nickel-lang-vector = { version = "0.1.0", path = "./vector" } nickel-lang-utils = { version = "0.1.0", path = "./utils" } lsp-harness = { version = "0.1.0", path = "./lsp/lsp-harness" } @@ -39,6 +41,7 @@ ansi_term = "0.12" anyhow = "1.0" assert_cmd = "2.0.11" assert_matches = "1.5.0" +base16 = "0.2.1" bincode = "1.3.3" clap = "4.3" clap_complete = "4.3.2" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index d9a0b0fc0f..1180318d8a 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -24,6 +24,7 @@ metrics = ["dep:metrics", "dep:metrics-util", "nickel-lang-core/metrics"] [dependencies] nickel-lang-core = { workspace = true, features = [ "markdown" ], default-features = false } +nickel-lang-package.workspace = true clap = { workspace = true, features = ["derive", "string"] } serde = { workspace = true, features = ["derive"] } @@ -37,6 +38,7 @@ clap_complete = { workspace = true } metrics = { workspace = true, optional = true } metrics-util = { workspace = true, optional = true } +semver = { version = "1.0.23", features = ["serde"] } comrak = { workspace = true, optional = true } once_cell.workspace = true diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 80a49ea18a..ed034e9939 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -4,7 +4,8 @@ use git_version::git_version; use crate::{ completions::GenCompletionsCommand, eval::EvalCommand, export::ExportCommand, - pprint_ast::PprintAstCommand, query::QueryCommand, typecheck::TypecheckCommand, + package::PackageCommand, pprint_ast::PprintAstCommand, query::QueryCommand, + typecheck::TypecheckCommand, }; use nickel_lang_core::error::report::ErrorFormat; @@ -74,6 +75,8 @@ pub enum Command { Query(QueryCommand), /// Typechecks the program but does not run it Typecheck(TypecheckCommand), + /// Handle nickel packages + Package(PackageCommand), /// Starts a REPL session #[cfg(feature = "repl")] Repl(ReplCommand), diff --git a/cli/src/error.rs b/cli/src/error.rs index f2ec8e576b..b48da6390d 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -54,6 +54,14 @@ pub enum Error { program: Program, error: CliUsageError, }, + NoManifest, + /// The provided manifest path doesn't have a parent directory. + NoPackageRoot { + manifest_path: std::path::PathBuf, + }, + Package { + error: nickel_lang_package::error::Error, + }, /// Not an actual failure but a special early return to indicate that information was printed /// during the usage of the customize mode, because a subcommand such as `list`, `show`, etc. /// was used, and thus no customized program can be returned. @@ -187,6 +195,12 @@ impl From for Error { } } +impl From for Error { + fn from(error: nickel_lang_package::error::Error) -> Self { + Error::Package { error } + } +} + #[cfg(feature = "format")] impl From for Error { fn from(error: crate::format::FormatError) -> Self { @@ -256,6 +270,32 @@ impl Error { Error::CustomizeInfoPrinted => { // Nothing to do, the caller should simply exit. } + Error::NoManifest => report_standalone("failed to find a manifest file", None), + Error::Package { error } => { + if let nickel_lang_package::error::Error::ManifestEval { + package, + mut program, + error, + } = error + { + let msg = if let Some(package) = package { + format!("failed to evaluate manifest file for package {package}") + } else { + "failed to evaluate package manifest".to_owned() + }; + report_standalone(&msg, None); + program.report(error, format) + } else { + report_standalone("failed to read manifest file", Some(error.to_string())) + } + } + Error::NoPackageRoot { manifest_path } => report_standalone( + &format!( + "invalid manifest path `{}` has no parent", + manifest_path.display() + ), + None, + ), } } } diff --git a/cli/src/input.rs b/cli/src/input.rs index 58605071de..2266264b55 100644 --- a/cli/src/input.rs +++ b/cli/src/input.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use nickel_lang_core::{eval::cache::lazy::CBNCache, program::Program}; +use nickel_lang_package::ManifestFile; use crate::{cli::GlobalOptions, customize::Customize, error::CliResult}; @@ -24,6 +25,9 @@ pub struct InputOptions { #[arg(long, short = 'I', global = true)] pub import_path: Vec, + #[arg(long, global = true)] + pub manifest_path: Option, + #[command(flatten)] pub customize_mode: Customize, } @@ -48,6 +52,21 @@ impl Prepare for InputOptions { program.add_import_paths(nickel_path.split(':')); } + if let Some(manifest_path) = self.manifest_path.as_ref() { + let manifest = ManifestFile::from_path(manifest_path)?; + let resolution = manifest.resolve()?; + for (pkg_id, versions) in &resolution.package_map { + for v in versions { + resolution + .index + .ensure_downloaded(pkg_id, v.clone()) + .unwrap(); + } + } + let package_map = resolution.package_map(&manifest)?; + program.set_package_map(package_map); + } + #[cfg(debug_assertions)] if self.nostdlib { program.set_skip_stdlib(); diff --git a/cli/src/main.rs b/cli/src/main.rs index 387c32c0de..8f9d28f102 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -18,6 +18,7 @@ mod error; mod eval; mod export; mod input; +mod package; mod pprint_ast; mod query; mod typecheck; @@ -44,6 +45,7 @@ fn main() -> ExitCode { Command::Query(query) => query.run(opts.global), Command::Typecheck(typecheck) => typecheck.run(opts.global), Command::GenCompletions(completions) => completions.run(opts.global), + Command::Package(package) => package.run(opts.global), #[cfg(feature = "repl")] Command::Repl(repl) => repl.run(opts.global), diff --git a/cli/src/package.rs b/cli/src/package.rs new file mode 100644 index 0000000000..b26f86164e --- /dev/null +++ b/cli/src/package.rs @@ -0,0 +1,132 @@ +use std::{ + collections::HashMap, + env::current_dir, + path::{Path, PathBuf}, +}; + +use nickel_lang_core::{identifier::Ident, package::PackageMap}; +use nickel_lang_package::{index::PackageIndex, ManifestFile}; + +use crate::{ + cli::GlobalOptions, + error::{CliResult, Error}, +}; + +#[derive(clap::Subcommand, Debug)] +pub enum Command { + GenerateLockfile, + DebugResolution, + RefreshIndex, + Publish { + #[arg(long)] + index: PathBuf, + + #[arg(long)] + // TODO: make this an index::Id and have clap use FromStr somehow + package_id: String, + }, +} + +#[derive(clap::Parser, Debug)] +pub struct PackageCommand { + #[command(subcommand)] + pub command: Command, + + #[arg(long, global = true)] + pub manifest_path: Option, +} + +impl PackageCommand { + fn find_manifest(&self) -> CliResult { + match &self.manifest_path { + Some(p) => Ok(p.clone()), + None => { + let mut dir = current_dir()?; + + loop { + let path = dir.join("package.ncl"); + if path.is_file() { + return Ok(path); + } + + if !dir.pop() { + return Err(Error::NoManifest); + } + } + } + } + } + + fn load_manifest(&self) -> CliResult { + Ok(ManifestFile::from_path(self.find_manifest()?)?) + } + + pub fn run(self, _global: GlobalOptions) -> CliResult<()> { + match &self.command { + Command::GenerateLockfile => { + self.load_manifest()?.regenerate_lock()?; + } + Command::DebugResolution => { + let path = self.find_manifest()?; + let manifest = ManifestFile::from_path(path.clone())?; + let resolution = manifest.resolve()?; + let package_map = resolution.package_map(&manifest)?; + print_package_map(&package_map); + } + Command::Publish { index, package_id } => { + let id = package_id.parse().unwrap(); + let package_file = nickel_lang_package::index::scrape::scrape(&id).unwrap(); + dbg!(&package_file); + let mut package_index = PackageIndex::new_with_root(index.clone()); + // TODO: check for conflicts between the new thing and what's already in the index + for pkg in package_file.packages.into_values() { + package_index.save(pkg); + } + } + Command::RefreshIndex => { + let index = PackageIndex::new(); + index.refresh_from_github(); + } + } + + Ok(()) + } +} + +fn print_package_map(map: &PackageMap) { + let mut by_parent: HashMap<&Path, Vec<(Ident, &Path)>> = HashMap::new(); + for ((parent, name), child) in &map.packages { + by_parent + .entry(parent.as_path()) + .or_default() + .push((*name, child)); + } + + if map.top_level.is_empty() { + eprintln!("No top-level dependencies"); + } else { + eprintln!("Top-level dependencies:"); + let mut top_level = map.top_level.iter().collect::>(); + top_level.sort(); + for (name, path) in top_level { + eprintln!(" {} -> {}", name, path.display()); + } + } + + let mut by_parent = by_parent.into_iter().collect::>(); + by_parent.sort(); + if by_parent.is_empty() { + eprintln!("No transitive dependencies"); + } else { + eprintln!("Transitive dependencies:"); + + for (parent, mut deps) in by_parent { + deps.sort(); + eprintln!(" {}", parent.display()); + + for (name, path) in deps { + eprintln!(" {} -> {}", name, path.display()); + } + } + } +} diff --git a/core/Cargo.toml b/core/Cargo.toml index f2387d1e0f..5faf8dcd7a 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -36,6 +36,7 @@ cxx-build = { workspace = true, optional = true } pkg-config = { workspace = true, optional = true } [dependencies] +base16.workspace = true lalrpop-util.workspace = true regex.workspace = true simple-counter.workspace = true @@ -84,6 +85,7 @@ tree-sitter-nickel = { workspace = true, optional = true } metrics = { workspace = true, optional = true } strsim = "0.10.0" +directories.workspace = true bumpalo = { workspace = true, optional = true } diff --git a/core/src/cache.rs b/core/src/cache.rs index b02fe03d48..eff0a38799 100644 --- a/core/src/cache.rs +++ b/core/src/cache.rs @@ -5,9 +5,11 @@ use crate::error::{Error, ImportError, ParseError, ParseErrors, TypecheckError}; use crate::eval::cache::Cache as EvalCache; use crate::eval::Closure; use crate::files::{FileId, Files}; +use crate::identifier::Ident; use crate::metrics::measure_runtime; #[cfg(feature = "nix-experimental")] use crate::nix_ffi; +use crate::package::PackageMap; use crate::parser::{lexer::Lexer, ErrorTolerantParser}; use crate::position::TermPos; use crate::program::FieldPath; @@ -109,6 +111,7 @@ impl InputFormat { /// is, the operations that have been performed on this term) is stored in an [EntryState]. #[derive(Debug, Clone)] pub struct Cache { + // TODO: associate packages to file ids /// The content of the program sources plus imports. files: Files, file_paths: HashMap, @@ -120,12 +123,18 @@ pub struct Cache { rev_imports: HashMap>, /// The table storing parsed terms corresponding to the entries of the file database. terms: HashMap, + /// A table mapping FileIds to the package that they belong to. + /// + /// Path dependencies have already been canonicalized to absolute paths. + package: HashMap, /// The inferred type of wildcards for each `FileId`. wildcards: HashMap, /// Whether processing should try to continue even in case of errors. Needed by the NLS. error_tolerance: ErrorTolerance, import_paths: Vec, + package_map: Option, + #[cfg(debug_assertions)] /// Skip loading the stdlib, used for debugging purpose pub skip_stdlib: bool, @@ -372,8 +381,10 @@ impl Cache { wildcards: HashMap::new(), imports: HashMap::new(), rev_imports: HashMap::new(), + package: HashMap::new(), error_tolerance, import_paths: Vec::new(), + package_map: None, #[cfg(debug_assertions)] skip_stdlib: false, @@ -387,6 +398,10 @@ impl Cache { self.import_paths.extend(paths.map(PathBuf::from)); } + pub fn set_package_map(&mut self, map: PackageMap) { + self.package_map = Some(map); + } + /// Same as [Self::add_file], but assume that the path is already normalized, and take the /// timestamp as a parameter. fn add_file_( @@ -1385,6 +1400,11 @@ impl Cache { } } +pub enum PathOrPackage<'a> { + Path(&'a OsStr, InputFormat), + Package(Ident), +} + /// Abstract the access to imported files and the import cache. Used by the evaluator, the /// typechecker and at the [import resolution](crate::transform::import_resolution) phase. /// @@ -1410,8 +1430,7 @@ pub trait ImportResolver { /// already transformed in the cache and do not need further processing. fn resolve( &mut self, - path: &OsStr, - format: InputFormat, + import: PathOrPackage<'_>, parent: Option, pos: &TermPos, ) -> Result<(ResolvedTerm, FileId), ImportError>; @@ -1425,21 +1444,47 @@ pub trait ImportResolver { impl ImportResolver for Cache { fn resolve( &mut self, - path: &OsStr, - format: InputFormat, + import: PathOrPackage<'_>, parent: Option, pos: &TermPos, ) -> Result<(ResolvedTerm, FileId), ImportError> { - // `parent` is the file that did the import. We first look in its containing directory. - let mut parent_path = parent - .and_then(|p| self.get_path(p)) - .map(PathBuf::from) - .unwrap_or_default(); - parent_path.pop(); + let (possible_parents, path, pkg_id, format) = match import { + PathOrPackage::Path(path, format) => { + // `parent` is the file that did the import. We first look in its containing directory, followed by + // the directories in the import path. + let mut parent_path = parent + .and_then(|p| self.get_path(p)) + .map(PathBuf::from) + .unwrap_or_default(); + parent_path.pop(); - let possible_parents: Vec = std::iter::once(parent_path) - .chain(self.import_paths.iter().cloned()) - .collect(); + ( + std::iter::once(parent_path) + .chain(self.import_paths.iter().cloned()) + .collect(), + Path::new(path), + None, + format, + ) + } + PathOrPackage::Package(pkg) => { + let package_map = self + .package_map + .as_ref() + .ok_or(ImportError::NoPackageMap { pos: *pos })?; + let parent_path = parent + .and_then(|p| self.package.get(&p)) + .map(PathBuf::as_path); + let pkg_path = package_map.get(parent_path, pkg, *pos)?; + ( + vec![pkg_path.to_owned()], + Path::new("lib.ncl"), + Some(pkg_path.to_owned()), + // Packages are always in nickel format + InputFormat::Nickel, + ) + } + }; // Try to import from all possibilities, taking the first one that succeeds. let (id_op, path_buf) = possible_parents @@ -1476,6 +1521,10 @@ impl ImportResolver for Cache { self.parse(file_id, format) .map_err(|err| ImportError::ParseErrors(err, *pos))?; + if let Some(pkg_id) = pkg_id { + self.package.insert(file_id, pkg_id); + } + Ok((result, file_id)) } @@ -1516,7 +1565,7 @@ pub fn normalize_path(path: impl Into) -> std::io::Result { /// [`std::fs::canonicalize`] can be hard to use correctly, since it can often /// fail, or on Windows returns annoying device paths. This is a problem Cargo /// needs to improve on. -fn normalize_abs_path(path: &Path) -> PathBuf { +pub fn normalize_abs_path(path: &Path) -> PathBuf { use std::path::Component; let mut components = path.components().peekable(); @@ -1545,6 +1594,37 @@ fn normalize_abs_path(path: &Path) -> PathBuf { ret } +pub fn normalize_rel_path(path: &Path) -> PathBuf { + use std::path::Component; + + let mut components = path.components().peekable(); + let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() { + components.next(); + PathBuf::from(c.as_os_str()) + } else { + PathBuf::new() + }; + + for component in components { + match component { + Component::Prefix(..) => unreachable!(), + Component::RootDir => { + ret.push(component.as_os_str()); + } + Component::CurDir => {} + Component::ParentDir => { + if !ret.pop() { + ret.push(Component::ParentDir); + } + } + Component::Normal(c) => { + ret.push(c); + } + } + } + ret +} + /// Return the timestamp of a file. Return `None` if an IO error occurred. pub fn timestamp(path: impl AsRef) -> io::Result { fs::metadata(path.as_ref())?.modified() @@ -1561,8 +1641,7 @@ pub mod resolvers { impl ImportResolver for DummyResolver { fn resolve( &mut self, - _path: &OsStr, - _format: InputFormat, + _import: PathOrPackage<'_>, _parent: Option, _pos: &TermPos, ) -> Result<(ResolvedTerm, FileId), ImportError> { @@ -1603,11 +1682,17 @@ pub mod resolvers { impl ImportResolver for SimpleResolver { fn resolve( &mut self, - path: &OsStr, - _format: InputFormat, + import: PathOrPackage<'_>, _parent: Option, pos: &TermPos, ) -> Result<(ResolvedTerm, FileId), ImportError> { + let PathOrPackage::Path(path, _format) = import else { + return Err(ImportError::InternalError { + msg: "simple resolver doesn't support packages".to_owned(), + pos: *pos, + }); + }; + let file_id = self .file_cache .get(path.to_string_lossy().as_ref()) diff --git a/core/src/error/mod.rs b/core/src/error/mod.rs index 58090fc43a..9b76778831 100644 --- a/core/src/error/mod.rs +++ b/core/src/error/mod.rs @@ -3,6 +3,8 @@ //! Define error types for different phases of the execution, together with functions to generate a //! [codespan](https://crates.io/crates/codespan-reporting) diagnostic from them. use codespan::ByteIndex; + +pub use codespan::{FileId, Files}; pub use codespan_reporting::diagnostic::{Diagnostic, Label, LabelStyle}; use codespan_reporting::files::Files as _; @@ -14,7 +16,7 @@ use crate::{ cache::Cache, eval::callstack::CallStack, files::{FileId, Files}, - identifier::LocIdent, + identifier::{Ident, LocIdent}, label::{ self, ty_path::{self, PathSpan}, @@ -579,6 +581,8 @@ pub enum ParseError { /// An error occurring during the resolution of an import. #[derive(Debug, PartialEq, Eq, Clone)] pub enum ImportError { + /// An unexpected internal error. + InternalError { msg: String, pos: TermPos }, /// An IO error occurred during an import. IOError( /* imported file */ String, @@ -590,6 +594,17 @@ pub enum ImportError { /* error */ ParseErrors, /* import position */ TermPos, ), + /// A package dependency was not found. + MissingDependency { + /// The package that tried to import the missing dependency, if there was one. + /// This will be `None` if the missing dependency was from the top-level + parent: Option, + /// The name of the package that could not be resolved. + missing: Ident, + pos: TermPos, + }, + /// They tried to import a file from a package, but no package manifest was supplied. + NoPackageMap { pos: TermPos }, } #[derive(Debug, PartialEq, Clone)] @@ -2537,6 +2552,17 @@ impl IntoDiagnostics for TypecheckError { impl IntoDiagnostics for ImportError { fn into_diagnostics(self, files: &mut Files) -> Vec> { match self { + ImportError::InternalError { msg, pos } => { + let labels = pos + .as_opt_ref() + .map(|span| vec![primary(span).with_message("here")]) + .unwrap_or_default(); + + vec![Diagnostic::error() + .with_message(format!("internal error: {msg}")) + .with_labels(labels) + .with_notes(vec![String::from(INTERNAL_ERROR_MSG)])] + } ImportError::IOError(path, error, span_opt) => { let labels = span_opt .as_opt_ref() @@ -2562,6 +2588,36 @@ impl IntoDiagnostics for ImportError { diagnostic } + ImportError::MissingDependency { + parent, + missing, + pos, + } => { + let labels = pos + .as_opt_ref() + .map(|span| vec![primary(span).with_message("imported here")]) + .unwrap_or_default(); + let msg = if let Some(parent_path) = parent.as_deref() { + format!( + "unknown package {missing}, imported from package {}", + parent_path.display() + ) + } else { + format!("unknown package {missing}") + }; + + vec![Diagnostic::error().with_message(msg).with_labels(labels)] + } + ImportError::NoPackageMap { pos } => { + let labels = pos + .as_opt_ref() + .map(|span| vec![primary(span).with_message("imported here")]) + .unwrap_or_default(); + vec![Diagnostic::error() + .with_message("tried to import from a package, but no package manifest found") + .with_labels(labels) + .with_notes(vec!["did you forget a --manifest-path argument?".to_owned()])] + } } } } diff --git a/core/src/eval/mod.rs b/core/src/eval/mod.rs index c6896598b0..4268cc4624 100644 --- a/core/src/eval/mod.rs +++ b/core/src/eval/mod.rs @@ -805,6 +805,12 @@ impl VirtualMachine { pos, )); } + Term::ImportPkg(pkg) => { + return Err(EvalError::InternalError( + format!("Unresolved package import ({})", pkg), + pos, + )); + } // Closurize the array if it's not already done. // This *should* make it unnecessary to call closurize in [operation]. // See the comment on the `BinaryOp::ArrayConcat` match arm. @@ -1191,6 +1197,7 @@ pub fn subst( | v @ Term::SealingKey(_) | v @ Term::Enum(_) | v @ Term::Import{..} + | v @ Term::ImportPkg(_) | v @ Term::ResolvedImport(_) // We could recurse here, because types can contain terms which would then be subject to // substitution. Not recursing should be fine, though, because a type in term position diff --git a/core/src/lib.rs b/core/src/lib.rs index 895eb4833c..dc38f338f6 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -12,6 +12,7 @@ pub mod identifier; pub mod label; #[cfg(feature = "nix-experimental")] pub mod nix_ffi; +pub mod package; pub mod parser; pub mod position; pub mod pretty; diff --git a/core/src/package.rs b/core/src/package.rs new file mode 100644 index 0000000000..a1311534d7 --- /dev/null +++ b/core/src/package.rs @@ -0,0 +1,144 @@ +//! This module contains the part of package management that's needed by the evaluator. +//! +//! In particular, it doesn't contain any support for version resolution or +//! dependency fetching, but defines lockfiles and allows them to be used to +//! resolve package dependencies to paths. + +use std::{ + array::TryFromSliceError, + collections::HashMap, + path::{Path, PathBuf}, + str::FromStr as _, +}; + +use crate::{error::ImportError, identifier::Ident, position::TermPos}; + +const ID_LEN: usize = 20; + +/// A git object id. +/// +/// Git uses 160-bit hashes as object ids. To avoid pulling in the full git dependency, we define our +/// own id type. +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct ObjectId([u8; ID_LEN]); + +// Git object ids are typically displayed in base16. +impl std::fmt::Display for ObjectId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(&base16::encode_lower(&self.0)) + } +} + +impl std::fmt::Debug for ObjectId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ObjectId({self})") + } +} + +impl TryFrom<&[u8]> for ObjectId { + type Error = TryFromSliceError; + + fn try_from(bytes: &[u8]) -> Result { + let arr: &[u8; ID_LEN] = bytes.try_into()?; + Ok(ObjectId(*arr)) + } +} + +impl From<[u8; ID_LEN]> for ObjectId { + fn from(bytes: [u8; ID_LEN]) -> Self { + ObjectId(bytes) + } +} + +impl AsRef<[u8; ID_LEN]> for ObjectId { + fn as_ref(&self) -> &[u8; ID_LEN] { + &self.0 + } +} + +#[derive(Clone, Debug)] +pub enum ParseObjectError { + Length(usize), + Base16(base16::DecodeError), +} + +impl std::fmt::Display for ParseObjectError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ParseObjectError::Length(x) => { + write!(f, "invalid object id length: got {x}, expected 40") + } + ParseObjectError::Base16(e) => write!(f, "invalid base16 for object id: {e}"), + } + } +} + +impl std::error::Error for ParseObjectError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + ParseObjectError::Length(_) => None, + ParseObjectError::Base16(e) => Some(e), + } + } +} + +impl std::str::FromStr for ObjectId { + type Err = ParseObjectError; + + fn from_str(s: &str) -> Result { + // Since it's base16, the string should be twice as long as the raw data. + if s.len() == ID_LEN * 2 { + let mut ret = ObjectId([0; ID_LEN]); + base16::decode_slice(s, &mut ret.0) + .map(move |_| ret) + .map_err(ParseObjectError::Base16) + } else { + Err(ParseObjectError::Length(s.len())) + } + } +} + +impl serde::Serialize for ObjectId { + fn serialize(&self, ser: S) -> Result { + self.to_string().serialize(ser) + } +} + +impl<'de> serde::Deserialize<'de> for ObjectId { + fn deserialize>(de: D) -> Result { + <&str>::deserialize(de) + .and_then(|s| ObjectId::from_str(s).map_err(::custom)) + } +} + +#[derive(Clone, Debug, Default)] +pub struct PackageMap { + pub top_level: HashMap, + pub packages: HashMap<(PathBuf, Ident), PathBuf>, +} + +impl PackageMap { + pub fn get( + &self, + parent: Option<&Path>, + name: Ident, + pos: TermPos, + ) -> Result<&Path, ImportError> { + let result = match parent { + Some(parent) => Some(self.packages.get(&(parent.to_owned(), name)).ok_or_else( + || ImportError::InternalError { + msg: format!("unknown parent package {parent:?}"), + pos, + }, + )?), + None => self.top_level.get(&name), + }; + result + .map(PathBuf::as_path) + .ok_or_else(|| ImportError::MissingDependency { + parent: parent.map(Path::to_owned), + missing: name, + pos, + }) + } +} diff --git a/core/src/parser/grammar.lalrpop b/core/src/parser/grammar.lalrpop index 6ca0a5435e..f5b9b0b974 100644 --- a/core/src/parser/grammar.lalrpop +++ b/core/src/parser/grammar.lalrpop @@ -258,6 +258,9 @@ UniTerm: UniTerm = { "import" "as" =>? { Ok(UniTerm::from(mk_import_explicit(s, t, mk_span(src_id, l, r))?)) }, + "import" => { + UniTerm::from(Term::ImportPkg(pkg.ident())) + } }; AnnotatedInfixExpr: UniTerm = { diff --git a/core/src/pretty.rs b/core/src/pretty.rs index d126079b22..880dea7d3c 100644 --- a/core/src/pretty.rs +++ b/core/src/pretty.rs @@ -1132,6 +1132,7 @@ impl<'a> Pretty<'a, Allocator> for &Term { }, ] } + ImportPkg(pkg) => allocator.text("import ").append(pkg.to_string()), ResolvedImport(id) => allocator.text(format!("import ")), // This type is in term position, so we don't need to add parentheses. Type { typ, contract: _ } => typ.pretty(allocator), diff --git a/core/src/program.rs b/core/src/program.rs index 9dbf18937d..ff654b95a5 100644 --- a/core/src/program.rs +++ b/core/src/program.rs @@ -32,10 +32,12 @@ use crate::{ identifier::LocIdent, label::Label, metrics::increment, + package::PackageMap, + position::TermPos, term::{ make::{self as mk_term, builder}, record::Field, - BinaryOp, MergePriority, RichTerm, Term, + BinaryOp, MergePriority, RichTerm, RuntimeContract, Term, }, typecheck::TypecheckMode, }; @@ -192,6 +194,9 @@ pub struct Program { /// be evaluated, but it can be set by the user (for example by the `--field` argument of the /// CLI) to evaluate only a specific field. pub field: FieldPath, + /// Extra contracts to apply to the main program source. Note that the contract is applied to + /// the whole value before fields are extracted. + pub contracts: Vec, } /// The Possible Input Sources, anything that a Nickel program can be created from @@ -236,6 +241,7 @@ impl Program { color_opt: clap::ColorChoice::Auto.into(), overrides: Vec::new(), field: FieldPath::new(), + contracts: Vec::new(), }) } @@ -285,6 +291,7 @@ impl Program { color_opt: clap::ColorChoice::Auto.into(), overrides: Vec::new(), field: FieldPath::new(), + contracts: Vec::new(), }) } @@ -367,6 +374,10 @@ impl Program { self.overrides.extend(overrides); } + pub fn add_contract(&mut self, contract: RuntimeContract) { + self.contracts.push(contract); + } + /// Adds import paths to the end of the list. pub fn add_import_paths

(&mut self, paths: impl Iterator) where @@ -375,6 +386,10 @@ impl Program { self.vm.import_resolver_mut().add_import_paths(paths); } + pub fn set_package_map(&mut self, map: PackageMap) { + self.vm.import_resolver_mut().set_package_map(map) + } + /// Only parse the program, don't typecheck or evaluate. returns the [`RichTerm`] AST pub fn parse(&mut self) -> Result { self.vm @@ -427,7 +442,7 @@ impl Program { fn prepare_eval_impl(&mut self, for_query: bool) -> Result { // If there are no overrides, we avoid the boilerplate of creating an empty record and // merging it with the current program - let prepared_body = if self.overrides.is_empty() { + let mut prepared_body = if self.overrides.is_empty() { self.vm.prepare_eval(self.main_id)? } else { let mut record = builder::Record::new(); @@ -456,6 +471,14 @@ impl Program { mk_term::op2(BinaryOp::Merge(Label::default().into()), t, built_record) }; + if !self.contracts.is_empty() { + prepared_body = RuntimeContract::apply_all( + prepared_body, + self.contracts.iter().cloned(), + TermPos::None, + ); + } + let prepared = Closure::atomic_closure(prepared_body); let result = if for_query { diff --git a/core/src/term/mod.rs b/core/src/term/mod.rs index c893dd739a..86db23ae7e 100644 --- a/core/src/term/mod.rs +++ b/core/src/term/mod.rs @@ -25,7 +25,7 @@ use crate::{ error::{EvalError, ParseError}, eval::{cache::CacheIndex, Environment}, files::FileId, - identifier::LocIdent, + identifier::{Ident, LocIdent}, impl_display_from_pretty, label::{Label, MergeLabel}, match_sharedterm, @@ -209,6 +209,9 @@ pub enum Term { #[serde(skip)] Import { path: OsString, format: InputFormat }, + #[serde(skip)] + ImportPkg(Ident), + /// A resolved import (which has already been loaded and parsed). #[serde(skip)] ResolvedImport(FileId), @@ -375,6 +378,7 @@ impl PartialEq for Term { format: r1, }, ) => l0 == r0 && l1 == r1, + (Self::ImportPkg(l0), Self::ImportPkg(r0)) => l0 == r0, (Self::ResolvedImport(l0), Self::ResolvedImport(r0)) => l0 == r0, ( Self::Type { @@ -1001,6 +1005,7 @@ impl Term { | Term::Op2(_, _, _) | Term::OpN(..) | Term::Import { .. } + | Term::ImportPkg(_) | Term::ResolvedImport(_) | Term::StrChunks(_) | Term::ParseError(_) @@ -1054,6 +1059,7 @@ impl Term { | Term::Sealed(..) | Term::Annotated(..) | Term::Import{..} + | Term::ImportPkg(_) | Term::ResolvedImport(_) | Term::StrChunks(_) | Term::RecRecord(..) @@ -1116,6 +1122,7 @@ impl Term { | Term::Sealed(..) | Term::Annotated(..) | Term::Import { .. } + | Term::ImportPkg(_) | Term::ResolvedImport(_) | Term::StrChunks(_) | Term::RecRecord(..) @@ -1172,6 +1179,7 @@ impl Term { | Term::Sealed(..) | Term::Annotated(..) | Term::Import{..} + | Term::ImportPkg(_) | Term::ResolvedImport(..) | Term::Closure(_) | Term::ParseError(_) @@ -2419,6 +2427,7 @@ impl Traverse for RichTerm { | Term::Closure(_) | Term::Enum(_) | Term::Import { .. } + | Term::ImportPkg(_) | Term::ResolvedImport(_) | Term::SealingKey(_) | Term::ForeignId(_) diff --git a/core/src/transform/free_vars.rs b/core/src/transform/free_vars.rs index e2c1f034fe..64b5c0cf93 100644 --- a/core/src/transform/free_vars.rs +++ b/core/src/transform/free_vars.rs @@ -43,6 +43,7 @@ impl CollectFreeVars for RichTerm { | Term::SealingKey(_) | Term::Enum(_) | Term::Import { .. } + | Term::ImportPkg(_) | Term::ResolvedImport(_) => (), Term::Fun(id, t) => { let mut fresh = HashSet::new(); diff --git a/core/src/transform/import_resolution.rs b/core/src/transform/import_resolution.rs index 40b2053118..3e087502bb 100644 --- a/core/src/transform/import_resolution.rs +++ b/core/src/transform/import_resolution.rs @@ -77,6 +77,7 @@ pub mod strict { /// together with a (partially) resolved term. pub mod tolerant { use super::ImportResolver; + use crate::cache::PathOrPackage; use crate::error::ImportError; use crate::files::FileId; use crate::term::{RichTerm, Term, Traverse, TraverseOrder}; @@ -144,11 +145,22 @@ pub mod tolerant { { let term = rt.as_ref(); match term { - Term::Import { path, format } => match resolver.resolve(path, *format, parent, &rt.pos) - { - Ok((_, file_id)) => (RichTerm::new(Term::ResolvedImport(file_id), rt.pos), None), - Err(err) => (rt, Some(err)), - }, + Term::Import { path, format } => { + match resolver.resolve(PathOrPackage::Path(path, *format), parent, &rt.pos) { + Ok((_, file_id)) => { + (RichTerm::new(Term::ResolvedImport(file_id), rt.pos), None) + } + Err(err) => (rt, Some(err)), + } + } + Term::ImportPkg(pkg) => { + match resolver.resolve(PathOrPackage::Package(*pkg), parent, &rt.pos) { + Ok((_, file_id)) => { + (RichTerm::new(Term::ResolvedImport(file_id), rt.pos), None) + } + Err(err) => (rt, Some(err)), + } + } _ => (rt, None), } } diff --git a/core/src/typecheck/mod.rs b/core/src/typecheck/mod.rs index b87b26b747..c069be395d 100644 --- a/core/src/typecheck/mod.rs +++ b/core/src/typecheck/mod.rs @@ -1447,6 +1447,7 @@ fn walk( // This function doesn't recursively typecheck imports: this is the responsibility of the // caller. | Term::Import{..} + | Term::ImportPkg(_) | Term::ResolvedImport(_) => Ok(()), Term::Var(x) => ctxt.type_env .get(&x.ident()) @@ -2402,7 +2403,7 @@ fn check( .unify(mk_uniftype::sym(), state, &ctxt) .map_err(|err| err.into_typecheck_err(state, rt.pos)), Term::Sealed(_, t, _) => check(state, ctxt, visitor, t, ty), - Term::Import { .. } => ty + Term::Import { .. } | Term::ImportPkg(_) => ty .unify(mk_uniftype::dynamic(), state, &ctxt) .map_err(|err| err.into_typecheck_err(state, rt.pos)), // We use the apparent type of the import for checking. This function doesn't recursively diff --git a/core/stdlib/std.ncl b/core/stdlib/std.ncl index 8b9eb3d016..7153434e92 100644 --- a/core/stdlib/std.ncl +++ b/core/stdlib/std.ncl @@ -2800,6 +2800,108 @@ = 2.7182818284590452354, }, + package = + let + # https://semver.org is kind enough to supply this "official" semver regex. + semver_re = m%"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"% + in + let + # An expression representing a range of semver versions, like `<1.2`. + # Unlike semver itself, semver range expressions don't seem to have an official standard. + semver_main_range_re = m%"(~|=|\^|<|>|<=|>=)?(0|[1-9]\d*)(\.(0|[1-9]\d*))?(\.(0|[1-9]\d*))?"% + in + let + # For requirements with non-empty prereleases, we support exactly two flavors: 0.1.2-pre3 or =0.1.2-pre3. + # We could also support inequalities, but we should avoid ^ and ~ because prereleases have no guaranteed + # compatibility semantics. + semver_prerelease_range_re = m%"=?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-((0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)"% + in + let semver_range_re = "(%{semver_main_range_re})|(%{semver_prerelease_range_re})" in + let semver_req_re = m%"^(%{semver_range_re}(,\s*%{semver_range_re})*)$"% in + { + is_semver_req + : String -> Bool + | doc m%" + Returns true if a string is a valid semantic version requirement. + "% + = std.string.is_match semver_req_re + , + is_semver + : String -> Bool + | doc m%" + Returns true if a string is a valid semantic version identifier. + "% + = std.string.is_match semver_re + , + Semver + | doc m%" + A contract for semantic version ("semver") identifiers. + + # Examples + + ```nickel + "1.2.0-pre1" | std.package.Semver + => "1.2.0-pre1" + + "1.foo" | std.package.Semver + => error: contract broken by a value + ``` + "% + = std.contract.from_predicate is_semver, + SemverReq + | doc m%" + A contract for semantic version ("semver") requirements. + + # Examples + + ```nickel + "^1.2" | std.package.SemverReq + => "^1.2" + + ">=1.2, <1.4" | std.package.SemverReq + => ">=1.2, <1.4" + "% + = std.contract.from_predicate is_semver_req, + Manifest = { + name + | String + | doc m%" + The name of this package. + "%, + + version + | String + | Semver + | doc m%" + The version of this package. + "%, + + nickel_version + | String + | Semver + | doc m%" + The minimal nickel version required for this package. + "%, + + dependencies + | { _: + [| + 'Path String, + 'Git { url | String, }, + 'Index { name | String, version | String | SemverReq }, + |] + } + | doc m%" + A dictionary of package dependencies, keyed by the name that this package uses to refer to them locally. + + Each dependency can refer to a path or a git repository. + In either case, the target must containing a `package.ncl` file. + "% + | default + = {}, + }, + }, + record = { map : forall a b. (String -> a -> b) -> { _ : a } -> { _ : b } diff --git a/flake.nix b/flake.nix index 9a8a7abc25..33e44132dd 100644 --- a/flake.nix +++ b/flake.nix @@ -95,6 +95,7 @@ if pkgs.stdenv.isDarwin then [ pkgs.darwin.apple_sdk.frameworks.Security + pkgs.darwin.apple_sdk.frameworks.SystemConfiguration pkgs.darwin.libiconv ] else diff --git a/lsp/nls/src/requests/completion.rs b/lsp/nls/src/requests/completion.rs index 792c7433eb..a08fcf9993 100644 --- a/lsp/nls/src/requests/completion.rs +++ b/lsp/nls/src/requests/completion.rs @@ -300,6 +300,7 @@ pub fn handle_completion( let term = server.world.lookup_term_by_position(pos)?.cloned(); let ident = server.world.lookup_ident_by_position(pos)?; + // FIXME: handle packages if let Some(Term::Import { path: import, .. }) = term.as_ref().map(|t| t.term.as_ref()) { // Don't respond with anything if trigger is a `.`, as that may be the // start of a relative file path `./`, or the start of a file extension diff --git a/package/Cargo.toml b/package/Cargo.toml new file mode 100644 index 0000000000..c5e298b511 --- /dev/null +++ b/package/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "nickel-lang-package" +description = "The Nickel Package Manager (npm)" +version = "0.1.0" + +authors.workspace = true +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true +readme.workspace = true + +[features] + +[dependencies] +anyhow.workspace = true +directories.workspace = true +gix = { version = "0.63.0", features = ["blocking-network-client", "blocking-http-transport-reqwest-rust-tls"] } +nickel-lang-core = { workspace = true, default-features = false } +pubgrub = "0.2.1" +semver = { version = "1.0.23", features = ["serde"] } +serde.workspace = true +serde_json.workspace = true +tempfile = { workspace = true } diff --git a/package/src/error.rs b/package/src/error.rs new file mode 100644 index 0000000000..ee11e5cdb2 --- /dev/null +++ b/package/src/error.rs @@ -0,0 +1,156 @@ +use std::path::{Path, PathBuf}; + +use nickel_lang_core::{eval::cache::CacheImpl, identifier::Ident, program::Program}; + +pub enum Error { + Io { + path: Option, + error: std::io::Error, + }, + ManifestEval { + package: Option, + program: Program, + error: nickel_lang_core::error::Error, + }, + NoPackageRoot { + path: PathBuf, + }, + RestrictedPath { + package: Ident, + attempted: PathBuf, + restriction: PathBuf, + }, + /// There was some error interacting with a git repository. + Git { + repo: String, + msg: String, + }, + InvalidUrl { + url: String, + msg: String, + }, + Resolution { + msg: String, + }, + InternalManifestError { + msg: String, + }, +} + +impl std::fmt::Debug for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::Io { error, path } => { + if let Some(path) = path { + write!(f, "{}: {error}", path.display()) + } else { + error.fmt(f) + } + } + // Just a short and not-very-informative error. To write a better error message to + // the terminal, use `program.report` like the cli does. + Error::ManifestEval { package, .. } => { + if let Some(package) = package { + write!(f, "error evaluating manifest for package {package}") + } else { + write!(f, "error evaluating package manifest") + } + } + Error::RestrictedPath { + package, + attempted, + restriction, + } => { + write!( + f, + "package {package} tried to import path {}, but can only import from {}", + attempted.display(), + restriction.display() + ) + } + Error::Git { repo, msg } => { + write!(f, "error processing git repository at {}: {}", repo, msg) + } + Error::InvalidUrl { url, msg } => { + write!(f, "invalid url {}: {}", url, msg) + } + Error::InternalManifestError { msg } => { + write!( + f, + "internal error reading the manifest; this is a bug in nickel: {msg}" + ) + } + Error::NoPackageRoot { path } => write!( + f, + "tried to import a relative path ({}), but we have no reference", + path.display() + ), + Error::Resolution { msg } => write!(f, "version resolution failed: {msg}"), + } + } +} + +pub trait ResultExt { + type T; + fn in_package(self, package: Ident) -> Result; +} + +impl ResultExt for Result { + type T = T; + + fn in_package(self, package: Ident) -> Result { + self.map_err(|e| match e { + Error::ManifestEval { program, error, .. } => Error::ManifestEval { + package: Some(package), + program, + error, + }, + x => x, + }) + } +} + +pub trait GitResultExt { + type T; + fn in_git_repo(self, url: impl AsRef) -> Result; +} + +impl GitResultExt for Result { + type T = T; + + fn in_git_repo(self, url: impl AsRef) -> Result { + self.map_err(|e| Error::Git { + repo: url.as_ref().to_owned(), + msg: e.to_string(), + }) + } +} + +pub trait IoResultExt { + type T; + fn with_path(self, path: impl AsRef) -> Result; + fn without_path(self) -> Result; +} + +impl IoResultExt for Result { + type T = T; + fn with_path(self, path: impl AsRef) -> Result { + self.map_err(|e| Error::Io { + path: Some(path.as_ref().to_owned()), + error: e, + }) + } + + fn without_path(self) -> Result { + self.map_err(|e| Error::Io { + path: None, + error: e, + }) + } +} diff --git a/package/src/index/mod.rs b/package/src/index/mod.rs new file mode 100644 index 0000000000..4079a79ef4 --- /dev/null +++ b/package/src/index/mod.rs @@ -0,0 +1,338 @@ +//! The package index. +//! +//! The package index lives in a hard-coded location on github. It gets cached on the local +//! disk, and then lazily loaded from there and cached in memory. +//! +//! TODO: +//! - add file locks to protect the on-disk cache from concurrent modification by multiple nickel +//! processes + +use std::{ + cell::RefCell, + collections::{BTreeMap, HashMap}, + io::Write, + path::PathBuf, +}; + +use anyhow::anyhow; +use nickel_lang_core::{identifier::Ident, package::ObjectId}; +use pubgrub::version::SemanticVersion; +use serde::{Deserialize, Serialize}; +use tempfile::{tempdir_in, NamedTempFile}; + +use crate::{ + util::{self, cache_dir, clone_git, semver_to_pg}, + Precise, +}; + +pub const INDEX_URL: &str = "https://github.com/tweag/nickel-mine.git"; + +pub mod scrape; + +/// The in-memory cache. +pub struct PackageCache { + root: PathBuf, + package_files: HashMap, +} + +pub struct PackageIndex { + cache: RefCell, +} + +impl PackageCache { + fn path(&self, id: &Id) -> PathBuf { + self.root.join(&id.org).join(&id.name) + } + + fn tmp_file(&self, id: &Id) -> NamedTempFile { + let parent = self.root.join(&id.org); + std::fs::create_dir_all(&parent).unwrap(); + NamedTempFile::new_in(parent).unwrap() + } + + fn load(&mut self, id: &Id) -> Option<&CachedPackageFile> { + let mut file = CachedPackageFile::default(); + let data = std::fs::read_to_string(self.path(id)).ok()?; + for line in data.lines() { + let package: Package = serde_json::from_str(line).unwrap(); + if file + .packages + .insert(package.vers.clone(), package) + .is_some() + { + panic!("duplicate version"); + } + } + + self.package_files.insert(id.clone(), file); + self.package_files.get(id) + } + + pub fn clear(&mut self) { + self.package_files.clear(); + } + + /// Saves a package description to disk. + /// + /// (Also retains a cached copy in memory.) + pub fn save(&mut self, pkg: Package) { + let id = pkg.id.clone(); + let mut existing = self + .load(&pkg.id) + .cloned() + .unwrap_or(CachedPackageFile::default()); + if existing.packages.insert(pkg.vers.clone(), pkg).is_some() { + panic!("you can't overwrite a package version"); + } + let mut tmp = self.tmp_file(&id); + for pkg in existing.packages.values() { + serde_json::to_writer(&mut tmp, pkg).unwrap(); + tmp.write_all(b"\n").unwrap(); + } + tmp.persist(self.path(&id)).unwrap(); + } +} + +impl PackageIndex { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + let root = cache_dir().join("index"); + PackageIndex { + cache: RefCell::new(PackageCache { + root, + package_files: HashMap::new(), + }), + } + } + + pub fn fetch_from_github(&self) { + let root = self.cache.borrow().root.clone(); + let (tmp_dir, _repo) = util::clone_git(INDEX_URL).unwrap(); + let tmp_path = tmp_dir.into_path(); + std::fs::rename(tmp_path, root).unwrap(); + } + + pub fn refresh_from_github(&self) { + let root = self.cache.borrow().root.clone(); + if !root.exists() { + self.fetch_from_github(); + return; + } + + let repo = gix::open(root.clone()).unwrap(); + let remote = repo + .find_default_remote(gix::remote::Direction::Fetch) + .unwrap() + .unwrap(); + let conn = remote.connect(gix::remote::Direction::Fetch).unwrap(); + let outcome = conn + .prepare_fetch( + gix::progress::Discard, + gix::remote::ref_map::Options::default(), + ) + .unwrap() + .receive(gix::progress::Discard, &gix::interrupt::IS_INTERRUPTED) + .unwrap(); + + // Set the new head to track the latest upstream. We don't care if it's a fast-forward + // or not. + let new_head = repo.find_reference("refs/remotes/origin/main").unwrap(); + repo.head_ref() + .unwrap() + .unwrap() + .set_target_id(new_head.id().detach(), "refresh") + .unwrap(); + match outcome.status { + gix::remote::fetch::Status::NoPackReceived { .. } => eprintln!("already up-to-date"), + gix::remote::fetch::Status::Change { .. } => {} + } + let tree = new_head.id().object().unwrap().peel_to_tree().unwrap().id(); + let mut index = repo.index_from_tree(&tree).unwrap(); + + // In principle we should be doing more work to clean up the filesystem state. For example, + // this doesn't delete files that were deleted in the index. But since the registry is + // append-only it should be ok. + // + // (Another interesting possibility: allow PackageIndex to work directly from a git index + // instead of requiring the files to be saved out.) + gix::worktree::state::checkout( + &mut index, + root, + repo.objects.clone(), + &gix::progress::Discard, + &gix::progress::Discard, + &gix::interrupt::IS_INTERRUPTED, + gix::worktree::state::checkout::Options { + overwrite_existing: true, + ..Default::default() + }, + ) + .unwrap(); + index.write(Default::default()).unwrap(); + self.cache.borrow_mut().clear(); + } + + pub fn new_with_root(root: PathBuf) -> Self { + PackageIndex { + cache: RefCell::new(PackageCache { + root, + package_files: HashMap::new(), + }), + } + } + + pub fn available_versions<'a>(&'a self, id: &Id) -> impl Iterator + 'a { + let mut cache = self.cache.borrow_mut(); + let pkg_file = cache.load(id); + let versions: Vec<_> = pkg_file + .map(|pkg_file| { + pkg_file + .packages + .keys() + .map(|v| SemanticVersion::new(v.major as u32, v.minor as u32, v.patch as u32)) + .collect() + }) + .unwrap_or_default(); + versions.into_iter() + } + + pub fn all_versions(&self, id: &Id) -> HashMap { + let mut cache = self.cache.borrow_mut(); + let pkg_file = cache.load(id); + pkg_file + .map(|pkg_file| { + pkg_file + .packages + .iter() + .map(|(v, package)| { + ( + SemanticVersion::new(v.major as u32, v.minor as u32, v.patch as u32), + package.clone(), + ) + }) + .collect() + }) + .unwrap_or_default() + } + + // TODO: clarify SemanticVersion vs semver::Version. The point is that SemanticVersion comes from pubgrub, which doesn't support prerelease. + pub fn package(&self, id: &Id, v: SemanticVersion) -> Option { + self.all_versions(id).get(&v).cloned() + } + + pub fn save(&mut self, pkg: Package) { + self.cache.borrow_mut().save(pkg) + } + + pub fn ensure_downloaded(&self, id: &Id, v: semver::Version) -> anyhow::Result<()> { + let package = self + .package(id, semver_to_pg(v.clone())) + .ok_or(anyhow!("tried to download an unknown package"))?; + let precise = Precise::Index { + id: id.clone(), + version: v, + }; + self.ensure_loc_downloaded(&precise, &package.loc) + } + + fn ensure_loc_downloaded( + &self, + precise: &Precise, + loc: &PackageLocation, + ) -> anyhow::Result<()> { + let PackageLocation::Github { id, rev } = loc; + let url = format!("https://github.com/{id}.git"); + + let target_dir = precise.local_path(); + if target_dir.exists() { + eprintln!("Package {id}@{rev} already exists"); + return Ok(()); + } + + eprintln!("Downloading {id}@{rev} to {}", target_dir.display()); + let (_tmp_dir, repo) = clone_git(url.as_str())?; + let commit_id = gix::ObjectId::Sha1(rev.as_ref().to_owned()); + let commit = repo.find_object(commit_id)?; + let tree = commit.peel_to_tree()?; + let mut index = repo.index_from_tree(&tree.id())?; + + let target_dir_parent = target_dir.parent().unwrap(); + std::fs::create_dir_all(target_dir_parent)?; + let tmp_dir = tempdir_in(target_dir_parent)?; + + gix::worktree::state::checkout( + &mut index, + tmp_dir.path(), + repo.objects.clone(), + &gix::progress::Discard, + &gix::progress::Discard, + &gix::interrupt::IS_INTERRUPTED, + Default::default(), + )?; + + let tmp_dir = tmp_dir.into_path(); + std::fs::rename(tmp_dir, target_dir)?; + + Ok(()) + } +} + +/// Packages in the index are identified by an organization and a package name. +#[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct Id { + pub org: String, + pub name: String, +} + +impl std::fmt::Display for Id { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}/{}", self.org, self.name) + } +} + +impl std::str::FromStr for Id { + type Err = (); + + fn from_str(s: &str) -> Result { + let (org, name) = s.split_once('/').ok_or(())?; + // TODO: decide on valid identifiers + Ok(Id { + org: org.to_owned(), + name: name.to_owned(), + }) + } +} + +#[derive(Clone, Debug, Default)] +pub struct CachedPackageFile { + pub packages: BTreeMap, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Package { + #[serde(flatten)] + pub id: Id, + pub vers: semver::Version, + pub nickel_vers: semver::Version, + pub loc: PackageLocation, + pub deps: BTreeMap, + + /// Version of the index schema. Currently always zero. + v: u32, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum PackageLocation { + Github { + #[serde(flatten)] + id: Id, + rev: ObjectId, + }, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct IndexDependency { + #[serde(flatten)] + pub id: Id, + pub req: semver::VersionReq, +} diff --git a/package/src/index/scrape.rs b/package/src/index/scrape.rs new file mode 100644 index 0000000000..530e759fdf --- /dev/null +++ b/package/src/index/scrape.rs @@ -0,0 +1,85 @@ +//! Tools for updating an index from a git repository. +//! +//! Given an org and a project name, we look for a github project at that location. +//! We then look for all tags of the form v. For each such tag, we record +//! a version of that package. + +use std::str::FromStr as _; + +use anyhow::anyhow; + +use crate::{util, ManifestFile}; + +use super::{CachedPackageFile, Id, IndexDependency, Package, PackageLocation}; + +// id here is a bit misused, because it tells the github url but the name of the package can actually be different +pub fn scrape(id: &Id) -> anyhow::Result { + let (_tmp_dir, repo) = util::clone_github(id)?; + let mut buf = Vec::new(); + let mut ret = CachedPackageFile::default(); + + for tag in repo.references()?.tags()? { + // Filter out tags that don't parse as versions. + let tag = tag.map_err(|e| anyhow!("{}", e))?; + let tag_name = tag.name().as_bstr(); + let Ok(tag_name) = std::str::from_utf8(tag_name) else { + continue; + }; + let Some(tag_version) = tag_name.strip_prefix("refs/tags/v") else { + continue; + }; + let Ok(version) = semver::Version::from_str(tag_version) else { + continue; + }; + + let peeled_tag = tag.into_fully_peeled_id()?; + let tree = peeled_tag.object()?.peel_to_tree()?; + let Some(entry) = tree.lookup_entry_by_path("package.ncl", &mut buf)? else { + continue; + }; + let manifest = match ManifestFile::from_contents(&entry.object()?.data) { + Ok(m) => m, + Err(e) => panic!("{e}"), + }; + + if manifest.version != version { + eprintln!( + "version mismatch: manifest {}, tag {}", + manifest.version, version + ); + continue; + } + + let package_id = Id { + org: id.org.clone(), + name: manifest.name.label().to_owned(), + }; + let deps = manifest + .dependencies + .into_iter() + .map(|(name, dep)| match dep { + crate::Dependency::Index { id, version } => { + (name, IndexDependency { id, req: version }) + } + _ => panic!("can't index a crate with git/path deps"), + }) + .collect(); + let gix::ObjectId::Sha1(rev) = peeled_tag.detach(); + ret.packages.insert( + version.clone(), + Package { + id: package_id, + vers: version, + nickel_vers: manifest.nickel_version, + loc: PackageLocation::Github { + id: id.clone(), + rev: rev.into(), + }, + deps, + v: 0, + }, + ); + } + + Ok(ret) +} diff --git a/package/src/lib.rs b/package/src/lib.rs new file mode 100644 index 0000000000..d1f53c4a92 --- /dev/null +++ b/package/src/lib.rs @@ -0,0 +1,152 @@ +use std::path::{Path, PathBuf}; + +pub mod error; +pub mod index; +pub mod lock; +pub mod manifest; +pub mod resolve; +pub mod util; + +pub use manifest::ManifestFile; +use nickel_lang_core::{cache::normalize_abs_path, package::ObjectId}; +use semver::{Version, VersionReq}; +use serde::{Deserialize, Serialize}; +use util::cache_dir; + +/// A source includes the place to fetch a package from (e.g. git or a registry), +/// along with possibly some narrowing-down of the allowed versions (e.g. a range +/// of versions, or a git commit id). +#[derive(Clone, Debug, PartialEq, Eq, Hash, Deserialize)] +pub enum Dependency { + // TODO: allow targeting branches or revisions, and allow supplying a relative path + Git { + #[serde(with = "serde_url")] + url: gix::Url, + //tree: Option, + }, + Path { + path: PathBuf, + }, + Index { + id: index::Id, + version: VersionReq, + }, +} + +impl Dependency { + pub fn matches(&self, precise: &Precise) -> bool { + match (self, precise) { + (Dependency::Git { url }, Precise::Git { repo, .. }) => url == repo, + (Dependency::Path { path }, Precise::Path { path: locked_path }) => path == locked_path, + ( + Dependency::Index { + id: dep_id, + version: dep_version, + }, + Precise::Index { id, version }, + ) => id == dep_id && dep_version.matches(version), + _ => false, + } + } +} + +mod serde_url { + use serde::{de::Error, Deserialize, Serialize as _}; + + pub fn serialize(url: &gix::Url, ser: S) -> Result { + // unwrap: locked urls can only come from nickel strings in the manifest file, which must be + // valid utf-8 + std::str::from_utf8(url.to_bstring().as_slice()) + .unwrap() + .serialize(ser) + } + + pub fn deserialize<'de, D: serde::Deserializer<'de>>(de: D) -> Result { + let s = <&str>::deserialize(de)?; + gix::Url::try_from(s).map_err(|e| D::Error::custom(e.to_string())) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub struct IndexPrecise { + id: index::Id, + version: Version, +} + +/// A precise package version, in a format suitable for putting into a lockfile. +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +pub enum Precise { + Git { + // We use `Precise` for a few different purposes, and not all of them need the url. (For + // resolution, for example, we could consider two git deps equal if they have the same id + // even if they came from different sources.) However, the lockfile should have a repo url in + // it, because it allows us to fetch the package if it isn't available, and it allows us to + // check if the locked dependency matches the manifest (which might only have the url). + #[serde(with = "serde_url")] + repo: gix::Url, + id: ObjectId, + path: PathBuf, + }, + /// The path is normalized (i.e., all '..'s are at the beginning), and relative + /// to the top-level package manifest. + /// + /// Note that when normalizing we only look at the path and not at the actual filesystem. + Path { path: PathBuf }, + Index { + // TODO: IndexPrecise + id: index::Id, + version: Version, + }, +} + +impl Precise { + /// Where on the local filesystem can this package be found? + /// + /// Note: it might not actually be there yet, if it's a git or index package that hasn't been fetched. + pub fn local_path(&self) -> PathBuf { + match self { + Precise::Git { id, path, .. } => repo_root(id).join(path), + Precise::Path { path } => Path::new(path).to_owned(), + Precise::Index { id, version } => cache_dir() + .join("index-packages") + .join(format!("{id}-{version}")), + } + } + + pub fn is_path(&self) -> bool { + matches!(self, Precise::Path { .. }) + } + + /// Is this locked package available offline? If not, it needs to be fetched. + pub fn is_available_offline(&self) -> bool { + // We consider path-dependencies to be always available offline, even if they don't exist. + // We consider git-dependencies to be available offline if there's a directory at + // `~/.cache/nickel/ed8234.../` (or wherever the cache directory is on your system). We + // don't check if that directory contains the right git repository -- if someone has messed + // with the contents of `~/.cache/nickel`, that's your problem. + match self { + Precise::Path { .. } => true, + _ => self.local_path().is_dir(), + } + } + + pub fn with_abs_path(self, root: &std::path::Path) -> Self { + match self { + Precise::Path { path } => Precise::Path { + path: normalize_abs_path(&root.join(path)), + }, + x => x, + } + } + + pub fn version(&self) -> Option { + match self { + Precise::Index { version, .. } => Some(version.clone()), + _ => None, + } + } +} + +fn repo_root(id: &ObjectId) -> PathBuf { + cache_dir().join(id.to_string()) +} diff --git a/package/src/lock.rs b/package/src/lock.rs new file mode 100644 index 0000000000..288a93064d --- /dev/null +++ b/package/src/lock.rs @@ -0,0 +1,74 @@ +// c&p from old file. + +use std::collections::HashMap; + +use nickel_lang_core::identifier::Ident; +use serde::{Deserialize, Serialize}; + +use crate::{error::Error, resolve::Resolution, ManifestFile, Precise}; + +mod package_list { + use std::collections::HashMap; + + use serde::{Deserializer, Serializer}; + + use super::*; + + #[derive(Serialize, Deserialize)] + struct Entry { + source: Precise, + #[serde(flatten)] + entry: LockFileEntry, + } + + pub fn serialize( + h: &HashMap, + ser: S, + ) -> Result { + let entries: Vec<_> = h + .iter() + .map(|(source, entry)| Entry { + source: source.clone(), + entry: entry.clone(), + }) + .collect(); + entries.serialize(ser) + } + + pub fn deserialize<'de, D: Deserializer<'de>>( + de: D, + ) -> Result, D::Error> { + let entries = Vec::::deserialize(de)?; + Ok(entries.into_iter().map(|e| (e.source, e.entry)).collect()) + } +} + +/// A lock file, specifying versions and names for all recursive dependencies. +/// +/// This defines the on-disk format for lock files. +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct LockFile { + /// The dependencies of the current (top-level) package. + pub dependencies: HashMap, + /// All packages that we know about, and the dependencies of each one. + /// + /// Note that the package list is not guaranteed to be closed: path dependencies + /// cannot have their dependencies resolved in the on-disk lockfile because they + /// can change at any time. *Some* path dependencies (for example, path dependencies + /// that are local to a git depencency repo) may have resolved dependencies. + #[serde(with = "package_list")] + pub packages: HashMap, +} + +impl LockFile { + // TODO: move the implementation here + pub fn new(manifest: &ManifestFile, resolution: &Resolution) -> Result { + resolution.lock_file(manifest) + } +} + +/// The dependencies of a single package. +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct LockFileEntry { + pub dependencies: HashMap, +} diff --git a/package/src/manifest.rs b/package/src/manifest.rs new file mode 100644 index 0000000000..ecaa448928 --- /dev/null +++ b/package/src/manifest.rs @@ -0,0 +1,321 @@ +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + +use nickel_lang_core::{ + cache::normalize_rel_path, + eval::cache::CacheImpl, + identifier::Ident, + label::Label, + package::ObjectId, + program::Program, + term::{make, RichTerm, RuntimeContract, Term}, +}; +use serde::Deserialize; + +use crate::{ + error::{Error, IoResultExt}, + lock::LockFile, + repo_root, + resolve::Resolution, + util::clone_git, + Dependency, Precise, +}; + +#[derive(Clone, Debug, Deserialize)] +struct ManifestFileFormat { + pub name: Ident, + pub version: semver::Version, + pub nickel_version: semver::Version, + pub dependencies: HashMap, +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ManifestFile { + // The directory containing the manifest file. Path deps are resolved relative to this. + // If `None`, path deps aren't allowed. + pub parent_dir: Option, + pub name: Ident, + pub version: semver::Version, + pub nickel_version: semver::Version, + pub dependencies: HashMap, +} + +impl ManifestFile { + pub fn from_path(path: impl AsRef) -> Result { + let path = path.as_ref(); + let prog = Program::new_from_file(path, std::io::stderr()).with_path(path)?; + let mut ret = ManifestFile::from_prog(prog)?; + ret.parent_dir = path.parent().map(Path::to_owned); + Ok(ret) + } + + pub fn from_contents(data: &[u8]) -> Result { + let prog = Program::new_from_source( + std::io::Cursor::new(data), + "", + std::io::stderr(), + ) + .without_path()?; + ManifestFile::from_prog(prog) + } + + fn from_prog(mut prog: Program) -> Result { + // Evaluate the manifest with an extra contract applied, so that nice error message will be generated. + // (Probably they applied the Manifest contract already, but just in case...) + // `contract` is `std.package.Manifest` + use nickel_lang_core::term::UnaryOp::RecordAccess; + let contract = make::op1( + RecordAccess("Manifest".into()), + make::op1(RecordAccess("package".into()), Term::Var("std".into())), + ); + prog.add_contract(RuntimeContract::new(contract, Label::default())); + + let manifest_term = prog.eval_full().map_err(|e| Error::ManifestEval { + package: None, + program: prog, + error: e, + })?; + ManifestFile::from_term(&manifest_term) + } + + fn lockfile_path(&self) -> Option { + let parent_dir = self.parent_dir.as_ref()?; + Some(parent_dir.join("package.lock")) + } + + pub fn is_lock_file_up_to_date(&self, lock_file: &LockFile) -> bool { + self.dependencies.iter().all(|(name, src)| { + lock_file + .dependencies + .get(name) + .map_or(false, |id| src.matches(id)) + }) + } + + /// Checks if this manifest already has an up-to-date lockfile. + /// + /// Here, by up-to-date we mean that all dependencies in the manifest are present in the lockfile. + /// But we don't, for example, check whether git deps are fully up-to-date. + fn find_lockfile(&self) -> Option { + let lock_file = std::fs::read_to_string(self.lockfile_path()?).ok()?; + let lock_file: LockFile = match serde_json::from_str(&lock_file) { + Ok(f) => f, + Err(e) => { + eprintln!("Found a lockfile, but it failed to parse: {e}"); + return None; + } + }; + self.is_lock_file_up_to_date(&lock_file) + .then_some(lock_file) + } + + /// Recursively resolve git dependencies, putting them into a lock file. + /// + /// Path dependencies aren't resolved recursively: path dependencies + /// don't get locked because they can change at any time. + pub fn resolve(&self) -> Result { + let lock = self.find_lockfile().unwrap_or_default(); + crate::resolve::resolve_with_lock(self, &lock) + } + + /// Determine the fully-resolved dependencies. + /// + /// Re-uses a lock file if there's one that's up-to-date. Otherwise, regenerates the lock file. + pub fn lock(&self) -> Result { + if let Some(lock) = self.find_lockfile() { + eprintln!("Found an up-to-date lockfile"); + return Ok(lock); + } + + self.regenerate_lock() + } + + /// Regenerate the lock file, even if it already exists. + pub fn regenerate_lock(&self) -> Result { + let resolution = self.resolve()?; + let lock = resolution.lock_file(self)?; + + if let Some(lock_path) = self.lockfile_path() { + // unwrap: serde_json serialization fails if the derived `Serialize` + // trait fails (which it shouldn't), or if there's a map with + // non-string keys (all our maps have `Ident` keys). + let serialized_lock = serde_json::to_string_pretty(&lock).unwrap(); + if let Err(e) = std::fs::write(lock_path, serialized_lock) { + eprintln!("Warning: failed to write lock-file: {e}"); + } + } + + Ok(lock) + } + + // Convert from a `RichTerm` (that we assume was evaluated deeply). We + // could serialize/deserialize, but that doesn't handle the enums. + fn from_term(rt: &RichTerm) -> Result { + // This is only ever called with terms that have passed the `std.package.Manifest` + // contract, so we can assume that they have the right fields. + let ManifestFileFormat { + name, + version, + nickel_version, + dependencies, + } = ManifestFileFormat::deserialize(rt.clone()) + .map_err(|e| Error::InternalManifestError { msg: e.to_string() })?; + Ok(Self { + parent_dir: None, + name, + version, + nickel_version, + dependencies, + }) + } +} + +#[derive(Clone, Debug)] +pub struct RealizedDependency { + /// Either `Git` or `Path`. + pub precise: Precise, + pub manifest: ManifestFile, +} + +#[derive(Clone, Debug, Default)] +pub struct Realization { + // TODO: the key here should be whatever's in Dependency::Git. Currently that's just the repo url, but it will change + pub git: HashMap, + pub precise: HashMap, + pub manifests: HashMap, +} + +impl Realization { + // TODO: take in an import sequence (like: the dependency was imported from x, which was imported from y) and use it to improve error messages + pub fn realize_all( + &mut self, + root_path: Option<&Path>, + dep: &Dependency, + relative_to: Option<&Precise>, + ) -> Result<(), Error> { + let precise = match (dep, relative_to) { + // Repo dependencies are resolved later. They are not allowed to have + // transitive git or path dependencies, so we don't even need to recurse. + (Dependency::Index { .. }, _) => { + return Ok(()); + } + (Dependency::Git { url }, _) => { + let id = self.realize_one(url)?; + Precise::Git { + id, + repo: url.clone(), + path: PathBuf::new(), + } + } + (Dependency::Path { path }, None) => Precise::Path { path: path.clone() }, + (Dependency::Path { path }, Some(relative_to)) => { + let p = normalize_rel_path(&relative_to.local_path().join(path)); + match relative_to { + Precise::Git { id, repo, .. } => { + let repo_path = repo_root(id); + let p = p + .strip_prefix(&repo_path) + .map_err(|_| Error::RestrictedPath { + package: "TODO".into(), + attempted: p.clone(), + restriction: repo_path.to_owned(), + })?; + Precise::Git { + id: *id, + repo: repo.clone(), + path: p.to_owned(), + } + } + _ => Precise::Path { path: p }, + } + } + }; + + let path = precise.local_path(); + let abs_path = if path.is_absolute() { + path + } else if let Some(root_path) = root_path { + root_path.join(path) + } else { + return Err(Error::NoPackageRoot { path }); + }; + let manifest = ManifestFile::from_path(abs_path.join("package.ncl"))?; + self.precise.insert(dep.clone(), precise.clone()); + self.manifests.insert(precise.clone(), manifest.clone()); + + for dep in manifest.dependencies.values() { + self.realize_all(root_path, dep, Some(&precise))?; + } + + Ok(()) + } + + fn realize_one(&mut self, url: &gix::Url) -> Result { + if let Some(id) = self.git.get(url) { + return Ok(*id); + } + + fn err(url: &gix::Url, msg: impl std::fmt::Display) -> Error { + Error::Git { + repo: url.to_string(), + msg: msg.to_string(), + } + } + + let (tmp_dir, repo) = clone_git(url.clone()).map_err(|e| Error::Git { + repo: url.to_string(), + msg: e.to_string(), + })?; + + let head = repo.head().map_err(|e| err(url, e))?; + let id: ObjectId = head + .into_peeled_id() + .map_err(|e| err(url, e))? + .as_bytes() + .try_into() + .map_err(|e| err(url, e))?; + + // Now that we know the object hash, move the fetched repo to the right place in the cache. + let precise = Precise::Git { + id, + repo: url.clone(), + path: PathBuf::default(), + }; + let path = precise.local_path(); + + if path.is_dir() { + eprintln!("Already have a cache entry at {path:?}"); + } else { + let tmp_dir = tmp_dir.into_path(); + std::fs::rename(tmp_dir, &path).with_path(path)?; + } + + self.git.insert(url.clone(), id); + Ok(id) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn manifest() { + let manifest = ManifestFile::from_contents( + r#"{name = "foo", version = "1.0.0", nickel_version = "1.8.0"}"#.as_bytes(), + ) + .unwrap(); + assert_eq!( + manifest, + ManifestFile { + parent_dir: None, + name: "foo".into(), + version: semver::Version::new(1, 0, 0), + nickel_version: semver::Version::new(1, 8, 0), + dependencies: HashMap::default() + } + ) + } +} diff --git a/package/src/resolve.rs b/package/src/resolve.rs new file mode 100644 index 0000000000..e428724aa4 --- /dev/null +++ b/package/src/resolve.rs @@ -0,0 +1,764 @@ +//! We do cargo-style version resolution, where we allow multiple semver-incompatible +//! copies of a package, but we insist that all semver-compatible verisons must resolve +//! to the exact same version. +//! +//! This is not natively supported in pubgrub, so we use the two transformations described +//! in [their book](https://pubgrub-rs-guide.pages.dev/limitations/multiple_versions). +//! The first transformation is to make a new package for every collection of semver-compatible +//! versions of each package. So instead of having `foo` with versions `1.1`, `1.2` and `2.0`, +//! we have a package `foo#1` with versions `1.1` and `1.2` and another package `foo#2` +//! with version `2.0`. We call `foo#1` and `foo#2` "buckets". Since we present them to pubgrub +//! as different packages, they can both appear in the final resolution. +//! +//! The problem with the approach above is that it introduces "union" dependencies, where +//! a package that required `foo` at version `>=1.0` now has a dependency on either `foo#1` +//! or `foo#2`. Pubgrub doesn't natively support union dependencies, so there's another +//! transformation needed for that. Any time there's a dependency that depends on one of +//! multiple buckets, we insert a "union" package (pubgrub's write-up calls it a "proxy") +//! that has a version for each bucket. See the pubgrub write-up for more details. + +use std::{ + borrow::Borrow, + collections::HashMap, + path::{Path, PathBuf}, +}; + +use nickel_lang_core::{cache::normalize_path, identifier::Ident, package::PackageMap}; +use pubgrub::{ + report::{DefaultStringReporter, Reporter as _}, + solver::DependencyProvider, + version::{SemanticVersion, Version}, +}; +use semver::{Comparator, VersionReq}; + +use crate::{ + error::{Error, IoResultExt as _}, + index::{Id, IndexDependency, PackageIndex}, + lock::{LockFile, LockFileEntry}, + manifest::Realization, + util::semver_to_pg, + Dependency, IndexPrecise, ManifestFile, Precise, +}; + +type VersionRange = pubgrub::range::Range; + +pub struct PackageRegistry { + // The packages whose versions were locked in a lockfile; we'll try to prefer using + // those same versions. We won't absolutely insist on it, because if the manifest + // changed (or some path-dependency changed) then the old locked versions might not + // resolve anymore. + previously_locked: HashMap, + index: PackageIndex, + realized_unversioned: Realization, +} + +impl PackageRegistry { + pub fn list_versions<'a>( + &'a self, + package: &VirtualPackage, + ) -> impl Iterator + 'a { + let locked_version = self.previously_locked.get(package).cloned(); + let rest = match package { + VirtualPackage::Package(Package::Unversioned(_)) => { + Box::new(std::iter::once(SemanticVersion::zero())) as Box> + } + VirtualPackage::Package(Package::Bucket(b)) => { + let bucket_version = b.version; + let iter = self + .index + .available_versions(&b.id) + .filter(move |v| bucket_version.contains(*v)); + Box::new(iter) + } + // The edge package has a version for every bucket of target versions that + // it could potentially resolve to. + VirtualPackage::Union { + source, + source_version, + target, + } => { + // First, find all buckets of target versions. + let target_versions = bucket_versions(self.index.available_versions(target)); + // Filter to keep only the ones that could concievably intersect with + // the allowed version constraints. + let source_req = self.dep(source, source_version, target); + + let iter = target_versions + .filter(move |v| BucketVersion::from(*v).intersects(&source_req)); + + Box::new(iter) + } + }; + + // Put the locked version first, and then the other versions in any order (filtering to ensure that the locked version isn't repeated). + locked_version + .into_iter() + .chain(rest.filter(move |v| Some(v) != locked_version.as_ref())) + } + + pub fn dep(&self, pkg: &Package, version: &SemanticVersion, dep_id: &Id) -> VersionReq { + let deps = match pkg { + Package::Unversioned(pkg) => self.unversioned_deps(pkg), + Package::Bucket(b) => self.index_deps(&b.id, version), + }; + deps.iter() + .find_map(|d| match d { + Dependency::Index { id, version } if id == dep_id => Some(version.clone()), + _ => None, + }) + .unwrap() + } + + pub fn unversioned_deps(&self, pkg: &UnversionedPackage) -> Vec { + let dep = Dependency::from(pkg.clone()); + let precise = &self.realized_unversioned.precise[&dep]; + let manifest = &self.realized_unversioned.manifests[precise]; + manifest.dependencies.values().cloned().collect() + } + + pub fn index_deps(&self, id: &Id, version: &SemanticVersion) -> Vec { + let all_versions = self.index.all_versions(id); + let pkg = all_versions.get(version).unwrap(); + pkg.deps + .iter() + .map(|(_, IndexDependency { id, req })| Dependency::Index { + id: id.clone(), + version: req.clone(), + }) + .collect() + } +} + +fn bucket_versions( + vs: impl Iterator, +) -> impl Iterator { + let mut vs: Vec<_> = vs + .map(BucketVersion::from) + .map(SemanticVersion::from) + .collect(); + vs.sort(); + vs.dedup(); + vs.into_iter() +} + +/// The same as [`Dependency`], but only for the packages that have fixed, unresolvable, versions. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub enum UnversionedPackage { + Git { url: gix::Url }, + Path { path: PathBuf }, +} + +impl From for Dependency { + fn from(p: UnversionedPackage) -> Self { + match p { + UnversionedPackage::Git { url } => Dependency::Git { url }, + UnversionedPackage::Path { path } => Dependency::Path { path }, + } + } +} + +/// A bucket version represents a collection of compatible semver versions. +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub enum BucketVersion { + /// A collection of versions all having the same major version number. + /// (For example, 1.x.y) + Major(u32), + /// A collection of versions all having major version zero, and the same minor version number. + /// (For example, 0.2.x) + Minor(u32), +} + +impl std::fmt::Display for BucketVersion { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BucketVersion::Major(v) => write!(f, "{v}"), + BucketVersion::Minor(v) => write!(f, "0.{v}"), + } + } +} + +impl BucketVersion { + pub fn contains(&self, semver: SemanticVersion) -> bool { + let (major, minor, _) = semver.into(); + match *self { + BucketVersion::Major(v) => v == major, + BucketVersion::Minor(v) => major == 0 && minor == v, + } + } + + pub fn next(&self) -> BucketVersion { + match *self { + BucketVersion::Major(v) => BucketVersion::Major(v + 1), + BucketVersion::Minor(v) => BucketVersion::Minor(v + 1), + } + } + + pub fn intersects(&self, req: &VersionReq) -> bool { + req.comparators + .iter() + .all(|c| self.intersects_constraint(c)) + } + + pub fn intersects_constraint(&self, comp: &Comparator) -> bool { + let maj = comp.major as u32; // TODO: avoid casts + let min = comp.minor.unwrap_or_default() as u32; + let comp_version = SemanticVersion::new(maj, min, 0); + + let slf: SemanticVersion = (*self).into(); + let next: SemanticVersion = self.next().into(); + let range = slf..next; + match comp.op { + semver::Op::Exact => range.contains(&comp_version), + semver::Op::Greater => next > comp_version, + semver::Op::GreaterEq => next > comp_version, + semver::Op::Less => slf < comp_version, + semver::Op::LessEq => slf <= comp_version, + semver::Op::Tilde => range.contains(&comp_version), + semver::Op::Caret => range.contains(&comp_version), + semver::Op::Wildcard => true, + // This is silly. Semver insists on having op be non_exhaustive (https://github.com/dtolnay/semver/issues/262) + // even though the addition of new ops should (IMO) be semver-breaking. We don't + // expect any other ops, but we have to handle them somehow. + _ => false, + } + } + + pub fn compatible_range(&self) -> VersionRange { + VersionRange::between( + SemanticVersion::from(*self), + SemanticVersion::from(self.next()), + ) + } +} + +impl From for BucketVersion { + fn from(v: SemanticVersion) -> Self { + let (major, minor, _) = v.into(); + if major == 0 { + BucketVersion::Minor(minor) + } else { + BucketVersion::Major(major) + } + } +} + +impl From for SemanticVersion { + fn from(bv: BucketVersion) -> Self { + match bv { + BucketVersion::Major(v) => SemanticVersion::new(v, 0, 0), + BucketVersion::Minor(v) => SemanticVersion::new(0, v, 0), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct Bucket { + pub id: Id, + pub version: BucketVersion, +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub enum Package { + /// A package that only comes in one version (like a path or a git dependency). + /// TODO: right now we say that all unversioned packages have version `0.0.0`, but it + /// isn't great for error messages + Unversioned(UnversionedPackage), + Bucket(Bucket), +} + +impl std::fmt::Display for Package { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Package::Unversioned(UnversionedPackage::Git { url }) => { + write!(f, "{url}") + } + Package::Unversioned(UnversionedPackage::Path { path }) => { + write!(f, "{}", path.display()) + } + Package::Bucket(b) => { + write!(f, "{}#{}", b.id, b.version) + } + } + } +} + +// Makes the precise less precise, by returning the bucket that it falls into. +impl From for Package { + fn from(p: Precise) -> Self { + match p { + Precise::Git { repo, .. } => { + Package::Unversioned(UnversionedPackage::Git { url: repo }) + } + Precise::Path { path } => Package::Unversioned(UnversionedPackage::Path { path }), + Precise::Index { id, version } => Package::Bucket(Bucket { + id, + version: semver_to_pg(version).into(), + }), + } + } +} + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub enum VirtualPackage { + Package(Package), + Union { + source: Package, + source_version: SemanticVersion, + target: Id, + }, +} + +fn proxify_dep(pkg: &Package, pkg_version: SemanticVersion, dep: Dependency) -> VirtualPackage { + match dep { + Dependency::Git { url } => { + VirtualPackage::Package(Package::Unversioned(UnversionedPackage::Git { url })) + } + Dependency::Path { path } => { + VirtualPackage::Package(Package::Unversioned(UnversionedPackage::Path { path })) + } + // We're making a proxy for every dependency on a repo package, but we could skip + // the proxy if the dependency range stays within a single semver range. + Dependency::Index { id, .. } => VirtualPackage::Union { + source: pkg.clone(), + source_version: pkg_version, + target: id, + }, + } +} + +impl std::fmt::Display for VirtualPackage { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + VirtualPackage::Package(b) => b.fmt(f), + VirtualPackage::Union { + source, + source_version, + target, + } => write!(f, "{}@{}->{}", source, source_version, target), + } + } +} + +impl DependencyProvider for PackageRegistry { + fn choose_package_version< + T: Borrow, + U: Borrow>, + >( + &self, + potential_packages: impl Iterator, + ) -> Result<(T, Option), Box> { + // We try to choose the package with the fewest available versions, as the pubgrub + // docs recommend this as a reasonably-performant heuristic. We count a previously locked package + // as having one version (even if we'd theoretically be willing to ignore the lock). + let count_valid = |(p, range): &(T, U)| { + if self.previously_locked.contains_key(p.borrow()) { + 1 + } else { + self.list_versions(p.borrow()) + .filter(|v| range.borrow().contains(v)) + .count() + } + }; + let (pkg, range) = potential_packages + .min_by_key(count_valid) + .expect("potential_packages gave us an empty iterator"); + let version = self + .list_versions(pkg.borrow()) + .find(|v| range.borrow().contains(v)); + Ok((pkg, version)) + } + + fn get_dependencies( + &self, + package: &VirtualPackage, + version: &SemanticVersion, + ) -> Result< + pubgrub::solver::Dependencies, + Box, + > { + match package { + VirtualPackage::Package(b @ Package::Unversioned(p)) => { + let deps = self + .unversioned_deps(p) + .into_iter() + .map(|dep| (proxify_dep(b, *version, dep), VersionRange::any())) + .collect(); + Ok(pubgrub::solver::Dependencies::Known(deps)) + } + VirtualPackage::Package(Package::Bucket(b)) => { + let deps = self + .index_deps(&b.id, version) + .into_iter() + .map(|dep| { + ( + proxify_dep(&Package::Bucket(b.clone()), *version, dep), + VersionRange::any(), + ) + }) + .collect(); + Ok(pubgrub::solver::Dependencies::Known(deps)) + } + VirtualPackage::Union { + source, + source_version, + target, + } => { + // A proxy package depends on a single package: its target bucket with the + // same version as itself. + let bucket_version = (*version).into(); + let dep = Bucket { + id: target.clone(), + version: bucket_version, + }; + let range = version_req_to_range(&self.dep(source, source_version, target)); + let bucket_range = bucket_version.compatible_range().intersection(&range); + let deps: HashMap<_, _, _> = + std::iter::once((VirtualPackage::Package(Package::Bucket(dep)), bucket_range)) + .collect(); + Ok(pubgrub::solver::Dependencies::Known(deps)) + } + } + } +} + +fn version_req_to_range(req: &VersionReq) -> pubgrub::range::Range { + use pubgrub::range::Range; + + let mut ret = pubgrub::range::Range::any(); + + fn comp_to_range(comp: &Comparator) -> pubgrub::range::Range { + let v = SemanticVersion::new( + comp.major as u32, + comp.minor.unwrap_or_default() as u32, + comp.patch.unwrap_or_default() as u32, + ); + match comp.op { + semver::Op::Exact => Range::exact(v), + semver::Op::Greater => Range::higher_than(v.bump()), + semver::Op::GreaterEq => Range::higher_than(v), + semver::Op::Less => Range::strictly_lower_than(v), + semver::Op::LessEq => Range::strictly_lower_than(v).union(&Range::exact(v)), + semver::Op::Tilde => { + if comp.minor.is_some() { + Range::between(v, v.bump_minor()) + } else { + Range::between(v, v.bump_major()) + } + } + semver::Op::Caret => { + if comp.major == 0 { + Range::between(v, v.bump_minor()) + } else { + Range::between(v, v.bump_major()) + } + } + semver::Op::Wildcard => Range::any(), + _ => panic!("unknown op"), + } + } + + for comp in &req.comparators { + ret = ret.intersection(&comp_to_range(comp)); + } + + ret +} + +pub struct Resolution { + pub realization: Realization, + pub package_map: HashMap>, + pub index: PackageIndex, +} + +pub fn resolve(manifest: &ManifestFile) -> Result { + resolve_with_lock(manifest, &LockFile::default()) +} + +fn previously_locked( + top_level: &Package, + lock: &LockFile, +) -> HashMap { + fn precise_to_index(p: &Precise) -> Option { + match p { + Precise::Index { id, version } => Some(IndexPrecise { + id: id.clone(), + version: version.clone(), + }), + _ => None, + } + } + + // A list of (package: Package, version of the package: SemanticVersion, dependency: IndexPrecise) + let pkg_deps = lock + .dependencies + .values() + .filter_map(precise_to_index) + // FIXME: another place we're hardcoding an unversioned version + .map(|dep| (top_level.clone(), SemanticVersion::zero(), dep)) + .chain(lock.packages.iter().flat_map(|(parent, entry)| { + let pkg = Package::from(parent.clone()); + let pkg_version = parent + .version() + .map(semver_to_pg) + .unwrap_or(SemanticVersion::zero()); + entry + .dependencies + .values() + .filter_map(precise_to_index) + .map(move |v| (pkg.clone(), pkg_version, v)) + })); + + // Because of the virtual package system, each parent->dep needs two entries + // in the locked map: one for recording which of the "union" packages the parent + // depends on, and another for recording which precise version the "union" package depends on. + pkg_deps + .flat_map(|(pkg, version, dep)| { + let dep_version = semver_to_pg(dep.version); + let dep_bucket: BucketVersion = dep_version.into(); + [ + ( + VirtualPackage::Union { + source: pkg, + source_version: version, + target: dep.id.clone(), + }, + dep_bucket.into(), + ), + ( + VirtualPackage::Package(Package::Bucket(Bucket { + id: dep.id, + version: dep_bucket, + })), + dep_version, + ), + ] + }) + .collect() +} + +pub fn resolve_with_lock(manifest: &ManifestFile, lock: &LockFile) -> Result { + let mut realization = Realization::default(); + + // pubgrub insists on resolving a top-level package. We'll represent it as a `Path` dependency, + // so it needs a path... + let root_path = manifest.parent_dir.as_deref(); + for dep in manifest.dependencies.values() { + realization.realize_all(root_path, dep, None)?; + } + // The top-level package doesn't matter for resolution, but it might appear in error messages. + // Try to give it an informative name. + let top_level_path = root_path.unwrap_or(Path::new("/dummy-package")); + let top_level_dep = UnversionedPackage::Path { + path: top_level_path.to_path_buf(), + }; + let top_level = VirtualPackage::Package(Package::Unversioned(top_level_dep.clone())); + let precise = Precise::Path { + path: top_level_path.to_path_buf(), + }; + realization + .precise + .insert(top_level_dep.clone().into(), precise.clone()); + realization.manifests.insert(precise, manifest.clone()); + + let registry = PackageRegistry { + previously_locked: dbg!(previously_locked( + &Package::Unversioned(top_level_dep), + lock + )), + index: PackageIndex::new(), + realized_unversioned: realization, + }; + registry.index.refresh_from_github(); + + let resolution = match pubgrub::solver::resolve(®istry, top_level, SemanticVersion::zero()) { + Ok(r) => r, + Err(pubgrub::error::PubGrubError::NoSolution(derivation_tree)) => { + //derivation_tree.collapse_no_versions(); + let msg = DefaultStringReporter::report(&derivation_tree); + return Err(Error::Resolution { msg }); + } + Err(e) => return Err(Error::Resolution { msg: e.to_string() }), + }; + let mut selected = HashMap::>::new(); + for (virt, vers) in resolution.iter() { + if let VirtualPackage::Package(Package::Bucket(Bucket { id, .. })) = virt { + let (major, minor, patch) = (*vers).into(); + selected + .entry(id.clone()) + .or_default() + .push(semver::Version::new( + major.into(), + minor.into(), + patch.into(), + )); + } + } + Ok(Resolution { + realization: registry.realized_unversioned, + index: registry.index, + package_map: selected, + }) +} + +impl Resolution { + /// Finds the precise resolved version of this dependency. + /// + /// # Panics + /// + /// Panics if the dependency was not part of the dependency tree that this resolution + /// was generated for. + pub fn precise(&self, dep: &Dependency) -> Precise { + match dep { + Dependency::Git { url } => Precise::Git { + repo: url.clone(), + id: self.realization.git[url], + path: PathBuf::new(), + }, + Dependency::Path { path } => Precise::Path { + path: path.to_owned(), + }, + Dependency::Index { id, version } => Precise::Index { + id: id.clone(), + version: self.package_map[id] + .iter() + .filter(|v| version.matches(v)) + .max() + .unwrap() + .clone(), + }, + } + } + + /// Returns all the dependencies of a package, along with their package-local names. + pub fn dependencies(&self, pkg: &Precise) -> HashMap { + match pkg { + p @ Precise::Git { .. } | p @ Precise::Path { .. } => { + let manifest = &self.realization.manifests[p]; + manifest + .dependencies + .iter() + .map(move |(dep_name, dep)| (*dep_name, self.precise(dep))) + .collect() + } + Precise::Index { id, version } => { + let pkg = self + .index + .package( + id, + SemanticVersion::new( + version.major as u32, + version.minor as u32, + version.patch as u32, + ), + ) + .unwrap(); + pkg.deps + .into_iter() + .map(move |(dep_name, dep)| { + let precise_dep = self.precise(&Dependency::Index { + id: dep.id.clone(), + version: dep.req.clone(), + }); + (dep_name, precise_dep) + }) + .collect() + } + } + } + + /// Returns all the resolved packages in the dependency tree. + pub fn all_precises(&self) -> Vec { + let mut ret: Vec<_> = self.realization.precise.values().cloned().collect(); + ret.sort(); + ret.dedup(); + + let index_precises = self.package_map.iter().flat_map(|(id, vs)| { + vs.iter().map(|v| Precise::Index { + id: id.clone(), + version: v.clone(), + }) + }); + ret.extend(index_precises); + ret + } + + pub fn package_map(&self, manifest: &ManifestFile) -> Result { + // TODO: we can still make a package map without a root directory; we just have to disallow + // relative path dependencies + let root_path = normalize_path(manifest.parent_dir.clone().unwrap()).without_path()?; + + let all = self.all_precises(); + + Ok(PackageMap { + // Copy over dependencies of the root, making paths absolute. + top_level: manifest + .dependencies + .iter() + .map(|(name, source)| { + ( + *name, + self.precise(source).with_abs_path(&root_path).local_path(), + ) + }) + .collect(), + + packages: all + .iter() + .flat_map(|p| { + let p_path = p.clone().with_abs_path(&root_path).local_path(); + let root_path = &root_path; + self.dependencies(p) + .into_iter() + .map(move |(dep_id, dep_precise)| { + ( + (p_path.clone(), dep_id), + dep_precise.with_abs_path(root_path).local_path(), + ) + }) + }) + .collect(), + }) + } + + pub fn lock_file(&self, manifest: &ManifestFile) -> Result { + // We don't put all packages in the lock file: we ignore dependencies (and therefore also + // transitive dependencies) of path deps. In order to figure out what to include, we + // traverse the depencency graph. + fn collect_packages( + slf: &Resolution, + pkg: &Precise, + acc: &mut HashMap, + ) { + let entry = LockFileEntry { + dependencies: if pkg.is_path() { + // Skip dependencies of path deps + Default::default() + } else { + slf.dependencies(pkg) + }, + }; + + // Only recurse if this is the first time we've encountered this precise package. + if acc.insert(pkg.clone(), entry).is_none() { + for (_, dep) in acc[pkg].clone().dependencies { + collect_packages(slf, &dep, acc); + } + } + } + + let mut acc = HashMap::new(); + for dep in manifest.dependencies.values() { + collect_packages(self, &self.precise(dep), &mut acc); + } + + Ok(LockFile { + dependencies: manifest + .dependencies + .iter() + .map(|(name, dep)| (*name, self.precise(dep))) + .collect(), + + packages: acc, + }) + } +} diff --git a/package/src/util.rs b/package/src/util.rs new file mode 100644 index 0000000000..75d4d5877f --- /dev/null +++ b/package/src/util.rs @@ -0,0 +1,37 @@ +use std::path::PathBuf; + +use directories::ProjectDirs; +use pubgrub::version::SemanticVersion; +use tempfile::{tempdir_in, TempDir}; + +use crate::index::Id; + +pub fn cache_dir() -> PathBuf { + let dir = ProjectDirs::from("org", "nickel-lang", "nickel").unwrap(); + dir.cache_dir().to_owned() +} + +pub fn clone_git(url: Url) -> anyhow::Result<(TempDir, gix::Repository)> +where + Url: TryInto, + gix::url::parse::Error: From, +{ + let cache_dir = cache_dir(); + std::fs::create_dir_all(&cache_dir)?; + let tmp_dir = tempdir_in(&cache_dir)?; + let (mut prepare_checkout, _) = gix::prepare_clone(url, &tmp_dir)? + .fetch_then_checkout(gix::progress::Discard, &gix::interrupt::IS_INTERRUPTED)?; + let (repo, _) = + prepare_checkout.main_worktree(gix::progress::Discard, &gix::interrupt::IS_INTERRUPTED)?; + + Ok((tmp_dir, repo)) +} + +pub fn clone_github(id: &Id) -> anyhow::Result<(TempDir, gix::Repository)> { + let url = format!("https://github.com/{}/{}.git", id.org, id.name); + clone_git(url.as_str()) +} + +pub fn semver_to_pg(v: semver::Version) -> SemanticVersion { + SemanticVersion::new(v.major as u32, v.minor as u32, v.patch as u32) +} diff --git a/test.ncl b/test.ncl new file mode 100644 index 0000000000..dad35cb2b1 --- /dev/null +++ b/test.ncl @@ -0,0 +1 @@ +let ctr = fun foo label value => value in [100, 200] | Array (ctr 1)