diff --git a/Cargo.lock b/Cargo.lock index 8f5e13af..9a1e84d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -19,14 +19,13 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.7.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", "cpufeatures", - "opaque-debug", ] [[package]] @@ -76,47 +75,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -124,9 +124,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayvec" @@ -161,27 +161,25 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.3.0", - "event-listener-strategy 0.5.1", + "event-listener-strategy", "futures-core", "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98c37cf288e302c16ef6c8472aad1e034c6c84ce5ea7b8101c98eb4a802fee" +checksum = "c8828ec6e544c02b0d6691d21ed9f9218d0384a82542855073c2a3f58304aaf0" dependencies = [ - "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-lite 2.3.0", "slab", ] @@ -220,18 +218,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" dependencies = [ - "async-lock 3.3.0", + "async-lock 3.4.0", "cfg-if", "concurrent-queue", "futures-io", "futures-lite 2.3.0", "parking", - "polling 3.6.0", - "rustix 0.38.32", + "polling 3.7.2", + "rustix 0.38.34", "slab", "tracing", "windows-sys 0.52.0", @@ -248,12 +246,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", + "event-listener 5.3.1", + "event-listener-strategy", "pin-project-lite", ] @@ -270,44 +268,44 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.48.0", ] [[package]] name = "async-recursion" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "async-signal" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" dependencies = [ - "async-io 2.3.2", - "async-lock 2.8.0", + "async-io 2.3.3", + "async-lock 3.4.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.32", + "rustix 0.38.34", "signal-hook-registry", "slab", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "async-task" -version = "4.7.0" +version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" @@ -317,7 +315,7 @@ checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -339,9 +337,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" @@ -366,7 +364,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustversion", - "serde 1.0.197", + "serde 1.0.203", "serde_json", "serde_path_to_error", "serde_urlencoded", @@ -408,14 +406,14 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -432,6 +430,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -487,35 +491,25 @@ dependencies = [ ] [[package]] -name = "block-modes" -version = "0.8.1" +name = "block-padding" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "block-padding", - "cipher", + "generic-array", ] -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - [[package]] name = "blocking" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" dependencies = [ "async-channel", - "async-lock 3.3.0", "async-task", - "fastrand 2.0.2", "futures-io", "futures-lite 2.3.0", "piper", - "tracing", ] [[package]] @@ -525,8 +519,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", - "regex-automata", - "serde 1.0.197", + "regex-automata 0.4.7", + "serde 1.0.203", ] [[package]] @@ -549,11 +543,11 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -579,28 +573,29 @@ dependencies = [ "rand_core", "rpassword", "semver", - "serde 1.0.197", + "serde 1.0.203", "serde_json", "shell-escape", "tempfile", "tokio", "tokio-util", - "toml_edit 0.22.9", + "toml_edit 0.22.14", "url", "warg-client", "warg-crypto", "warg-protocol", "warg-server", "wasi-preview1-component-adapter-provider", - "wasm-metadata", + "wasm-metadata 0.208.1", + "wasm-pkg-client", "wasmparser 0.208.1", "wasmprinter 0.208.1", "wat", "which", "wit-bindgen-core", "wit-bindgen-rust", - "wit-component", - "wit-parser", + "wit-component 0.208.1", + "wit-parser 0.208.1", ] [[package]] @@ -609,35 +604,38 @@ version = "0.15.0-dev" dependencies = [ "anyhow", "clap", + "dirs", "futures", "indexmap 2.2.6", "libc", "log", "owo-colors", "semver", - "serde 1.0.197", + "serde 1.0.203", "tokio", - "toml_edit 0.22.9", + "tokio-util", + "toml_edit 0.22.14", "unicode-width", "url", "warg-client", "warg-crypto", "warg-protocol", + "wasm-pkg-client", "windows-sys 0.52.0", - "wit-component", - "wit-parser", + "wit-component 0.208.1", + "wit-parser 0.208.1", ] [[package]] name = "cargo-config2" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d9bdc858a15454c2d0a5138d8dcf4bcabc06fde679abdea8330393fbc0ef05" +checksum = "d83ce0be8bd1479e5de6202def660e6c7e27e4e0599bffa4fed05bd380ec2ede" dependencies = [ "home", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", - "toml_edit 0.22.9", + "toml_edit 0.22.14", ] [[package]] @@ -646,7 +644,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -658,16 +656,25 @@ dependencies = [ "camino", "cargo-platform", "semver", - "serde 1.0.197", + "serde 1.0.203", "serde_json", "thiserror", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" -version = "1.0.92" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -677,31 +684,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", - "num-traits 0.2.18", - "serde 1.0.197", + "js-sys", + "num-traits 0.2.19", + "serde 1.0.203", + "wasm-bindgen", "windows-targets 0.52.5", ] [[package]] name = "cipher" -version = "0.3.0" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "generic-array", + "crypto-common", + "inout", ] [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -709,45 +719,45 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -761,7 +771,7 @@ dependencies = [ "lazy_static 1.4.0", "nom", "rust-ini", - "serde 1.0.197", + "serde 1.0.203", "serde-hjson", "serde_json", "toml 0.5.11", @@ -814,9 +824,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 = "crypto-bigint" @@ -842,9 +852,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -852,27 +862,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", - "syn 2.0.58", + "strsim", + "syn 2.0.66", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -893,7 +903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -979,12 +989,34 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "doc-comment" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +[[package]] +name = "docker_credential" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31951f49556e34d90ed28342e1df7e1cb7a229c4cab0aecc627b5d91edd41d07" +dependencies = [ + "base64 0.21.7", + "serde 1.0.203", + "serde_json", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -1001,9 +1033,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -1042,23 +1074,23 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" dependencies = [ "enumflags2_derive", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] name = "enumflags2_derive" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -1082,9 +1114,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", @@ -1109,20 +1141,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.3.0" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1131,21 +1152,11 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 5.3.0", + "event-listener 5.3.1", "pin-project-lite", ] @@ -1160,9 +1171,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "ff" @@ -1186,7 +1197,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] @@ -1288,7 +1299,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-core", "futures-io", "parking", @@ -1303,7 +1314,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -1349,9 +1360,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1360,9 +1371,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "group" @@ -1377,15 +1388,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap 2.2.6", "slab", @@ -1402,12 +1413,12 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -1437,6 +1448,12 @@ 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 = "hex" version = "0.4.3" @@ -1481,6 +1498,15 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-auth" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643c9bbf6a4ea8a656d6b4cd53d34f79e3f841ad5203c1a55fb7d761923bc255" +dependencies = [ + "memchr", +] + [[package]] name = "http-body" version = "1.0.0" @@ -1493,12 +1519,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -1506,15 +1532,15 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce4ef31cda248bbdb6e6820603b82dfcd9e833db65a43e997a0ccec777d11fe" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1530,9 +1556,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", @@ -1549,6 +1575,23 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.6.0" @@ -1567,9 +1610,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -1578,7 +1621,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.5.7", "tokio", "tower", "tower-service", @@ -1608,6 +1651,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "id-arena" version = "2.2.1" @@ -1622,12 +1783,14 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -1652,7 +1815,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -1662,15 +1825,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.3", - "serde 1.0.197", + "hashbrown 0.14.5", + "serde 1.0.203", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", ] [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -1703,6 +1876,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.11.0" @@ -1736,6 +1915,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jwt" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f" +dependencies = [ + "base64 0.13.1", + "crypto-common", + "digest", + "hmac", + "serde 1.0.203", + "serde_json", + "sha2", +] + [[package]] name = "keyring" version = "2.3.3" @@ -1783,9 +1977,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -1821,15 +2015,21 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[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", @@ -1841,36 +2041,13 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" -[[package]] -name = "logos" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1" -dependencies = [ - "logos-derive 0.13.0", -] - [[package]] name = "logos" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "161971eb88a0da7ae0c333e1063467c5b5727e7fb6b710b8db4814eade3a42e8" dependencies = [ - "logos-derive 0.14.0", -] - -[[package]] -name = "logos-codegen" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68" -dependencies = [ - "beef", - "fnv", - "proc-macro2", - "quote", - "regex-syntax 0.6.29", - "syn 2.0.58", + "logos-derive", ] [[package]] @@ -1884,26 +2061,26 @@ dependencies = [ "lazy_static 1.4.0", "proc-macro2", "quote", - "regex-syntax 0.8.3", - "syn 2.0.58", + "regex-syntax 0.8.4", + "syn 2.0.66", ] [[package]] name = "logos-derive" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e" +checksum = "1c2a69b3eb68d5bd595107c9ee58d7e07fe2bb5e360cc85b0f084dedac80de0a" dependencies = [ - "logos-codegen 0.13.0", + "logos-codegen", ] [[package]] -name = "logos-derive" -version = "0.14.0" +name = "matchers" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c2a69b3eb68d5bd595107c9ee58d7e07fe2bb5e360cc85b0f084dedac80de0a" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "logos-codegen 0.14.0", + "regex-automata 0.1.10", ] [[package]] @@ -1914,9 +2091,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -1956,7 +2133,7 @@ checksum = "dcf09caffaac8068c346b6df2a7fc27a177fd20b39421a39ce0a211bde679a6c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -1977,9 +2154,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] @@ -2003,11 +2180,10 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static 1.4.0", "libc", "log", "openssl", @@ -2069,36 +2245,35 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", "num-rational", - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] @@ -2113,30 +2288,29 @@ version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] @@ -2145,14 +2319,14 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[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", ] @@ -2169,24 +2343,71 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] [[package]] -name = "once_cell" -version = "1.19.0" +name = "oci-distribution" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "b95a2c51531af0cb93761f66094044ca6ea879320bccd35ab747ff3fcab3f422" +dependencies = [ + "bytes", + "chrono", + "futures-util", + "http", + "http-auth", + "jwt", + "lazy_static 1.4.0", + "olpc-cjson", + "regex", + "reqwest", + "serde 1.0.203", + "serde_json", + "sha2", + "thiserror", + "tokio", + "tracing", + "unicase", +] [[package]] -name = "opaque-debug" -version = "0.3.1" +name = "oci-wasm" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +checksum = "a91502e5352f927156f2b6a28d2558cc59558b1f441b681df3f706ced6937e07" +dependencies = [ + "anyhow", + "chrono", + "oci-distribution", + "serde 1.0.203", + "serde_json", + "sha2", + "tokio", + "wit-component 0.209.1", + "wit-parser 0.209.1", +] + +[[package]] +name = "olpc-cjson" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d637c9c15b639ccff597da8f4fa968300651ad2f1e968aefc3b4927a6fb2027a" +dependencies = [ + "serde 1.0.203", + "serde_json", + "unicode-normalization", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" @@ -2211,7 +2432,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2244,7 +2465,7 @@ version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" dependencies = [ - "num-traits 0.2.18", + "num-traits 0.2.19", ] [[package]] @@ -2289,9 +2510,9 @@ checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[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", @@ -2299,15 +2520,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.5", ] [[package]] @@ -2329,7 +2550,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" dependencies = [ "base64 0.21.7", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -2356,7 +2577,7 @@ dependencies = [ "pbjson-build", "prost", "prost-build", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -2376,9 +2597,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", "indexmap 2.2.6", @@ -2401,7 +2622,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2418,12 +2639,12 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" dependencies = [ "atomic-waker", - "fastrand 2.0.2", + "fastrand 2.1.0", "futures-io", ] @@ -2461,15 +2682,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.6.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi 0.3.9", + "hermit-abi 0.4.0", "pin-project-lite", - "rustix 0.38.32", + "rustix 0.38.34", "tracing", "windows-sys 0.52.0", ] @@ -2528,12 +2749,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2557,18 +2778,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" dependencies = [ "bytes", "prost-derive", @@ -2576,9 +2797,9 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b776a1b2dc779f5ee0641f8ade0125bc1298dd41a9a0c16d8bd57b42d222b1" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", "heck 0.5.0", @@ -2591,21 +2812,21 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.58", + "syn 2.0.66", "tempfile", ] [[package]] name = "prost-derive" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19de2de2a00075bf566bee3bd4db014b11587e84184d3f7a791bc17f1a8e9e48" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -2614,7 +2835,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f5eec97d5d34bdd17ad2db2219aabf46b054c6c41bd5529767c9ce55be5898f" dependencies = [ - "logos 0.14.0", + "logos", "miette", "once_cell", "prost", @@ -2623,18 +2844,18 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.4" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3235c33eb02c1f1e212abdbe34c78b264b038fb58ca612664343271e36e55ffe" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" dependencies = [ "prost", ] [[package]] name = "protox" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a29b3c5596eb23a849deba860b53ffd468199d9ad5fe4402a7d55379e16aa2d2" +checksum = "ac532509cee918d40f38c3e12f8ef9230f215f017d54de7dd975015538a42ce7" dependencies = [ "bytes", "miette", @@ -2647,11 +2868,11 @@ dependencies = [ [[package]] name = "protox-parse" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033b939d76d358f7c32120c86c71f515bae45e64f2bde455200356557276276c" +checksum = "7f6c33f43516fe397e2f930779d720ca12cd057f7da4cd6326a0ef78d69dee96" dependencies = [ - "logos 0.13.0", + "logos", "miette", "prost-types", "thiserror", @@ -2668,7 +2889,7 @@ dependencies = [ "config", "directories", "petgraph", - "serde 1.0.197", + "serde 1.0.203", "serde-value", "tint", ] @@ -2723,11 +2944,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -2743,25 +2964,34 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] @@ -2772,15 +3002,15 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -2792,6 +3022,7 @@ dependencies = [ "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", "hyper-util", "ipnet", @@ -2803,10 +3034,10 @@ dependencies = [ "percent-encoding", "pin-project-lite", "rustls-pemfile", - "serde 1.0.197", + "serde 1.0.203", "serde_json", "serde_urlencoded", - "sync_wrapper 0.1.2", + "sync_wrapper 1.0.1", "system-configuration", "tokio", "tokio-native-tls", @@ -2831,6 +3062,21 @@ dependencies = [ "subtle", ] +[[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 = "rpassword" version = "7.3.1" @@ -2860,9 +3106,9 @@ checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" @@ -2880,17 +3126,30 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys 0.4.13", + "linux-raw-sys 0.4.14", "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -2907,17 +3166,28 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.102.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2963,35 +3233,36 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" dependencies = [ + "serde 1.0.203", "zeroize", ] [[package]] name = "secret-service" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95" +checksum = "b5204d39df37f06d1944935232fd2dfe05008def7ca599bf28c0800366c8a8f9" dependencies = [ "aes", - "block-modes", + "cbc", "futures-util", "generic-array", "hkdf", "num", "once_cell", "rand", - "serde 1.0.197", + "serde 1.0.203", "sha2", "zbus", ] [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -3000,9 +3271,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -3010,11 +3281,11 @@ dependencies = [ [[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 1.0.197", + "serde 1.0.203", ] [[package]] @@ -3025,9 +3296,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -3051,29 +3322,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" dependencies = [ "ordered-float", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -3083,7 +3354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -3094,16 +3365,16 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -3115,21 +3386,21 @@ dependencies = [ "form_urlencoded", "itoa", "ryu", - "serde 1.0.197", + "serde 1.0.203", ] [[package]] name = "serde_with" -version = "3.7.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", "indexmap 2.2.6", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", "serde_json", "serde_with_macros", @@ -3138,14 +3409,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3157,7 +3428,7 @@ dependencies = [ "indexmap 2.2.6", "itoa", "ryu", - "serde 1.0.197", + "serde 1.0.203", "unsafe-libyaml", ] @@ -3219,9 +3490,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[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", ] @@ -3273,9 +3544,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3283,13 +3554,19 @@ dependencies = [ [[package]] name = "spdx" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ef1a0fa1e39ac22972c8db23ff89aea700ab96aa87114e1fb55937a631a0c9" +checksum = "47317bbaf63785b53861e1ae2d11b80d6b624211d42cb20efcd210ee6f8a14bc" dependencies = [ "smallvec", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "spki" version = "0.7.3" @@ -3301,16 +3578,16 @@ dependencies = [ ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "stable_deref_trait" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] -name = "strsim" -version = "0.10.0" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strsim" @@ -3337,9 +3614,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.58" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3358,6 +3635,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3386,8 +3674,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.2", - "rustix 0.38.32", + "fastrand 2.1.0", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -3408,22 +3696,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3446,7 +3734,7 @@ dependencies = [ "itoa", "num-conv", "powerfmt", - "serde 1.0.197", + "serde 1.0.203", "time-core", "time-macros", ] @@ -3476,6 +3764,16 @@ dependencies = [ "lazy_static 0.2.11", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -3493,9 +3791,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3505,20 +3803,20 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.6", + "socket2 0.5.7", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3531,6 +3829,17 @@ dependencies = [ "tokio", ] +[[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-socks" version = "0.5.1" @@ -3545,16 +3854,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -3563,28 +3871,28 @@ version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", ] [[package]] name = "toml" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", "serde_spanned", "toml_datetime", - "toml_edit 0.22.9", + "toml_edit 0.22.14", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", ] [[package]] @@ -3600,15 +3908,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.9" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ "indexmap 2.2.6", - "serde 1.0.197", + "serde 1.0.203", "serde_spanned", "toml_datetime", - "winnow 0.6.6", + "winnow 0.6.13", ] [[package]] @@ -3684,7 +3992,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", ] [[package]] @@ -3714,10 +4022,14 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", "nu-ansi-term", + "once_cell", + "regex", "sharded-slab", "smallvec", "thread_local", + "tracing", "tracing-core", "tracing-log", ] @@ -3754,12 +4066,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -3777,9 +4083,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -3793,23 +4099,41 @@ 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 = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde 1.0.197", + "serde 1.0.203", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[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 = "valuable" @@ -3840,9 +4164,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" @@ -3871,7 +4195,7 @@ checksum = "6a22d3c9026f2f6a628cf386963844cdb7baea3b3419ba090c9096da114f977d" dependencies = [ "indexmap 2.2.6", "itertools 0.12.1", - "serde 1.0.197", + "serde 1.0.203", "serde_with", "thiserror", "warg-crypto", @@ -3903,7 +4227,7 @@ dependencies = [ "reqwest", "secrecy", "semver", - "serde 1.0.197", + "serde 1.0.203", "serde_json", "sha256", "tempfile", @@ -3939,7 +4263,7 @@ dependencies = [ "p256", "rand_core", "secrecy", - "serde 1.0.197", + "serde 1.0.203", "sha2", "signature", "thiserror", @@ -3960,7 +4284,7 @@ dependencies = [ "prost-types", "protox", "regex", - "serde 1.0.197", + "serde 1.0.203", "warg-crypto", ] @@ -3978,7 +4302,7 @@ dependencies = [ "prost", "prost-types", "semver", - "serde 1.0.197", + "serde 1.0.203", "serde_with", "thiserror", "warg-crypto", @@ -4000,12 +4324,12 @@ dependencies = [ "futures", "indexmap 2.2.6", "secrecy", - "serde 1.0.197", + "serde 1.0.203", "tempfile", "thiserror", "tokio", "tokio-util", - "toml 0.8.12", + "toml 0.8.14", "tower", "tower-http", "tracing", @@ -4065,7 +4389,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -4099,7 +4423,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4122,7 +4446,7 @@ dependencies = [ "indexmap 2.2.6", "log", "petgraph", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", "serde_yaml", "smallvec", @@ -4150,6 +4474,24 @@ dependencies = [ "leb128", ] +[[package]] +name = "wasm-encoder" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4a05336882dae732ce6bd48b7e11fe597293cb72c13da4f35d7d5f8d53b2a7" +dependencies = [ + "leb128", +] + +[[package]] +name = "wasm-encoder" +version = "0.210.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e3764d9d6edabd8c9e16195e177be0d20f6ab942ad18af52860f12f82bc59a" +dependencies = [ + "leb128", +] + [[package]] name = "wasm-metadata" version = "0.208.1" @@ -4158,7 +4500,7 @@ checksum = "42a2c4280ad374a6db3d76d4bb61e2ec4b3b9ce5469cc4f2bbc5708047a2bbff" dependencies = [ "anyhow", "indexmap 2.2.6", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", "serde_json", "spdx", @@ -4166,6 +4508,73 @@ dependencies = [ "wasmparser 0.208.1", ] +[[package]] +name = "wasm-metadata" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d32029ce424f6d3c2b39b4419fb45a0e2d84fb0751e0c0a32b7ce8bd5d97f46" +dependencies = [ + "anyhow", + "indexmap 2.2.6", + "serde 1.0.203", + "serde_derive", + "serde_json", + "spdx", + "wasm-encoder 0.209.1", + "wasmparser 0.209.1", +] + +[[package]] +name = "wasm-pkg-client" +version = "0.4.1" +source = "git+https://github.com/bytecodealliance/wasm-pkg-tools.git?rev=47ad11a549c23ac48ecee9226d395fc7c6063250#47ad11a549c23ac48ecee9226d395fc7c6063250" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.22.1", + "bytes", + "dirs", + "docker_credential", + "futures-util", + "oci-distribution", + "oci-wasm", + "secrecy", + "serde 1.0.203", + "serde_json", + "sha2", + "thiserror", + "tokio", + "tokio-util", + "toml 0.8.14", + "tracing", + "tracing-subscriber", + "url", + "warg-client", + "warg-protocol", + "wasm-pkg-common", +] + +[[package]] +name = "wasm-pkg-common" +version = "0.4.1" +source = "git+https://github.com/bytecodealliance/wasm-pkg-tools.git?rev=47ad11a549c23ac48ecee9226d395fc7c6063250#47ad11a549c23ac48ecee9226d395fc7c6063250" +dependencies = [ + "anyhow", + "bytes", + "dirs", + "futures-util", + "http", + "reqwest", + "semver", + "serde 1.0.203", + "serde_json", + "sha2", + "thiserror", + "tokio", + "toml 0.8.14", + "tracing", +] + [[package]] name = "wasm-streams" version = "0.4.0" @@ -4198,10 +4607,23 @@ checksum = "dd921789c9dcc495f589cb37d200155dee65b4a4beeb853323b5e24e0a5f9c58" dependencies = [ "ahash", "bitflags 2.5.0", - "hashbrown 0.14.3", + "hashbrown 0.14.5", + "indexmap 2.2.6", + "semver", + "serde 1.0.203", +] + +[[package]] +name = "wasmparser" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07035cc9a9b41e62d3bb3a3815a66ab87c993c06fe1cf6b2a3f2a18499d937db" +dependencies = [ + "ahash", + "bitflags 2.5.0", + "hashbrown 0.14.5", "indexmap 2.2.6", "semver", - "serde 1.0.197", ] [[package]] @@ -4226,22 +4648,22 @@ dependencies = [ [[package]] name = "wast" -version = "208.0.1" +version = "210.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00b3f023b4e2ccd2e054e240294263db52ae962892e6523e550783c83a67f1" +checksum = "aa835c59bd615e00f16be65705d85517d40b44b3c831d724e450244685176c3c" dependencies = [ "bumpalo", "leb128", "memchr", "unicode-width", - "wasm-encoder 0.208.1", + "wasm-encoder 0.210.0", ] [[package]] name = "wat" -version = "1.208.1" +version = "1.210.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ed38e59176550214c025ea2bd0eeefd8e86b92d0af6698d5ba95020ec2e07b" +checksum = "67faece8487996430c6812be7f8776dc563ca0efcd3db77f8839070480c0d1a6" dependencies = [ "wast", ] @@ -4264,7 +4686,7 @@ checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" dependencies = [ "either", "home", - "rustix 0.38.32", + "rustix 0.38.34", "winsafe", ] @@ -4286,11 +4708,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4458,9 +4880,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.6" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0c976aaaa0e1f90dbb21e9587cdaf1d9679a1cde8875c0d6bd83ab96a208352" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -4499,20 +4921,21 @@ dependencies = [ "rand_core", "rpassword", "semver", - "serde 1.0.197", + "serde 1.0.203", "tempfile", "tokio", "tokio-util", - "toml_edit 0.22.9", + "toml_edit 0.22.14", "url", "warg-client", "warg-crypto", "warg-protocol", "warg-server", - "wasm-metadata", + "wasm-metadata 0.208.1", + "wasm-pkg-client", "wasmparser 0.208.1", - "wit-component", - "wit-parser", + "wit-component 0.208.1", + "wit-parser 0.208.1", ] [[package]] @@ -4523,7 +4946,7 @@ checksum = "7076a12e69af6e1f6093bd16657d7ae61c30cfd3c5f62321046eb863b17ab1e2" dependencies = [ "anyhow", "heck 0.5.0", - "wit-parser", + "wit-parser 0.208.1", ] [[package]] @@ -4535,9 +4958,9 @@ dependencies = [ "anyhow", "heck 0.5.0", "indexmap 2.2.6", - "wasm-metadata", + "wasm-metadata 0.208.1", "wit-bindgen-core", - "wit-component", + "wit-component 0.208.1", ] [[package]] @@ -4550,13 +4973,32 @@ dependencies = [ "bitflags 2.5.0", "indexmap 2.2.6", "log", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", "serde_json", "wasm-encoder 0.208.1", - "wasm-metadata", + "wasm-metadata 0.208.1", "wasmparser 0.208.1", - "wit-parser", + "wit-parser 0.208.1", +] + +[[package]] +name = "wit-component" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a2bb5b039f9cb03425e1d5a6e54b441ca4ca1b1d4fa6a0924db67a55168f99" +dependencies = [ + "anyhow", + "bitflags 2.5.0", + "indexmap 2.2.6", + "log", + "serde 1.0.203", + "serde_derive", + "serde_json", + "wasm-encoder 0.209.1", + "wasm-metadata 0.209.1", + "wasmparser 0.209.1", + "wit-parser 0.209.1", ] [[package]] @@ -4570,21 +5012,51 @@ dependencies = [ "indexmap 2.2.6", "log", "semver", - "serde 1.0.197", + "serde 1.0.203", "serde_derive", "serde_json", "unicode-xid", "wasmparser 0.208.1", ] +[[package]] +name = "wit-parser" +version = "0.209.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e79b9e3c0b6bb589dec46317e645851e0db2734c44e2be5e251b03ff4a51269" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.2.6", + "log", + "semver", + "serde 1.0.203", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.209.1", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "xdg-home" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" +checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4596,6 +5068,30 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde 1.0.203", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zbus" version = "3.15.2" @@ -4624,7 +5120,7 @@ dependencies = [ "once_cell", "ordered-stream", "rand", - "serde 1.0.197", + "serde 1.0.203", "serde_repr", "sha1", "static_assertions", @@ -4657,7 +5153,7 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" dependencies = [ - "serde 1.0.197", + "serde 1.0.203", "static_assertions", "zvariant", ] @@ -4679,14 +5175,57 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.58", + "syn 2.0.66", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] [[package]] name = "zvariant" @@ -4697,7 +5236,7 @@ dependencies = [ "byteorder", "enumflags2", "libc", - "serde 1.0.197", + "serde 1.0.203", "static_assertions", "zvariant_derive", ] diff --git a/Cargo.toml b/Cargo.toml index 9d1504bc..460323d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,96 +18,104 @@ keywords = ["webassembly", "wasm", "components", "component-model"] repository = "https://github.com/bytecodealliance/cargo-component" [dependencies] -cargo-component-core = { workspace = true } anyhow = { workspace = true } +bytes = { workspace = true } +cargo_metadata = { workspace = true } +cargo-component-core = { workspace = true } +cargo-config2 = { workspace = true } clap = { workspace = true } -toml_edit = { workspace = true } -pretty_env_logger = { workspace = true } -log = { workspace = true } -tokio = { workspace = true } -tokio-util = { workspace = true } +futures = { workspace = true } heck = { workspace = true } -semver = { workspace = true } -serde = { workspace = true } -serde_json = { workspace = true } indexmap = { workspace = true } -url = { workspace = true } -wit-bindgen-rust = { workspace = true } -wit-bindgen-core = { workspace = true } -wit-parser = { workspace = true } -wit-component = { workspace = true } -wasm-metadata = { workspace = true } -wasmparser = { workspace = true } -parse_arg = { workspace = true } -cargo_metadata = { workspace = true } -cargo-config2 = { workspace = true } libc = { workspace = true } -warg-protocol = { workspace = true } -warg-crypto = { workspace = true } -warg-client = { workspace = true } +log = { workspace = true } p256 = { workspace = true } +parse_arg = { workspace = true } +pretty_env_logger = { workspace = true } rand_core = { workspace = true } rpassword = { workspace = true } -futures = { workspace = true } -bytes = { workspace = true } -which = { workspace = true } +semver = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } shell-escape = "0.1.5" tempfile = { workspace = true } -wasi-preview1-component-adapter-provider = "23.0.1" +tokio = { workspace = true } +tokio-util = { workspace = true } +toml_edit = { workspace = true } +url = { workspace = true } +warg-client = { workspace = true } +warg-crypto = { workspace = true } +warg-protocol = { workspace = true } +wasi-preview1-component-adapter-provider = { workspace = true } +wasm-metadata = { workspace = true } +wasm-pkg-client = { workspace = true } +wasmparser = { workspace = true } +which = { workspace = true } +wit-bindgen-core = { workspace = true } +wit-bindgen-rust = { workspace = true } +wit-component = { workspace = true } +wit-parser = { workspace = true } [dev-dependencies] assert_cmd = { workspace = true } predicates = { workspace = true } -wat = { workspace = true } -warg-server = { workspace = true } tempfile = { workspace = true } +warg-server = { workspace = true } wasmprinter = { workspace = true } +wat = { workspace = true } [workspace] members = ["crates/core", "crates/wit"] [workspace.dependencies] -cargo-component-core = { path = "crates/core", version = "0.15.0-dev" } -warg-protocol = "0.7.0" -warg-crypto = "0.7.0" -warg-client = "0.7.0" -warg-server = "0.7.0" anyhow = "1.0.82" -clap = { version = "4.5.4", features = ["derive"] } -toml_edit = { version = "0.22.9", features = ["serde"] } -pretty_env_logger = "0.5.0" -log = "0.4.21" -tokio = { version = "1.37.0", default-features = false, features = ["macros", "rt-multi-thread"] } -tokio-util = "0.7.10" -heck = "0.5.0" -semver = "1.0.22" -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.115" -indexmap = "2.2.6" -url = { version = "2.5.0", features = ["serde"] } -wit-parser = "0.208.1" -wit-component = "0.208.1" -wasm-metadata = "0.208.1" -parse_arg = "0.1.4" +assert_cmd = "2.0.14" +bytes = "1.6.0" cargo_metadata = "0.18.1" +cargo-component-core = { path = "crates/core", version = "0.15.0-dev" } cargo-config2 = "0.1.24" +clap = { version = "4.5.4", features = ["derive", "env"] } +dirs = "5" +futures = "0.3.30" +heck = "0.5.0" +indexmap = "2.2.6" libc = "0.2.153" +log = "0.4.21" +oci-distribution = "0.11" owo-colors = "4.0.0" -unicode-width = "0.1.11" p256 = "0.13.2" +parse_arg = "0.1.4" +predicates = "3.1.0" +pretty_env_logger = "0.5.0" rand_core = "0.6.4" rpassword = "7.3.1" -futures = "0.3.30" -bytes = "1.6.0" -which = "6.0.1" -wit-bindgen-rust = "0.25.0" -wit-bindgen-core = "0.25.0" +semver = "1" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" tempfile = "3.10.1" -assert_cmd = "2.0.14" -predicates = "3.1.0" +tokio = { version = "1.37.0", default-features = false, features = [ + "macros", + "rt-multi-thread", +] } +tokio-util = "0.7.10" +toml_edit = { version = "0.22.9", features = ["serde"] } +unicode-width = "0.1.11" +url = { version = "2.5.0", features = ["serde"] } +warg-client = "0.7.0" +warg-crypto = "0.7.0" +warg-protocol = "0.7.0" +warg-server = "0.7.0" +wasi-preview1-component-adapter-provider = "23.0.1" +wasm-metadata = "0.208.1" +wasm-pkg-client = { git = "https://github.com/bytecodealliance/wasm-pkg-tools.git", rev = "47ad11a549c23ac48ecee9226d395fc7c6063250" } wasmparser = "0.208.1" -wat = "1.208.1" wasmprinter = "0.208.1" +wat = "1.208.1" +which = "6.0.1" +wit-bindgen-core = "0.25.0" +wit-bindgen-rust = "0.25.0" +wit-component = "0.208.1" +wit-parser = "0.208.1" [profile.release] panic = "abort" diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 0a07dc89..7bc43a47 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -11,23 +11,26 @@ repository = { workspace = true } [dependencies] anyhow = { workspace = true } +clap = { workspace = true } +dirs = { workspace = true } +futures = { workspace = true } +indexmap = { workspace = true } libc = { workspace = true } +log = { workspace = true } owo-colors = { workspace = true } -unicode-width = { workspace = true } -warg-crypto = { workspace = true } -warg-protocol = { workspace = true } -warg-client = { workspace = true } -toml_edit = { workspace = true } semver = { workspace = true } serde = { workspace = true } -indexmap = { workspace = true } -futures = { workspace = true } +tokio = { workspace = true } +tokio-util = { workspace = true, features = ["io"] } +toml_edit = { workspace = true } +unicode-width = { workspace = true } url = { workspace = true } +warg-client = { workspace = true } +warg-crypto = { workspace = true } +warg-protocol = { workspace = true } +wasm-pkg-client = { workspace = true } wit-component = { workspace = true } wit-parser = { workspace = true } -log = { workspace = true } -tokio = { workspace = true } -clap = { workspace = true } [target.'cfg(windows)'.dependencies.windows-sys] version = "0.52" diff --git a/crates/core/src/command.rs b/crates/core/src/command.rs index 3d92ccbb..e1e6ebfb 100644 --- a/crates/core/src/command.rs +++ b/crates/core/src/command.rs @@ -1,8 +1,15 @@ //! Module for common command implementation. +use std::path::PathBuf; -use crate::terminal::{Color, Terminal, Verbosity}; use clap::{ArgAction, Args}; +use crate::terminal::{Color, Terminal, Verbosity}; + +/// The environment variable name for setting a cache directory location +pub const CACHE_DIR_ENV_VAR: &str = "CARGO_COMPONENT_CACHE_DIR"; +/// The environment variable name for setting a path to a config file +pub const CONFIG_FILE_ENV_VAR: &str = "CARGO_COMPONENT_CONFIG_FILE"; + /// Common options for commands. #[derive(Args)] #[command( @@ -24,6 +31,14 @@ pub struct CommonOptions { /// Coloring: auto, always, never #[clap(long = "color", value_name = "WHEN")] pub color: Option, + + /// The path to the cache directory to store component dependencies. + #[clap(long = "cache-dir", env = CACHE_DIR_ENV_VAR)] + pub cache_dir: Option, + + /// The path to the pkg-tools config file + #[clap(long = "config", env = CONFIG_FILE_ENV_VAR)] + pub config: Option, } impl CommonOptions { diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs index 87ae52fe..870258f1 100644 --- a/crates/core/src/lib.rs +++ b/crates/core/src/lib.rs @@ -2,10 +2,12 @@ #![deny(missing_docs)] +use std::path::PathBuf; +use std::str::FromStr; + use anyhow::Context; use semver::VersionReq; -use std::str::FromStr; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::PackageRef; pub mod command; pub mod lock; @@ -13,11 +15,31 @@ pub mod progress; pub mod registry; pub mod terminal; +/// The root directory name used for default cargo component directories +pub const CARGO_COMPONENT_DIR: &str = "cargo-component"; +/// The cache directory name used by default +pub const CACHE_DIR: &str = "cache"; + +/// Returns the path to the default cache directory, returning an error if a cache directory cannot be found. +pub fn default_cache_dir() -> anyhow::Result { + dirs::cache_dir() + .map(|p| p.join(CARGO_COMPONENT_DIR).join(CACHE_DIR)) + .ok_or_else(|| anyhow::anyhow!("failed to find cache directory")) +} + +/// A helper that fetches the default directory if the given directory is `None`. +pub fn cache_dir(dir: Option) -> anyhow::Result { + match dir { + Some(dir) => Ok(dir), + None => default_cache_dir(), + } +} + /// Represents a versioned component package name. #[derive(Clone)] pub struct VersionedPackageName { /// The package name. - pub name: PackageName, + pub name: PackageRef, /// The optional package version. pub version: Option, } diff --git a/crates/core/src/lock.rs b/crates/core/src/lock.rs index 90a9f59d..30f9a51a 100644 --- a/crates/core/src/lock.rs +++ b/crates/core/src/lock.rs @@ -10,8 +10,7 @@ use std::{ path::{Path, PathBuf}, }; use toml_edit::{DocumentMut, Item, Value}; -use warg_crypto::hash::AnyHash; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::{ContentDigest, PackageRef}; /// The file format version of the lock file. const LOCK_FILE_VERSION: i64 = 1; @@ -21,7 +20,7 @@ const LOCK_FILE_VERSION: i64 = 1; #[serde(rename_all = "kebab-case")] pub struct LockedPackage { /// The name of the locked package. - pub name: PackageName, + pub name: PackageRef, /// The registry the package was resolved from. /// /// Defaults to the default registry if not specified. @@ -37,9 +36,10 @@ pub struct LockedPackage { impl LockedPackage { /// Gets the key used in sorting and searching the package list. - pub fn key(&self) -> (&PackageName, &str) { + pub fn key(&self) -> (&str, &str, &str) { ( - &self.name, + self.name.namespace().as_ref(), + self.name.name().as_ref(), self.registry.as_deref().unwrap_or(DEFAULT_REGISTRY_NAME), ) } @@ -53,7 +53,7 @@ pub struct LockedPackageVersion { /// The version the package is locked to. pub version: Version, /// The digest of the package contents. - pub digest: AnyHash, + pub digest: ContentDigest, } impl LockedPackageVersion { @@ -81,13 +81,20 @@ impl<'a> LockFileResolver<'a> { pub fn resolve( &'a self, registry: &str, - name: &PackageName, + package_ref: &PackageRef, requirement: &VersionReq, ) -> Result> { if let Some(pkg) = self .0 .packages - .binary_search_by_key(&(name, registry), LockedPackage::key) + .binary_search_by_key( + &( + package_ref.namespace().as_ref(), + package_ref.name().as_ref(), + registry, + ), + LockedPackage::key, + ) .ok() .map(|i| &self.0.packages[i]) { @@ -96,12 +103,12 @@ impl<'a> LockFileResolver<'a> { .binary_search_by_key(&requirement.to_string().as_str(), LockedPackageVersion::key) { let locked = &pkg.versions[index]; - log::info!("dependency package `{name}` from registry `{registry}` with requirement `{requirement}` was resolved by the lock file to version {version}", version = locked.version); + log::info!("dependency package `{package_ref}` from registry `{registry}` with requirement `{requirement}` was resolved by the lock file to version {version}", version = locked.version); return Ok(Some(locked)); } } - log::info!("dependency package `{name}` from registry `{registry}` with requirement `{requirement}` was not in the lock file"); + log::info!("dependency package `{package_ref}` from registry `{registry}` with requirement `{requirement}` was not in the lock file"); Ok(None) } } diff --git a/crates/core/src/registry.rs b/crates/core/src/registry.rs index 2391babb..c5684816 100644 --- a/crates/core/src/registry.rs +++ b/crates/core/src/registry.rs @@ -1,35 +1,36 @@ //! Module for resolving dependencies from a component registry. - -use crate::{ - lock::{LockFileResolver, LockedPackageVersion}, - progress::{ProgressBar, ProgressStyle}, - terminal::{Colors, Terminal}, +use std::{ + collections::{hash_map, HashMap}, + fmt::Debug, + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, }; + use anyhow::{bail, Context, Result}; -use futures::{stream::FuturesUnordered, StreamExt}; +use futures::TryStreamExt; use indexmap::IndexMap; use semver::{Comparator, Op, Version, VersionReq}; use serde::{ de::{self, value::MapAccessDeserializer}, Deserialize, Serialize, }; -use std::{ - collections::{hash_map, HashMap, HashSet}, - fs, - path::{Path, PathBuf}, - str::FromStr, - sync::Arc, -}; + +use tokio::io::AsyncReadExt; use url::Url; -use warg_client::{ - storage::{ContentStorage, PackageInfo}, - Config, FileSystemClient, StorageLockResult, +use warg_client::{Config as WargConfig, FileSystemClient, StorageLockResult}; +use wasm_pkg_client::{ + caching::{CachingClient, FileCache}, + Client, Config, ContentDigest, Error as WasmPkgError, PackageRef, Release, VersionInfo, }; -use warg_crypto::hash::AnyHash; -use warg_protocol::registry; use wit_component::DecodedWasm; use wit_parser::{PackageId, PackageName, Resolve, UnresolvedPackage, WorldId}; +use crate::{ + lock::{LockFileResolver, LockedPackageVersion}, + terminal::{Colors, Terminal}, +}; + /// The name of the default registry. pub const DEFAULT_REGISTRY_NAME: &str = "default"; @@ -51,7 +52,7 @@ pub fn find_url<'a>( /// Creates a registry client with the given warg configuration. pub async fn create_client( - config: &warg_client::Config, + config: &WargConfig, url: &str, terminal: &Terminal, ) -> Result { @@ -92,7 +93,7 @@ impl Serialize for Dependency { } else { #[derive(Serialize)] struct Entry<'a> { - package: Option<&'a registry::PackageName>, + package: Option<&'a PackageRef>, version: &'a str, registry: Option<&'a str>, } @@ -146,7 +147,7 @@ impl<'de> Deserialize<'de> for Dependency { #[serde(default, deny_unknown_fields)] struct Entry { path: Option, - package: Option, + package: Option, version: Option, registry: Option, } @@ -196,7 +197,7 @@ pub struct RegistryPackage { /// The name of the package. /// /// If not specified, the name from the mapping will be used. - pub name: Option, + pub name: Option, /// The version requirement of the package. pub version: VersionReq, @@ -222,14 +223,14 @@ impl FromStr for RegistryPackage { } /// Represents information about a resolution of a registry package. -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct RegistryResolution { /// The name of the dependency that was resolved. /// /// This may differ from `package` if the dependency was renamed. - pub name: registry::PackageName, + pub name: PackageRef, /// The name of the package from the registry that was resolved. - pub package: registry::PackageName, + pub package: PackageRef, /// The name of the registry used to resolve the package. /// /// A value of `None` indicates that the default registry was used. @@ -239,16 +240,29 @@ pub struct RegistryResolution { /// The package version that was resolved. pub version: Version, /// The digest of the package contents. - pub digest: AnyHash, - /// The path to the resolved dependency. - pub path: PathBuf, + pub digest: ContentDigest, + /// The client to use for fetching the package contents. + client: Arc>, +} + +impl Debug for RegistryResolution { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.debug_struct("RegistryResolution") + .field("name", &self.name) + .field("package", &self.package) + .field("registry", &self.registry) + .field("requirement", &self.requirement) + .field("version", &self.version) + .field("digest", &self.digest) + .finish() + } } /// Represents information about a resolution of a local file. #[derive(Clone, Debug)] pub struct LocalResolution { /// The name of the dependency that was resolved. - pub name: registry::PackageName, + pub name: PackageRef, /// The path to the resolved dependency. pub path: PathBuf, } @@ -265,21 +279,13 @@ pub enum DependencyResolution { impl DependencyResolution { /// Gets the name of the dependency that was resolved. - pub fn name(&self) -> ®istry::PackageName { + pub fn name(&self) -> &PackageRef { match self { Self::Registry(res) => &res.name, Self::Local(res) => &res.name, } } - /// Gets the path to the resolved dependency. - pub fn path(&self) -> &Path { - match self { - Self::Registry(res) => &res.path, - Self::Local(res) => &res.path, - } - } - /// Gets the resolved version. /// /// Returns `None` if the dependency is not resolved from a registry package. @@ -293,7 +299,7 @@ impl DependencyResolution { /// The key used in sorting and searching the lock file package list. /// /// Returns `None` if the dependency is not resolved from a registry package. - pub fn key(&self) -> Option<(®istry::PackageName, Option<&str>)> { + pub fn key(&self) -> Option<(&PackageRef, Option<&str>)> { match self { DependencyResolution::Registry(pkg) => Some((&pkg.package, pkg.registry.as_deref())), DependencyResolution::Local(_) => None, @@ -301,37 +307,60 @@ impl DependencyResolution { } /// Decodes the resolved dependency. - pub fn decode(&self) -> Result { + pub async fn decode(&self) -> Result { // If the dependency path is a directory, assume it contains wit to parse as a package. - if self.path().is_dir() { - return Ok(DecodedDependency::Wit { - resolution: self, - package: UnresolvedPackage::parse_dir(self.path()).with_context(|| { + let bytes = match self { + DependencyResolution::Local(LocalResolution { path, .. }) + if tokio::fs::metadata(path).await?.is_dir() => + { + return Ok(DecodedDependency::Wit { + resolution: self, + package: UnresolvedPackage::parse_dir(path).with_context(|| { + format!("failed to parse dependency `{path}`", path = path.display()) + })?, + }); + } + DependencyResolution::Local(LocalResolution { path, .. }) => { + tokio::fs::read(path).await.with_context(|| { format!( - "failed to parse dependency `{path}`", - path = self.path().display() + "failed to read content of dependency `{name}` at path `{path}`", + name = self.name(), + path = path.display() ) - })?, - }); - } + })? + } + DependencyResolution::Registry(res) => { + let stream = res + .client + .get_content( + &res.package, + &Release { + version: res.version.clone(), + content_digest: res.digest.clone(), + }, + ) + .await?; - let bytes = fs::read(self.path()).with_context(|| { - format!( - "failed to read content of dependency `{name}` at path `{path}`", - name = self.name(), - path = self.path().display() - ) - })?; + let mut buf = Vec::new(); + tokio_util::io::StreamReader::new( + stream.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)), + ) + .read_to_end(&mut buf) + .await?; + buf + } + }; if &bytes[0..4] != b"\0asm" { return Ok(DecodedDependency::Wit { resolution: self, package: UnresolvedPackage::parse( - self.path(), + // This is fake, but it's needed for the parser to work. + self.name().to_string().as_ref(), std::str::from_utf8(&bytes).with_context(|| { format!( - "dependency `{path}` is not UTF-8 encoded", - path = self.path().display() + "dependency `{name}` is not UTF-8 encoded", + name = self.name() ) })?, )?, @@ -342,9 +371,8 @@ impl DependencyResolution { resolution: self, decoded: wit_component::decode(&bytes).with_context(|| { format!( - "failed to decode content of dependency `{name}` at path `{path}`", + "failed to decode content of dependency `{name}`", name = self.name(), - path = self.path().display() ) })?, }) @@ -416,39 +444,42 @@ impl<'a> DecodedDependency<'a> { /// Used to resolve dependencies for a WIT package. pub struct DependencyResolver<'a> { - terminal: &'a Terminal, - registry_urls: &'a HashMap, - warg_config: &'a Config, + client: Arc>, lock_file: Option>, registries: IndexMap<&'a str, Registry<'a>>, - resolutions: HashMap, - network_allowed: bool, + resolutions: HashMap, } impl<'a> DependencyResolver<'a> { /// Creates a new dependency resolver. - pub fn new( - warg_config: &'a Config, - registry_urls: &'a HashMap, + pub fn new(config: Config, lock_file: Option>, cache: FileCache) -> Self { + let client = CachingClient::new(Client::new(config), cache); + DependencyResolver { + client: Arc::new(client), + lock_file, + registries: Default::default(), + resolutions: Default::default(), + } + } + + /// Creates a new dependency resolver with the given client. This is useful when you already + /// have a client available + pub fn new_with_client( + client: Arc>, lock_file: Option>, - terminal: &'a Terminal, - network_allowed: bool, - ) -> Result { - Ok(DependencyResolver { - terminal, - registry_urls, - warg_config, + ) -> Self { + DependencyResolver { + client, lock_file, registries: Default::default(), resolutions: Default::default(), - network_allowed, - }) + } } /// Add a dependency to the resolver. pub async fn add_dependency( &mut self, - name: &'a registry::PackageName, + name: &'a PackageRef, dependency: &'a Dependency, ) -> Result<()> { match dependency { @@ -470,25 +501,15 @@ impl<'a> DependencyResolver<'a> { let registry = match self.registries.entry(registry_name) { indexmap::map::Entry::Occupied(e) => e.into_mut(), - indexmap::map::Entry::Vacant(e) => { - let url = find_url( - Some(registry_name), - self.registry_urls, - self.warg_config.home_url.as_deref(), - )?; - e.insert(Registry { - client: Arc::new( - create_client(self.warg_config, url, self.terminal).await?, - ), - packages: HashMap::new(), - dependencies: Vec::new(), - upserts: HashSet::new(), - }) - } + indexmap::map::Entry::Vacant(e) => e.insert(Registry { + client: self.client.clone(), + packages: HashMap::new(), + dependencies: Vec::new(), + }), }; registry - .add_dependency(name, package_name, &package.version, registry_name, locked) + .add_dependency(name, package_name, &package.version, locked) .await?; } Dependency::Local(p) => { @@ -511,202 +532,44 @@ impl<'a> DependencyResolver<'a> { /// This will download all dependencies that are not already present in client storage. /// /// Returns the dependency resolution map. - pub async fn resolve(self) -> Result { - let Self { - mut registries, - mut resolutions, - terminal, - network_allowed, - .. - } = self; - - // Start by updating the packages that need updating - // This will determine the contents that need to be downloaded - let downloads = Self::update_packages(&mut registries, terminal, network_allowed).await?; - - // Finally, download and resolve the dependencies - for resolution in - Self::download_and_resolve(registries, downloads, terminal, network_allowed).await? - { - let prev = resolutions.insert(resolution.name().clone(), resolution); - assert!(prev.is_none()); - } - - Ok(resolutions) - } - - async fn update_packages( - registries: &mut IndexMap<&'a str, Registry<'a>>, - terminal: &Terminal, - network_allowed: bool, - ) -> Result> { - let task_count = registries - .iter() - .filter(|(_, r)| !r.upserts.is_empty()) - .count(); - - let mut progress = ProgressBar::with_style("Updating", ProgressStyle::Ratio, terminal); - - if task_count > 0 { - if !network_allowed { - bail!("a component registry update is required but network access is disabled"); - } - - terminal.status("Updating", "component registry package logs")?; - progress.tick_now(0, task_count, "")?; - } - - let mut downloads = DownloadMap::new(); - let mut futures = FuturesUnordered::new(); - for (index, (name, registry)) in registries.iter_mut().enumerate() { - let upserts = std::mem::take(&mut registry.upserts); - if upserts.is_empty() { - // No upserts needed, add the necessary downloads now - registry.add_downloads(name, &mut downloads).await?; - continue; - } - - log::info!("updating package logs for registry `{name}`"); - - let client = registry.client.clone(); - futures.push(tokio::spawn(async move { - (index, client.fetch_packages(upserts.iter()).await) - })) + pub async fn resolve(mut self) -> Result { + // Resolve all dependencies + for (name, registry) in self.registries.iter_mut() { + registry.resolve(name).await?; } - assert_eq!(futures.len(), task_count); - - let mut finished = 0; - while let Some(res) = futures.next().await { - let (index, res) = res.context("failed to join registry update task")?; - let (name, registry) = registries - .get_index_mut(index) - .expect("out of bounds registry index"); - - res.with_context(|| { - format!("failed to update package logs for component registry `{name}`") - })?; - - log::info!("package logs successfully updated for component registry `{name}`"); - finished += 1; - progress.tick_now(finished, task_count, ": updated `{name}`")?; - registry.add_downloads(name, &mut downloads).await?; - } - - assert_eq!(finished, task_count); - - progress.clear(); - - Ok(downloads) - } - - async fn download_and_resolve( - mut registries: IndexMap<&'a str, Registry<'a>>, - downloads: DownloadMap<'a>, - terminal: &Terminal, - network_allowed: bool, - ) -> Result + 'a> { - if !downloads.is_empty() { - if !network_allowed { - bail!("a component package download is required but network access is disabled"); - } - - terminal.status("Downloading", "component registry packages")?; - - let mut progress = - ProgressBar::with_style("Downloading", ProgressStyle::Ratio, terminal); - - let count = downloads.len(); - progress.tick_now(0, count, "")?; - - let mut futures = FuturesUnordered::new(); - for ((registry_name, name, version), deps) in downloads { - let registry_index = registries.get_index_of(registry_name).unwrap(); - let (_, registry) = registries.get_index(registry_index).unwrap(); - - log::info!("downloading content for package `{name}` from component registry `{registry_name}`"); - - let client = registry.client.clone(); - futures.push(tokio::spawn(async move { - let res = client.download_exact(&name, &version).await; - (registry_index, name, version, deps, res) - })) - } - - assert_eq!(futures.len(), count); - - let mut finished = 0; - while let Some(res) = futures.next().await { - let (registry_index, name, version, deps, res) = - res.context("failed to join content download task")?; - let (registry_name, registry) = registries - .get_index_mut(registry_index) - .expect("out of bounds registry index"); - - let download = res.with_context(|| { - format!("failed to download package `{name}` (v{version}) from component registry `{registry_name}`") - })?; - - log::info!( - "downloaded contents of package `{name}` (v{version}) from component registry `{registry_name}`" - ); - - finished += 1; - progress.tick_now( - finished, - count, - &format!(": downloaded `{name}` (v{version})"), - )?; - - for index in deps { - let dependency = &mut registry.dependencies[index]; - assert!(dependency.resolution.is_none()); - dependency.resolution = Some(RegistryResolution { - name: dependency.name.clone(), - package: dependency.package.clone(), - registry: if *registry_name == DEFAULT_REGISTRY_NAME { - None - } else { - Some(registry_name.to_string()) - }, - requirement: dependency.version.clone(), - version: download.version.clone(), - digest: download.digest.clone(), - path: download.path.clone(), - }); - } - } - - assert_eq!(finished, count); - - progress.clear(); - } - - Ok(registries + for resolution in self + .registries .into_values() .flat_map(|r| r.dependencies.into_iter()) .map(|d| { DependencyResolution::Registry( d.resolution.expect("dependency should have been resolved"), ) - })) + }) + { + let prev = self + .resolutions + .insert(resolution.name().clone(), resolution); + assert!(prev.is_none()); + } + + Ok(self.resolutions) } } struct Registry<'a> { - client: Arc, - packages: HashMap, + client: Arc>, + packages: HashMap>, dependencies: Vec>, - upserts: HashSet, } impl<'a> Registry<'a> { async fn add_dependency( &mut self, - name: &'a registry::PackageName, - package: registry::PackageName, + name: &'a PackageRef, + package: PackageRef, version: &'a VersionReq, - registry: &str, locked: Option<&LockedPackageVersion>, ) -> Result<()> { let dep = RegistryDependency { @@ -719,56 +582,28 @@ impl<'a> Registry<'a> { self.dependencies.push(dep); - let mut needs_upsert = true; - if let Some(locked) = locked { - if let Some(package) = - Self::load_package(&self.client, &mut self.packages, package.clone()).await? - { - if package - .state - .release(&locked.version) - .and_then(|r| r.content()) - .is_some() - { - // Don't need to upsert this package as it is present - // in the lock file and in client storage. - needs_upsert = false; - } - } - } - - if needs_upsert && self.upserts.insert(package.clone()) { - log::info!( - "package `{package}` from component registry `{registry}` needs to be updated" - ); - } - Ok(()) } - async fn add_downloads( - &mut self, - registry: &'a str, - downloads: &mut DownloadMap<'a>, - ) -> Result<()> { - let Self { - dependencies, - packages, - client, - .. - } = self; - - for (index, dependency) in dependencies.iter_mut().enumerate() { - let package = Self::load_package(client, packages, dependency.package.clone()) - .await? - .with_context(|| { - format!( - "package `{name}` was not found in component registry `{registry}`", - name = dependency.package - ) - })?; + async fn resolve(&mut self, registry: &'a str) -> Result<()> { + for dependency in self.dependencies.iter_mut() { + // We need to clone a handle to the client because we mutably borrow self below. Might + // be worth replacing the mutable borrow with a RwLock down the line. + let client = self.client.clone(); + let versions = load_package( + &mut self.packages, + &self.client.client, + dependency.package.clone(), + ) + .await? + .with_context(|| { + format!( + "package `{name}` was not found in component registry `{registry}`", + name = dependency.package + ) + })?; - let release = match &dependency.locked { + let (selected_version, digest) = match &dependency.locked { Some((version, digest)) => { // The dependency had a lock file entry, so attempt to do an exact match first let exact_req = VersionReq { @@ -781,104 +616,86 @@ impl<'a> Registry<'a> { }], }; - // If an exact match can't be found, fallback to the latest release to - // satisfy the version requirement; this can happen when packages are yanked - package.state.find_latest_release(&exact_req).map(|r| { - // Exact match, verify the content digests match - let content = r.content().expect("release must have content"); - if content != digest { - bail!( - "component registry package `{name}` (v`{version}`) has digest `{content}` but the lock file specifies digest `{digest}`", - name = dependency.package, - ); - } - Ok(r) - }).transpose()?.or_else(|| package.state.find_latest_release(dependency.version)) + // If an exact match can't be found, fallback to the latest release to satisfy + // the version requirement; this can happen when packages are yanked. If we did + // find an exact match, return the digest for comparison after fetching the + // release + find_latest_release(versions, &exact_req).map(|v| (v, Some(digest))).or_else(|| find_latest_release(versions, dependency.version).map(|v| (v, None))) } - None => package.state.find_latest_release(dependency.version), + None => find_latest_release(versions, dependency.version).map(|v| (v, None)), }.with_context(|| format!("component registry package `{name}` has no release matching version requirement `{version}`", name = dependency.package, version = dependency.version))?; - - let digest = release.content().expect("release must have content"); - match client.content().content_location(digest) { - Some(path) => { - // Content is already present, set the resolution - assert!(dependency.resolution.is_none()); - dependency.resolution = Some(RegistryResolution { - name: dependency.name.clone(), - package: dependency.package.clone(), - registry: if registry == DEFAULT_REGISTRY_NAME { - None - } else { - Some(registry.to_string()) - }, - requirement: dependency.version.clone(), - version: release.version.clone(), - digest: digest.clone(), - path, - }); - - log::info!( - "version {version} of registry package `{name}` from registry `{registry}` is already in client storage", + // We need to clone a handle to the client because we mutably borrow self above. Might + // be worth replacing the mutable borrow with a RwLock down the line. + let release = client + .client + .get_release(&dependency.package, &selected_version.version) + .await?; + if let Some(digest) = digest { + if &release.content_digest != digest { + bail!( + "component registry package `{name}` (v`{version}`) has digest `{content}` but the lock file specifies digest `{digest}`", name = dependency.package, version = release.version, + content = release.content_digest, ); } - None => { - // Content needs to be downloaded - let indexes = downloads - .entry(( - registry, - dependency.package.clone(), - release.version.clone(), - )) - .or_default(); - - if indexes.is_empty() { - log::info!( - "version {version} of registry package `{name}` from registry `{registry}` needs to be downloaded", - name = dependency.package, - version = release.version, - ); - } - - indexes.push(index); - } } + + dependency.resolution = Some(RegistryResolution { + name: dependency.name.clone(), + package: dependency.package.clone(), + registry: if registry == DEFAULT_REGISTRY_NAME { + None + } else { + Some(registry.to_string()) + }, + requirement: dependency.version.clone(), + version: release.version.clone(), + digest: release.content_digest.clone(), + client: self.client.clone(), + }); } Ok(()) } +} - async fn load_package<'b>( - client: &FileSystemClient, - packages: &'b mut HashMap, - name: registry::PackageName, - ) -> Result> { - match packages.entry(name) { - hash_map::Entry::Occupied(e) => Ok(Some(e.into_mut())), - hash_map::Entry::Vacant(e) => match client.package(e.key()).await { - Ok(p) => Ok(Some(e.insert(p))), - Err(warg_client::ClientError::PackageDoesNotExist { .. }) => Ok(None), - Err(err) => Err(err.into()), - }, - } +async fn load_package<'b>( + packages: &'b mut HashMap>, + client: &Client, + package: PackageRef, +) -> Result>> { + match packages.entry(package) { + hash_map::Entry::Occupied(e) => Ok(Some(e.into_mut())), + hash_map::Entry::Vacant(e) => match client.list_all_versions(e.key()).await { + Ok(p) => Ok(Some(e.insert(p))), + Err(WasmPkgError::PackageNotFound) => Ok(None), + Err(err) => Err(err.into()), + }, } } -type DownloadMapKey<'a> = (&'a str, registry::PackageName, Version); -type DownloadMap<'a> = HashMap, Vec>; - struct RegistryDependency<'a> { /// The package name assigned in the configuration file. - name: &'a registry::PackageName, + name: &'a PackageRef, /// The package name of the registry package. - package: registry::PackageName, + package: PackageRef, version: &'a VersionReq, - locked: Option<(Version, AnyHash)>, + locked: Option<(Version, ContentDigest)>, resolution: Option, } /// Represents a map of dependency resolutions. /// /// The key to the map is the package name of the dependency. -pub type DependencyResolutionMap = HashMap; +pub type DependencyResolutionMap = HashMap; + +fn find_latest_release<'a>( + versions: &'a [VersionInfo], + req: &VersionReq, +) -> Option<&'a VersionInfo> { + versions + .iter() + .filter(|info| !info.yanked && req.matches(&info.version)) + .max_by(|a, b| a.version.cmp(&b.version)) +} diff --git a/crates/wit/Cargo.toml b/crates/wit/Cargo.toml index b2933524..da1b91bf 100644 --- a/crates/wit/Cargo.toml +++ b/crates/wit/Cargo.toml @@ -12,28 +12,29 @@ repository = { workspace = true } readme = "README.md" [dependencies] -cargo-component-core = { workspace = true } anyhow = { workspace = true } +bytes = { workspace = true } +cargo-component-core = { workspace = true } +clap = { workspace = true } +futures = { workspace = true } +indexmap = { workspace = true } +log = { workspace = true } +p256 = { workspace = true } +pretty_env_logger = { workspace = true } +rand_core = { workspace = true } +rpassword = { workspace = true } semver = { workspace = true } -url = { workspace = true } serde = { workspace = true } +tokio = { workspace = true } toml_edit = { workspace = true } -warg-protocol = { workspace = true } +url = { workspace = true } +wasm-pkg-client = { workspace = true } warg-client = { workspace = true } warg-crypto = { workspace = true } -log = { workspace = true } -clap = { workspace = true } -rpassword = { workspace = true } -rand_core = { workspace = true } -p256 = { workspace = true } -indexmap = { workspace = true } -wit-parser = { workspace = true } -wit-component = { workspace = true } +warg-protocol = { workspace = true } wasm-metadata = { workspace = true } -futures = { workspace = true } -bytes = { workspace = true } -tokio = { workspace = true } -pretty_env_logger = { workspace = true } +wit-component = { workspace = true } +wit-parser = { workspace = true } [dev-dependencies] assert_cmd = { workspace = true } diff --git a/crates/wit/src/commands/add.rs b/crates/wit/src/commands/add.rs index 93eb4611..86e0144d 100644 --- a/crates/wit/src/commands/add.rs +++ b/crates/wit/src/commands/add.rs @@ -1,25 +1,25 @@ -use crate::config::{Config, CONFIG_FILE_NAME}; +use std::path::PathBuf; + use anyhow::{bail, Context, Result}; use cargo_component_core::{ + cache_dir, command::CommonOptions, registry::{Dependency, DependencyResolution, DependencyResolver, RegistryPackage}, - terminal::Terminal, VersionedPackageName, }; use clap::Args; use semver::VersionReq; -use std::path::PathBuf; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::{caching::FileCache, PackageRef}; + +use crate::config::{Config, CONFIG_FILE_NAME}; async fn resolve_version( - config: &Config, - warg_config: &warg_client::Config, + pkg_config: wasm_pkg_client::Config, package: &VersionedPackageName, registry: &Option, - terminal: &Terminal, + file_cache: FileCache, ) -> Result { - let mut resolver = - DependencyResolver::new(warg_config, &config.registries, None, terminal, true)?; + let mut resolver = DependencyResolver::new(pkg_config, None, file_cache); let dependency = Dependency::Package(RegistryPackage { name: Some(package.name.clone()), version: package @@ -63,7 +63,7 @@ pub struct AddCommand { /// The name of the dependency to use; defaults to the package name. #[clap(long, value_name = "NAME")] - pub name: Option, + pub name: Option, /// Add a package dependency to a file or directory. #[clap(long = "path", value_name = "PATH")] @@ -82,13 +82,23 @@ impl AddCommand { let (mut config, config_path) = Config::from_default_file()? .with_context(|| format!("failed to find configuration file `{CONFIG_FILE_NAME}`"))?; + let terminal = self.common.new_terminal(); + let pkg_config = if let Some(config_file) = self.common.config { + wasm_pkg_client::Config::from_file(&config_file).context(format!( + "failed to load configuration file from {}", + config_file.display() + ))? + } else { + wasm_pkg_client::Config::global_defaults()? + }; + + let file_cache = FileCache::new(cache_dir(self.common.cache_dir)?).await?; + let name = self.name.as_ref().unwrap_or(&self.package.name); if config.dependencies.contains_key(name) { bail!("cannot add dependency `{name}` as it conflicts with an existing dependency"); } - let warg_config = warg_client::Config::from_default_file()?.unwrap_or_default(); - let terminal = self.common.new_terminal(); let message = match self.path.as_deref() { Some(path) => { config @@ -102,14 +112,8 @@ impl AddCommand { ) } None => { - let version = resolve_version( - &config, - &warg_config, - &self.package, - &self.registry, - &terminal, - ) - .await?; + let version = + resolve_version(pkg_config, &self.package, &self.registry, file_cache).await?; let package = RegistryPackage { name: self.name.is_some().then(|| self.package.name.clone()), diff --git a/crates/wit/src/commands/build.rs b/crates/wit/src/commands/build.rs index cf672164..5887b8b4 100644 --- a/crates/wit/src/commands/build.rs +++ b/crates/wit/src/commands/build.rs @@ -1,11 +1,14 @@ +use std::{fs, path::PathBuf}; + +use anyhow::{Context, Result}; +use cargo_component_core::{cache_dir, command::CommonOptions}; +use clap::Args; +use wasm_pkg_client::caching::FileCache; + use crate::{ build_wit_package, config::{Config, CONFIG_FILE_NAME}, }; -use anyhow::{Context, Result}; -use cargo_component_core::command::CommonOptions; -use clap::Args; -use std::{fs, path::PathBuf}; /// Build a binary WIT package. #[derive(Args)] @@ -28,10 +31,19 @@ impl BuildCommand { let (config, config_path) = Config::from_default_file()? .with_context(|| format!("failed to find configuration file `{CONFIG_FILE_NAME}`"))?; - let warg_config = warg_client::Config::from_default_file()?.unwrap_or_default(); - let terminal = self.common.new_terminal(); - let (id, bytes) = build_wit_package(&config, &config_path, &warg_config, &terminal).await?; + let pkg_config = if let Some(config_file) = self.common.config { + wasm_pkg_client::Config::from_file(&config_file).context(format!( + "failed to load configuration file from {}", + config_file.display() + ))? + } else { + wasm_pkg_client::Config::global_defaults()? + }; + let file_cache = FileCache::new(cache_dir(self.common.cache_dir)?).await?; + + let (id, bytes) = + build_wit_package(&config, &config_path, pkg_config, &terminal, file_cache).await?; let output = self .output diff --git a/crates/wit/src/commands/publish.rs b/crates/wit/src/commands/publish.rs index 6141d149..58d2cd01 100644 --- a/crates/wit/src/commands/publish.rs +++ b/crates/wit/src/commands/publish.rs @@ -1,12 +1,14 @@ -use crate::{ - config::{Config, CONFIG_FILE_NAME}, - publish_wit_package, PublishOptions, -}; use anyhow::{Context, Result}; -use cargo_component_core::{command::CommonOptions, registry::find_url}; +use cargo_component_core::{cache_dir, command::CommonOptions, registry::find_url}; use clap::Args; use warg_crypto::signing::PrivateKey; use warg_protocol::registry::PackageName; +use wasm_pkg_client::caching::FileCache; + +use crate::{ + config::{Config, CONFIG_FILE_NAME}, + publish_wit_package, PublishOptions, +}; /// Publish a WIT package to a registry. #[derive(Args)] @@ -43,6 +45,15 @@ impl PublishCommand { let terminal = self.common.new_terminal(); let warg_config = warg_client::Config::from_default_file()?.unwrap_or_default(); + let pkg_config = if let Some(config_file) = self.common.config { + wasm_pkg_client::Config::from_file(&config_file).context(format!( + "failed to load configuration file from {}", + config_file.display() + ))? + } else { + wasm_pkg_client::Config::global_defaults()? + }; + let file_cache = FileCache::new(cache_dir(self.common.cache_dir)?).await?; let url = find_url( self.registry.as_deref(), @@ -63,6 +74,8 @@ impl PublishCommand { config: &config, config_path: &config_path, warg_config: &warg_config, + pkg_config, + cache: file_cache, url, signing_key, package: self.package.as_ref(), diff --git a/crates/wit/src/commands/update.rs b/crates/wit/src/commands/update.rs index c8f4b6e6..d183025c 100644 --- a/crates/wit/src/commands/update.rs +++ b/crates/wit/src/commands/update.rs @@ -1,7 +1,9 @@ -use crate::config::{Config, CONFIG_FILE_NAME}; use anyhow::{Context, Result}; -use cargo_component_core::command::CommonOptions; +use cargo_component_core::{cache_dir, command::CommonOptions}; use clap::Args; +use wasm_pkg_client::caching::FileCache; + +use crate::config::{Config, CONFIG_FILE_NAME}; /// Update dependencies as recorded in the lock file. #[derive(Args)] @@ -24,9 +26,25 @@ impl UpdateCommand { let (config, config_path) = Config::from_default_file()? .with_context(|| format!("failed to find configuration file `{CONFIG_FILE_NAME}`"))?; - let warg_config = warg_client::Config::from_default_file()?.unwrap_or_default(); - let terminal = self.common.new_terminal(); - crate::update_lockfile(&config, &config_path, &warg_config, &terminal, self.dry_run).await + let pkg_config = if let Some(config_file) = self.common.config { + wasm_pkg_client::Config::from_file(&config_file).context(format!( + "failed to load configuration file from {}", + config_file.display() + ))? + } else { + wasm_pkg_client::Config::global_defaults()? + }; + let file_cache = FileCache::new(cache_dir(self.common.cache_dir)?).await?; + + crate::update_lockfile( + &config, + &config_path, + pkg_config, + &terminal, + self.dry_run, + file_cache, + ) + .await } } diff --git a/crates/wit/src/config.rs b/crates/wit/src/config.rs index 16d19561..69442605 100644 --- a/crates/wit/src/config.rs +++ b/crates/wit/src/config.rs @@ -11,7 +11,7 @@ use std::{ }; use toml_edit::Item; use url::Url; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::PackageRef; /// The default name of the configuration file. pub const CONFIG_FILE_NAME: &str = "wit.toml"; @@ -80,7 +80,7 @@ pub struct Config { pub version: Version, /// The package dependencies. #[serde(default, skip_serializing_if = "HashMap::is_empty")] - pub dependencies: HashMap, + pub dependencies: HashMap, /// The registries to use for sourcing packages. #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub registries: HashMap, diff --git a/crates/wit/src/lib.rs b/crates/wit/src/lib.rs index 8b402948..76d571c5 100644 --- a/crates/wit/src/lib.rs +++ b/crates/wit/src/lib.rs @@ -17,6 +17,7 @@ use warg_client::storage::{ContentStorage, PublishEntry, PublishInfo}; use warg_crypto::signing::PrivateKey; use warg_protocol::registry; use wasm_metadata::{Link, LinkType, RegistryMetadata}; +use wasm_pkg_client::caching::FileCache; use wit_component::DecodedWasm; use wit_parser::{PackageId, PackageName, Resolve, UnresolvedPackage}; @@ -27,9 +28,10 @@ mod lock; async fn resolve_dependencies( config: &Config, config_path: &Path, - warg_config: &warg_client::Config, + pkg_config: wasm_pkg_client::Config, terminal: &Terminal, update_lock_file: bool, + file_cache: FileCache, ) -> Result { let file_lock = acquire_lock_file_ro(terminal, config_path)?; let lock_file = file_lock @@ -45,12 +47,10 @@ async fn resolve_dependencies( .transpose()?; let mut resolver = DependencyResolver::new( - warg_config, - &config.registries, + pkg_config, lock_file.as_ref().map(LockFileResolver::new), - terminal, - true, - )?; + file_cache, + ); for (name, dep) in &config.dependencies { resolver.add_dependency(name, dep).await?; @@ -78,7 +78,7 @@ async fn resolve_dependencies( Ok(map) } -fn parse_wit_package( +async fn parse_wit_package( dir: &Path, dependencies: &DependencyResolutionMap, ) -> Result<(Resolve, PackageId)> { @@ -87,7 +87,7 @@ fn parse_wit_package( // Start by decoding all of the dependencies let mut deps = IndexMap::new(); for (name, resolution) in dependencies { - let decoded = resolution.decode()?; + let decoded = resolution.decode().await?; if let Some(prev) = deps.insert(decoded.package_name().clone(), decoded) { bail!( "duplicate definitions of package `{prev}` found while decoding dependency `{name}`", @@ -222,15 +222,16 @@ fn parse_wit_package( async fn build_wit_package( config: &Config, config_path: &Path, - warg_config: &warg_client::Config, + pkg_config: wasm_pkg_client::Config, terminal: &Terminal, + file_cache: FileCache, ) -> Result<(registry::PackageName, Vec)> { let dependencies = - resolve_dependencies(config, config_path, warg_config, terminal, true).await?; + resolve_dependencies(config, config_path, pkg_config, terminal, true, file_cache).await?; let dir = config_path.parent().unwrap_or_else(|| Path::new(".")); - let (mut resolve, package) = parse_wit_package(dir, &dependencies)?; + let (mut resolve, package) = parse_wit_package(dir, &dependencies).await?; let pkg = &mut resolve.packages[package]; let name = format!("{ns}:{name}", ns = pkg.name.namespace, name = pkg.name.name).parse()?; @@ -255,11 +256,13 @@ struct PublishOptions<'a> { config: &'a Config, config_path: &'a Path, warg_config: &'a warg_client::Config, + pkg_config: wasm_pkg_client::Config, url: &'a str, signing_key: Option, package: Option<&'a registry::PackageName>, init: bool, dry_run: bool, + cache: FileCache, } fn add_registry_metadata(config: &Config, bytes: &[u8]) -> Result> { @@ -316,8 +319,9 @@ async fn publish_wit_package(options: PublishOptions<'_>, terminal: &Terminal) - let (name, bytes) = build_wit_package( options.config, options.config_path, - options.warg_config, + options.pkg_config, terminal, + options.cache, ) .await?; @@ -379,13 +383,13 @@ async fn publish_wit_package(options: PublishOptions<'_>, terminal: &Terminal) - pub async fn update_lockfile( config: &Config, config_path: &Path, - warg_config: &warg_client::Config, + pkg_config: wasm_pkg_client::Config, terminal: &Terminal, dry_run: bool, + file_cache: FileCache, ) -> Result<()> { // Resolve all dependencies as if the lock file does not exist - let mut resolver = - DependencyResolver::new(warg_config, &config.registries, None, terminal, true)?; + let mut resolver = DependencyResolver::new(pkg_config, None, file_cache); for (name, dep) in &config.dependencies { resolver.add_dependency(name, dep).await?; } diff --git a/crates/wit/src/lock.rs b/crates/wit/src/lock.rs index 59df150a..60a2cc76 100644 --- a/crates/wit/src/lock.rs +++ b/crates/wit/src/lock.rs @@ -1,4 +1,5 @@ //! Module for the lock file implementation. +use std::{collections::HashMap, path::Path}; use anyhow::Result; use cargo_component_core::{ @@ -7,9 +8,7 @@ use cargo_component_core::{ terminal::{Colors, Terminal}, }; use semver::Version; -use std::{collections::HashMap, path::Path}; -use warg_crypto::hash::AnyHash; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::{ContentDigest, PackageRef}; /// The name of the lock file. pub const LOCK_FILE_NAME: &str = "wit.lock"; @@ -57,8 +56,8 @@ pub(crate) fn acquire_lock_file_rw(terminal: &Terminal, config_path: &Path) -> R /// Constructs a `LockFile` from a `DependencyResolutionMap`. pub fn to_lock_file(map: &DependencyResolutionMap) -> LockFile { - type PackageKey = (PackageName, Option); - type VersionsMap = HashMap; + type PackageKey = (PackageRef, Option); + type VersionsMap = HashMap; let mut packages: HashMap = HashMap::new(); for resolution in map.values() { diff --git a/crates/wit/tests/add.rs b/crates/wit/tests/add.rs index f4d87a35..c040f95d 100644 --- a/crates/wit/tests/add.rs +++ b/crates/wit/tests/add.rs @@ -1,16 +1,17 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::{prelude::*, str::contains}; -use std::{fs, rc::Rc}; -use tempfile::TempDir; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help add", "add -h", "add --help"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains( "Adds a reference to a WIT package from a registry", @@ -21,7 +22,7 @@ fn help() { #[test] fn it_fails_with_missing_toml_file() -> Result<()> { - wit("add foo:bar") + wit(["add", "foo:bar"]) .assert() .stderr(contains( "error: failed to find configuration file `wit.toml`", @@ -32,7 +33,7 @@ fn it_fails_with_missing_toml_file() -> Result<()> { #[test] fn requires_package() { - wit("add") + wit(["add"]) .assert() .stderr(contains("wit add ")) .failure(); @@ -40,16 +41,14 @@ fn requires_package() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn validate_the_package_exists() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(["foo"]).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project - .wit("add foo:bar") + .wit(["add", "foo:bar"]) .assert() - .stderr(contains("package `foo:bar` does not exist")) + .stderr(contains("package `foo:bar` was not found")) .failure(); Ok(()) @@ -57,22 +56,20 @@ async fn validate_the_package_exists() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn validate_the_version_exists() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project.file("foo.wit", "package test:bar;\n")?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) .success(); - let project = Project::with_dir(dir.clone(), "bar", "")?; + let project = server.project("bar", Vec::::new())?; project - .wit("add test:bar") + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `0.1.0`")) .success(); @@ -81,7 +78,7 @@ async fn validate_the_version_exists() -> Result<()> { assert!(contains(r#""test:bar" = "0.1.0""#).eval(&manifest)); project - .wit("add --name test:bar2 test:bar@2.0.0") + .wit(["add", "--name", "test:bar2", "test:bar@2.0.0"]) .assert() .stderr(contains( "component registry package `test:bar` has no release matching version requirement `^2.0.0`", @@ -93,22 +90,20 @@ async fn validate_the_version_exists() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn checks_for_duplicate_dependencies() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project.file("foo.wit", "package test:bar;\n")?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) .success(); - let project = Project::with_dir(dir.clone(), "bar", "")?; + let project = server.project("bar", Vec::::new())?; project - .wit("add test:bar") + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `0.1.0`")) .success(); @@ -117,7 +112,7 @@ async fn checks_for_duplicate_dependencies() -> Result<()> { assert!(contains(r#""test:bar" = "0.1.0""#).eval(&manifest)); project - .wit("add test:bar") + .wit(["add", "test:bar"]) .assert() .stderr(contains( "cannot add dependency `test:bar` as it conflicts with an existing dependency", @@ -129,22 +124,20 @@ async fn checks_for_duplicate_dependencies() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn does_not_modify_manifest_for_dry_run() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project.file("foo.wit", "package test:bar;\n")?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) .success(); - let project = Project::with_dir(dir.clone(), "bar", "")?; + let project = server.project("bar", Vec::::new())?; project - .wit("add test:bar --dry-run") + .wit(["add", "test:bar", "--dry-run"]) .assert() .stderr(contains( "Would add dependency `test:bar` with version `0.1.0` (dry run)", @@ -162,7 +155,7 @@ fn validate_add_from_path() -> Result<()> { let project = Project::new("foo")?; project - .wit("add --path foo/baz foo:baz") + .wit(["add", "--path", "foo/baz", "foo:baz"]) .assert() .stderr(contains("Added dependency `foo:baz` from path `foo/baz`")); diff --git a/crates/wit/tests/build.rs b/crates/wit/tests/build.rs index 83da4220..ad82c21f 100644 --- a/crates/wit/tests/build.rs +++ b/crates/wit/tests/build.rs @@ -1,15 +1,17 @@ -use crate::support::*; +use std::fs; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::str::contains; -use std::fs; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help build", "build -h", "build --help"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains("Build a binary WIT package")) .success(); @@ -18,7 +20,7 @@ fn help() { #[test] fn it_fails_with_missing_toml_file() -> Result<()> { - wit("build") + wit(["build"]) .assert() .stderr(contains( "error: failed to find configuration file `wit.toml`", @@ -46,7 +48,7 @@ world baz-world {} )?; project - .wit("build") + .wit(["build"]) .assert() .stderr(contains("Created package `bar.wasm`")) .success(); @@ -74,7 +76,7 @@ fn it_adds_a_producers_field() -> Result<()> { project.file("producers.wit", "package test:producers;")?; project - .wit("build") + .wit(["build"]) .assert() .stderr(contains("Created package `producers.wasm`")) .success(); diff --git a/crates/wit/tests/init.rs b/crates/wit/tests/init.rs index c016811d..7b5bd0df 100644 --- a/crates/wit/tests/init.rs +++ b/crates/wit/tests/init.rs @@ -1,16 +1,18 @@ -use crate::support::*; +use std::{fs, path::Path}; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::str::contains; -use std::{fs, path::Path}; use tempfile::TempDir; +use crate::support::*; + mod support; #[test] fn help() { for arg in ["help init", "init -h", "init --help"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains("Initialize a new WIT package")) .success(); @@ -21,7 +23,7 @@ fn help() { fn it_creates_the_expected_files() -> Result<()> { let dir = TempDir::new()?; - wit("init foo") + wit(["init", "foo"]) .current_dir(dir.path()) .assert() .stderr(contains(format!( @@ -40,7 +42,7 @@ fn it_creates_the_expected_files() -> Result<()> { fn it_supports_registry_option() -> Result<()> { let dir = TempDir::new()?; - wit("init bar --registry https://example.com") + wit(["init", "bar", "--registry", "https://example.com"]) .current_dir(dir.path()) .assert() .stderr(contains(format!( diff --git a/crates/wit/tests/publish.rs b/crates/wit/tests/publish.rs index a2d3c2a6..83203385 100644 --- a/crates/wit/tests/publish.rs +++ b/crates/wit/tests/publish.rs @@ -1,22 +1,23 @@ -use std::{fs, rc::Rc}; +use std::fs; -use crate::support::*; use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::str::contains; use semver::Version; -use tempfile::TempDir; use toml_edit::{value, Array}; use warg_client::{Client, FileSystemClient}; use warg_protocol::registry::PackageName; use wasm_metadata::LinkType; +use wasm_pkg_client::warg::WargRegistryConfig; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help publish", "publish -h", "publish --help"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains("Publish a WIT package to a registry")) .success(); @@ -25,7 +26,7 @@ fn help() { #[test] fn it_fails_with_missing_toml_file() -> Result<()> { - wit("publish") + wit(["publish"]) .assert() .stderr(contains( "error: failed to find configuration file `wit.toml`", @@ -36,14 +37,12 @@ fn it_fails_with_missing_toml_file() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_publishes_a_wit_package() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project.file("baz.wit", "package test:qux;\n")?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:qux` v0.1.0")) @@ -54,14 +53,14 @@ async fn it_publishes_a_wit_package() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_does_a_dry_run_publish() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", Vec::::new())?; project.file("baz.wit", "package test:qux;\n")?; project - .wit("publish --init --dry-run") + .wit(["publish", "--init", "--dry-run"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains( @@ -69,7 +68,7 @@ async fn it_does_a_dry_run_publish() -> Result<()> { )) .success(); - let client = FileSystemClient::new_with_config(None, &config, None).await?; + let client = FileSystemClient::new_with_config(None, &warg_config.client_config, None).await?; assert!(client .download(&"test:qux".parse().unwrap(), &"0.1.0".parse().unwrap()) @@ -83,9 +82,11 @@ async fn it_does_a_dry_run_publish() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_publishes_with_registry_metadata() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); + + let project = server.project("foo", Vec::::new())?; let authors = ["Jane Doe "]; let categories = ["wasm"]; @@ -95,7 +96,6 @@ async fn it_publishes_with_registry_metadata() -> Result<()> { let homepage = "https://example.com/home"; let repository = "https://example.com/repo"; - let project = Project::with_dir(dir.clone(), "foo", "")?; project.file("baz.wit", "package test:qux;\n")?; project.update_manifest(|mut doc| { @@ -110,13 +110,13 @@ async fn it_publishes_with_registry_metadata() -> Result<()> { })?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:qux` v0.1.0")) .success(); - let client = Client::new_with_config(None, &config, None).await?; + let client = Client::new_with_config(None, &warg_config.client_config, None).await?; let download = client .download_exact(&PackageName::new("test:qux")?, &Version::parse("0.1.0")?) .await?; diff --git a/crates/wit/tests/support/mod.rs b/crates/wit/tests/support/mod.rs index 88744afd..62dad4d5 100644 --- a/crates/wit/tests/support/mod.rs +++ b/crates/wit/tests/support/mod.rs @@ -2,9 +2,12 @@ use anyhow::{bail, Context, Result}; use assert_cmd::prelude::OutputAssertExt; +use cargo_component_core::command::{CACHE_DIR_ENV_VAR, CONFIG_FILE_ENV_VAR}; use indexmap::IndexSet; use std::{ - env, fs, + env, + ffi::OsStr, + fs, path::{Path, PathBuf}, process::Command, rc::Rc, @@ -17,8 +20,12 @@ use toml_edit::DocumentMut; use warg_crypto::signing::PrivateKey; use warg_protocol::operator::NamespaceState; use warg_server::{policy::content::WasmContentPolicy, Config, Server}; +use wasm_pkg_client::Registry; use wasmparser::{Chunk, Encoding, Parser, Payload, Validator}; +const WARG_CONFIG_NAME: &str = "warg-config.json"; +const WASM_PKG_CONFIG_NAME: &str = "wasm-pkg-config.json"; + pub fn test_operator_key() -> &'static str { "ecdsa-p256:I+UlDo0HxyBBFeelhPPWmD+LnklOpqZDkrFP5VduASk=" } @@ -53,7 +60,11 @@ fn exclude_test_directories() -> Result<()> { Ok(()) } -pub fn wit(args: &str) -> Command { +pub fn wit(args: I) -> Command +where + I: IntoIterator, + S: AsRef, +{ let mut exe = std::env::current_exe().unwrap(); exe.pop(); // remove test exe name exe.pop(); // remove `deps` @@ -61,16 +72,37 @@ pub fn wit(args: &str) -> Command { exe.set_extension(std::env::consts::EXE_EXTENSION); let mut cmd = Command::new(&exe); - for arg in args.split_whitespace() { - cmd.arg(arg); - } + cmd.args(args); cmd } +// NOTE(thomastaylor312): This is basically a copy/paste of the same helper in the top level +// integration tests. Honestly we should just put this in the crates dir for everything to use in +// this repo, but this is how it was initially, so I am not going to change it for now. pub struct ServerInstance { task: Option>, shutdown: CancellationToken, + root: Rc, +} + +impl ServerInstance { + /// Returns a `Project` that is configured to use the server instance with the correct config. + pub fn project(&self, name: &str, additional_args: I) -> Result + where + I: IntoIterator, + S: Into, + { + let proj = Project { + dir: self.root.clone(), + root: self.root.path().join(name), + config_file: Some(self.root.path().join(WASM_PKG_CONFIG_NAME)), + }; + + proj.new_inner(name, additional_args)?; + + Ok(proj) + } } impl Drop for ServerInstance { @@ -82,17 +114,20 @@ impl Drop for ServerInstance { } } -/// Spawns a server as a background task. -pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::Config)> { +/// Spawns a server as a background task. This will start a +pub async fn spawn_server( + additional_namespaces: I, +) -> Result<(ServerInstance, wasm_pkg_client::Config, Registry)> +where + I: IntoIterator, + S: AsRef, +{ + let root = Rc::new(TempDir::new().context("failed to create temp dir")?); let shutdown = CancellationToken::new(); let config = Config::new( PrivateKey::decode(test_operator_key().to_string())?, - Some( - [("test".to_string(), NamespaceState::Defined)] - .into_iter() - .collect(), - ), - root.join("server"), + Some(vec![("test".to_string(), NamespaceState::Defined)]), + root.path().join("server"), ) .with_addr(([127, 0, 0, 1], 0)) .with_shutdown(shutdown.clone().cancelled_owned()) @@ -109,13 +144,14 @@ pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::C let instance = ServerInstance { task: Some(task), shutdown, + root: root.to_owned(), }; - let config = warg_client::Config { + let warg_config = warg_client::Config { home_url: Some(format!("http://{addr}")), - registries_dir: Some(root.join("registries")), - content_dir: Some(root.join("content")), - namespace_map_path: Some(root.join("namespaces")), + registries_dir: Some(root.path().join("registries")), + content_dir: Some(root.path().join("content")), + namespace_map_path: Some(root.path().join("namespaces")), keys: IndexSet::new(), keyring_auth: false, keyring_backend: None, @@ -124,40 +160,111 @@ pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::C disable_interactive: true, }; - Ok((instance, config)) + let config_file = root.path().join(WARG_CONFIG_NAME); + warg_config.write_to_file(&config_file)?; + + let mut config = wasm_pkg_client::Config::default(); + // We should probably update wasm-pkg-tools to use http for "localhost" or "127.0.0.1" + let registry: Registry = format!("localhost:{}", addr.port()).parse().unwrap(); + config.set_namespace_registry("test".parse().unwrap(), registry.clone()); + for ns in additional_namespaces { + config.set_namespace_registry(ns.as_ref().parse().unwrap(), registry.clone()); + } + let reg_conf = config.get_or_insert_registry_config_mut(®istry); + reg_conf.set_default_backend(Some("warg".to_string())); + reg_conf + .set_backend_config( + "warg", + wasm_pkg_client::warg::WargRegistryConfig { + client_config: warg_config, + auth_token: None, + config_file: Some(config_file), + }, + ) + .expect("Should be able to set backend config"); + + config.to_file(root.path().join(WASM_PKG_CONFIG_NAME))?; + + Ok((instance, config, registry)) } pub struct Project { dir: Rc, root: PathBuf, + config_file: Option, } impl Project { + /// Creates a new project with the given name and whether or not to create a library instead of + /// a binary. This should only be used if you want an "empty" project that doesn't have things + /// like warg config or wasm pkg tools config configured. If you want a project with a warg + /// config and wasm pkg tools config, use the `project` method of `ServerInstance`. pub fn new(name: &str) -> Result { let dir = TempDir::new()?; + let root = dir.path().join(name); + let proj = Self { + dir: Rc::new(dir), + root, + config_file: None, + }; - wit(&format!("init {name}")) - .current_dir(&dir) - .assert() - .try_success()?; + proj.new_inner(name, Vec::::new())?; - let root = dir.path().join(name); + Ok(proj) + } - Ok(Self { + /// Same as `new` but allows you to specify additional arguments to pass to `cargo component + /// new` + pub fn new_with_args(name: &str, additional_args: I) -> Result + where + I: IntoIterator, + S: Into, + { + let dir = TempDir::new()?; + let root = dir.path().join(name); + let proj = Self { dir: Rc::new(dir), root, - }) + config_file: None, + }; + + proj.new_inner(name, additional_args)?; + + Ok(proj) + } + + /// Same as `new` but uses the given temp directory instead of creating a new one. + pub fn with_dir(dir: Rc, name: &str, args: I) -> Result + where + I: IntoIterator, + S: Into, + { + let root = dir.path().join(name); + let proj = Self { + dir, + root, + config_file: None, + }; + + proj.new_inner(name, args)?; + + Ok(proj) } - pub fn with_dir(dir: Rc, name: &str, args: &str) -> Result { - wit(&format!("init {name} {args}")) - .current_dir(dir.as_ref()) + fn new_inner(&self, name: &str, additional_args: I) -> Result<()> + where + I: IntoIterator, + S: Into, + { + let mut args = vec!["init".to_string(), name.to_string()]; + args.extend(additional_args.into_iter().map(|arg| arg.into())); + + self.wit(args) + .current_dir(self.dir.path()) .assert() .try_success()?; - let root = dir.path().join(name); - - Ok(Self { dir, root }) + Ok(()) } pub fn file>(&self, path: B, body: &str) -> Result<&Self> { @@ -175,8 +282,25 @@ impl Project { &self.dir } - pub fn wit(&self, cmd: &str) -> Command { - let mut cmd = wit(cmd); + pub fn cache_dir(&self) -> PathBuf { + self.dir.path().join("cache") + } + + pub fn config_file(&self) -> Option<&Path> { + self.config_file.as_deref() + } + + pub fn wit(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut cmd = wit(args); + // Set the cache dir and the config file env var for every command + if let Some(config_file) = self.config_file() { + cmd.env(CONFIG_FILE_ENV_VAR, config_file); + } + cmd.env(CACHE_DIR_ENV_VAR, self.cache_dir()); cmd.current_dir(&self.root); cmd } diff --git a/crates/wit/tests/update.rs b/crates/wit/tests/update.rs index 0a527d1b..f415d654 100644 --- a/crates/wit/tests/update.rs +++ b/crates/wit/tests/update.rs @@ -1,16 +1,17 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::{prelude::PredicateBooleanExt, str::contains, Predicate}; -use std::{fs, rc::Rc}; -use tempfile::TempDir; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help update", "update -h", "update --help"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains("Update dependencies as recorded in the lock file")) .success(); @@ -19,7 +20,7 @@ fn help() { #[test] fn it_fails_with_missing_toml_file() -> Result<()> { - wit("update") + wit(["update"]) .assert() .stderr(contains( "error: failed to find configuration file `wit.toml`", @@ -30,35 +31,33 @@ fn it_fails_with_missing_toml_file() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_without_changes_is_a_noop() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "bar", "")?; + let project = server.project("bar", Vec::::new())?; project.file("bar.wit", "package test:bar;\n")?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) .success(); - let project = Project::with_dir(dir.clone(), "baz", "")?; + let project = server.project("baz", Vec::::new())?; project.file("baz.wit", "package test:baz;\n")?; project - .wit("add test:bar") + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `0.1.0")) .success(); project - .wit("build") + .wit(["build"]) .assert() .success() .stderr(contains("Created package `baz.wasm`")); project - .wit("update") + .wit(["update"]) .assert() .success() .stderr(contains("test:bar").not()); @@ -68,47 +67,46 @@ async fn update_without_changes_is_a_noop() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_update_without_compatible_changes_is_a_noop() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "bar", "")?; - project.file("bar.wit", "package test:bar;\n")?; - project - .wit("publish --init") + let project1 = server.project("bar", Vec::::new())?; + project1.file("bar.wit", "package test:bar;\n")?; + + project1 + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) .success(); - let project = Project::with_dir(dir.clone(), "baz", "")?; - project.file("baz.wit", "package test:baz;\n")?; - project - .wit("add test:bar") + let project2 = server.project("baz", Vec::::new())?; + project2.file("baz.wit", "package test:baz;\n")?; + project2 + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `0.1.0")) .success(); - project - .wit("build") + project2 + .wit(["build"]) .assert() .success() .stderr(contains("Created package `baz.wasm`")); - fs::write( - dir.path().join("bar/wit.toml"), + project1.file( + "wit.toml", "version = \"1.0.0\"\n[dependencies]\n[registries]\n", )?; - wit("publish") + project1 + .wit(["publish"]) .env("WIT_PUBLISH_KEY", test_signing_key()) - .current_dir(dir.path().join("bar")) .assert() .stderr(contains("Published package `test:bar` v1.0.0")) .success(); - project - .wit("update") + project2 + .wit(["update"]) .assert() .success() .stderr(contains("test:bar").not()); @@ -118,57 +116,55 @@ async fn test_update_without_compatible_changes_is_a_noop() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_compatible_changes() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "bar", "")?; - project.file("bar.wit", "package test:bar;\n")?; - project.file( + let project1 = server.project("bar", Vec::::new())?; + project1.file("bar.wit", "package test:bar;\n")?; + project1.file( "wit.toml", "version = \"1.0.0\"\n[dependencies]\n[registries]\n", )?; - project - .wit("publish --init") + project1 + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v1.0.0")) .success(); - let project = Project::with_dir(dir.clone(), "baz", "")?; - project.file("baz.wit", "package test:baz;\n")?; - project - .wit("add test:bar") + let project2 = server.project("baz", Vec::::new())?; + project2.file("baz.wit", "package test:baz;\n")?; + project2 + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.0.0")) .success(); - project - .wit("build") + project2 + .wit(["build"]) .assert() .success() .stderr(contains("Created package `baz.wasm`")); - fs::write( - dir.path().join("bar/wit.toml"), + project1.file( + "wit.toml", "version = \"1.1.0\"\n[dependencies]\n[registries]\n", )?; - wit("publish") + project1 + .wit(["publish"]) .env("WIT_PUBLISH_KEY", test_signing_key()) - .current_dir(dir.path().join("bar")) .assert() .stderr(contains("Published package `test:bar` v1.1.0")) .success(); - project - .wit("update") + project2 + .wit(["update"]) .assert() .success() .stderr(contains("Updating dependency `test:bar` v1.0.0 -> v1.1.0")); - let lock_file = fs::read_to_string(project.root().join("wit.lock"))?; + let lock_file = fs::read_to_string(project2.root().join("wit.lock"))?; assert!(contains("version = \"1.1.0\"").eval(&lock_file)); Ok(()) @@ -176,57 +172,59 @@ async fn update_with_compatible_changes() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_compatible_changes_is_noop_for_dryrun() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "bar", "")?; - project.file("bar.wit", "package test:bar;\n")?; - project.file( + let project1 = server.project("bar", Vec::::new())?; + project1.file("bar.wit", "package test:bar;\n")?; + project1.file( "wit.toml", "version = \"1.0.0\"\n[dependencies]\n[registries]\n", )?; - project - .wit("publish --init") + project1 + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v1.0.0")) .success(); - let project = Project::with_dir(dir.clone(), "baz", "")?; - project.file("baz.wit", "package test:baz;\n")?; - project - .wit("add test:bar") + let project2 = server.project("baz", Vec::::new())?; + project2.file("baz.wit", "package test:baz;\n")?; + project2 + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.0.0")) .success(); - project - .wit("build") + project2 + .wit(["build"]) .assert() .success() .stderr(contains("Created package `baz.wasm`")); - fs::write( - dir.path().join("bar/wit.toml"), + project1.file( + "wit.toml", "version = \"1.1.0\"\n[dependencies]\n[registries]\n", )?; - wit("publish") + project1 + .wit(["publish"]) .env("WIT_PUBLISH_KEY", test_signing_key()) - .current_dir(dir.path().join("bar")) .assert() .stderr(contains("Published package `test:bar` v1.1.0")) .success(); - project.wit("update --dry-run").assert().success().stderr( - contains("Would update dependency `test:bar` v1.0.0 -> v1.1.0").and(contains( - "warning: not updating lock file due to --dry-run option", - )), - ); + project2 + .wit(["update", "--dry-run"]) + .assert() + .success() + .stderr( + contains("Would update dependency `test:bar` v1.0.0 -> v1.1.0").and(contains( + "warning: not updating lock file due to --dry-run option", + )), + ); - let lock_file = fs::read_to_string(project.root().join("wit.lock"))?; + let lock_file = fs::read_to_string(project2.root().join("wit.lock"))?; assert!(contains("version = \"1.1.0\"").not().eval(&lock_file)); Ok(()) @@ -234,11 +232,9 @@ async fn update_with_compatible_changes_is_noop_for_dryrun() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_changed_dependencies() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(Vec::::new()).await?; - let project = Project::with_dir(dir.clone(), "bar", "")?; + let project = server.project("bar", Vec::::new())?; project.file("bar.wit", "package test:bar;\n")?; project.file( "wit.toml", @@ -246,13 +242,13 @@ async fn update_with_changed_dependencies() -> Result<()> { )?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v1.0.0")) .success(); - let project = Project::with_dir(dir.clone(), "baz", "")?; + let project = server.project("baz", Vec::::new())?; project.file("baz.wit", "package test:baz;\n")?; project.file( "wit.toml", @@ -260,22 +256,22 @@ async fn update_with_changed_dependencies() -> Result<()> { )?; project - .wit("publish --init") + .wit(["publish", "--init"]) .env("WIT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:baz` v1.0.0")) .success(); - let project = Project::with_dir(dir.clone(), "qux", "")?; + let project = server.project("qux", Vec::::new())?; project.file("qux.wit", "package test:qux;\n")?; project - .wit("add test:bar") + .wit(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.0.0")) .success(); project - .wit("build") + .wit(["build"]) .assert() .stderr(contains("Created package `qux.wasm`")) .success(); @@ -286,7 +282,7 @@ async fn update_with_changed_dependencies() -> Result<()> { )?; project - .wit("update") + .wit(["update"]) .assert() .stderr( contains("Removing dependency `test:bar` v1.0.0") @@ -295,7 +291,7 @@ async fn update_with_changed_dependencies() -> Result<()> { .success(); project - .wit("build") + .wit(["build"]) .assert() .stderr(contains("Created package `qux.wasm`")) .success(); diff --git a/crates/wit/tests/version.rs b/crates/wit/tests/version.rs index d17fc45d..b9d0d0d8 100644 --- a/crates/wit/tests/version.rs +++ b/crates/wit/tests/version.rs @@ -7,7 +7,7 @@ mod support; #[test] fn help() { for arg in ["-V", "--version"] { - wit(arg) + wit(arg.split_whitespace()) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))) .success(); diff --git a/src/bin/cargo-component.rs b/src/bin/cargo-component.rs index 49a700f9..7a5e74cf 100644 --- a/src/bin/cargo-component.rs +++ b/src/bin/cargo-component.rs @@ -1,10 +1,15 @@ +use std::path::PathBuf; + use anyhow::{bail, Result}; use cargo_component::{ commands::{AddCommand, NewCommand, PublishCommand, UpdateCommand}, config::{CargoArguments, Config}, load_component_metadata, load_metadata, run_cargo_command, }; -use cargo_component_core::terminal::{Color, Terminal, Verbosity}; +use cargo_component_core::{ + command::{CACHE_DIR_ENV_VAR, CONFIG_FILE_ENV_VAR}, + terminal::{Color, Terminal, Verbosity}, +}; use clap::{CommandFactory, Parser}; fn version() -> &'static str { @@ -144,17 +149,22 @@ async fn main() -> Result<()> { _ => { // Not a built-in command, run the cargo command let cargo_args = CargoArguments::parse()?; - let config = Config::new(Terminal::new( - if cargo_args.quiet { - Verbosity::Quiet - } else { - match cargo_args.verbose { - 0 => Verbosity::Normal, - _ => Verbosity::Verbose, - } - }, - cargo_args.color.unwrap_or_default(), - ))?; + let cache_dir = std::env::var(CACHE_DIR_ENV_VAR).map(PathBuf::from).ok(); + let config_file = std::env::var(CONFIG_FILE_ENV_VAR).map(PathBuf::from).ok(); + let config = Config::new( + Terminal::new( + if cargo_args.quiet { + Verbosity::Quiet + } else { + match cargo_args.verbose { + 0 => Verbosity::Normal, + _ => Verbosity::Verbose, + } + }, + cargo_args.color.unwrap_or_default(), + ), + config_file, + )?; let metadata = load_metadata(cargo_args.manifest_path.as_deref())?; let packages = load_component_metadata( @@ -171,7 +181,9 @@ async fn main() -> Result<()> { } let spawn_args: Vec<_> = std::env::args().skip(1).collect(); + let client = config.client(cache_dir).await?; if let Err(e) = run_cargo_command( + client, &config, &metadata, &packages, diff --git a/src/bindings.rs b/src/bindings.rs index 89fb78b5..497efa09 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -1,21 +1,15 @@ //! Module for bindings generation. - -use crate::{ - last_modified_time, - metadata::{ComponentMetadata, Ownership}, - registry::PackageDependencyResolution, +use std::{ + collections::{HashMap, HashSet}, + path::{Path, PathBuf}, }; + use anyhow::{bail, Context, Result}; use cargo_component_core::registry::DecodedDependency; use heck::ToKebabCase; use indexmap::{IndexMap, IndexSet}; use semver::Version; -use std::{ - collections::{HashMap, HashSet}, - path::{Path, PathBuf}, - time::SystemTime, -}; -use warg_protocol::registry; +use wasm_pkg_client::PackageRef; use wit_bindgen_core::Files; use wit_bindgen_rust::Opts; use wit_component::DecodedWasm; @@ -24,6 +18,8 @@ use wit_parser::{ World, WorldId, WorldItem, WorldKey, }; +use crate::{metadata::Ownership, registry::PackageDependencyResolution}; + // Used to format `unlocked-dep` import names for dependencies on // other components. fn format_dep_import(package: &Package, name: Option<&str>, version: Option<&Version>) -> String { @@ -63,7 +59,6 @@ pub struct BindingsGenerator<'a> { resolution: &'a PackageDependencyResolution<'a>, resolve: Resolve, world: WorldId, - source_files: Vec, } impl<'a> BindingsGenerator<'a> { @@ -71,23 +66,24 @@ impl<'a> BindingsGenerator<'a> { /// and package dependency resolution. /// /// Returns a tuple of the bindings generator and a map of import names. - pub fn new( + pub async fn new( resolution: &'a PackageDependencyResolution<'a>, ) -> Result)>> { let mut import_name_map = Default::default(); - match Self::create_target_world(resolution, &mut import_name_map).with_context(|| { - format!( - "failed to create a target world for package `{name}` ({path})", - name = resolution.metadata.name, - path = resolution.metadata.manifest_path.display() - ) - })? { - Some((resolve, world, source_files)) => Ok(Some(( + match Self::create_target_world(resolution, &mut import_name_map) + .await + .with_context(|| { + format!( + "failed to create a target world for package `{name}` ({path})", + name = resolution.metadata.name, + path = resolution.metadata.manifest_path.display() + ) + })? { + Some((resolve, world, _)) => Ok(Some(( Self { resolution, resolve, world, - source_files, }, import_name_map, ))), @@ -95,53 +91,6 @@ impl<'a> BindingsGenerator<'a> { } } - /// Gets the cargo metadata for the package that the bindings are for. - pub fn metadata(&self) -> &ComponentMetadata { - self.resolution.metadata - } - - /// Gets the reason for generating the bindings. - /// - /// If this returns `Ok(None)`, then the bindings are up-to-date and - /// do not need to be regenerated. - pub fn reason( - &self, - last_modified_exe: SystemTime, - last_modified_output: Option, - ) -> Result> { - let last_modified_output = match last_modified_output { - Some(time) => time, - None => return Ok(Some("the bindings have not been generated yet")), - }; - - let metadata = self.metadata(); - let exe_modified = last_modified_exe > last_modified_output; - let manifest_modified = metadata.modified_at > last_modified_output; - let target_modified = if let Some(path) = metadata.target_path() { - last_modified_time(&path)? > last_modified_output - } else { - false - }; - - if exe_modified - || manifest_modified - || target_modified - || self.dependencies_are_newer(last_modified_output)? - { - Ok(Some(if manifest_modified { - "the manifest was modified" - } else if target_modified { - "the target WIT package was modified" - } else if exe_modified { - "the cargo-component executable was modified" - } else { - "a dependency was modified" - })) - } else { - Ok(None) - } - } - /// Generates the bindings source for a package. pub fn generate(self) -> Result { let settings = &self.resolution.metadata.section.bindings; @@ -196,32 +145,8 @@ impl<'a> BindingsGenerator<'a> { Ok(sources[0].to_string()) } - fn dependencies_are_newer(&self, last_modified_output: SystemTime) -> Result { - for dep in &self.source_files { - if last_modified_time(dep)? > last_modified_output { - log::debug!( - "target source file `{path}` has been modified", - path = dep.display() - ); - return Ok(true); - } - } - - for (_, dep) in self.resolution.all() { - if last_modified_time(dep.path())? > last_modified_output { - log::debug!( - "dependency `{path}` has been modified", - path = dep.path().display() - ); - return Ok(true); - } - } - - Ok(false) - } - - fn create_target_world( - resolution: &PackageDependencyResolution, + async fn create_target_world( + resolution: &PackageDependencyResolution<'_>, import_name_map: &mut HashMap, ) -> Result)>> { log::debug!( @@ -233,16 +158,17 @@ impl<'a> BindingsGenerator<'a> { // A flag used to determine whether the target is empty. It must meet two conditions: // no wit files and no dependencies. let mut empty_target = false; - let (mut merged, world_id, source_files) = - if let Some(name) = resolution.metadata.target_package() { - Self::target_package(resolution, name, resolution.metadata.target_world())? - } else if let Some(path) = resolution.metadata.target_path() { - Self::target_local_path(resolution, &path, resolution.metadata.target_world())? - } else { - empty_target = true; - let (merged, world) = Self::target_empty_world(resolution); - (merged, world, Vec::new()) - }; + let (mut merged, world_id, source_files) = if let Some(name) = + resolution.metadata.target_package() + { + Self::target_package(resolution, name, resolution.metadata.target_world()).await? + } else if let Some(path) = resolution.metadata.target_path() { + Self::target_local_path(resolution, &path, resolution.metadata.target_world()).await? + } else { + empty_target = true; + let (merged, world) = Self::target_empty_world(resolution); + (merged, world, Vec::new()) + }; // Merge all component dependencies as interface imports for (id, dependency) in &resolution.resolutions { @@ -250,7 +176,8 @@ impl<'a> BindingsGenerator<'a> { empty_target = false; let (mut resolve, component_world_id) = dependency - .decode()? + .decode() + .await? .into_component_world() .with_context(|| format!("failed to decode component dependency `{id}`"))?; @@ -282,9 +209,9 @@ impl<'a> BindingsGenerator<'a> { Ok(Some((merged, world_id, source_files))) } - fn target_package( - resolution: &PackageDependencyResolution, - name: ®istry::PackageName, + async fn target_package( + resolution: &PackageDependencyResolution<'_>, + name: &PackageRef, world: Option<&str>, ) -> Result<(Resolve, WorldId, Vec)> { // We must have resolved a target package dependency at this point @@ -292,12 +219,13 @@ impl<'a> BindingsGenerator<'a> { // Decode the target package dependency let dependency = resolution.target_resolutions.values().next().unwrap(); - let (resolve, pkg, source_files) = dependency.decode()?.resolve().with_context(|| { - format!( - "failed to resolve target package `{name}`", - name = dependency.name() - ) - })?; + let (resolve, pkg, source_files) = + dependency.decode().await?.resolve().with_context(|| { + format!( + "failed to resolve target package `{name}`", + name = dependency.name() + ) + })?; let world = resolve .select_world(pkg, world) @@ -306,8 +234,8 @@ impl<'a> BindingsGenerator<'a> { Ok((resolve, world, source_files)) } - fn target_local_path( - resolution: &PackageDependencyResolution, + async fn target_local_path( + resolution: &PackageDependencyResolution<'_>, path: &Path, world: Option<&str>, ) -> Result<(Resolve, WorldId, Vec)> { @@ -316,7 +244,7 @@ impl<'a> BindingsGenerator<'a> { // Start by decoding all of the target dependencies let mut deps = IndexMap::new(); for (id, resolution) in &resolution.target_resolutions { - let decoded = resolution.decode()?; + let decoded = resolution.decode().await?; let name = decoded.package_name(); if let Some(prev) = deps.insert(name.clone(), decoded) { diff --git a/src/commands/add.rs b/src/commands/add.rs index 794866f4..d6b86760 100644 --- a/src/commands/add.rs +++ b/src/commands/add.rs @@ -1,9 +1,9 @@ -use crate::{ - config::CargoPackageSpec, - load_component_metadata, load_metadata, - metadata::{ComponentMetadata, Target}, - Config, PackageComponentMetadata, +use std::{ + fs, + path::{Path, PathBuf}, + sync::Arc, }; + use anyhow::{bail, Context, Result}; use cargo_component_core::{ command::CommonOptions, @@ -13,12 +13,18 @@ use cargo_component_core::{ use cargo_metadata::Package; use clap::Args; use semver::VersionReq; -use std::{ - fs, - path::{Path, PathBuf}, -}; use toml_edit::{value, DocumentMut, InlineTable, Item, Table, Value}; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::{ + caching::{CachingClient, FileCache}, + PackageRef, +}; + +use crate::{ + config::CargoPackageSpec, + load_component_metadata, load_metadata, + metadata::{ComponentMetadata, Target}, + Config, PackageComponentMetadata, +}; /// Add a dependency for a WebAssembly component #[derive(Args)] @@ -46,7 +52,7 @@ pub struct AddCommand { /// The name of the dependency to use; defaults to the package name. #[clap(long, value_name = "NAME")] - pub name: Option, + pub name: Option, /// The name of the package to add a dependency to. #[clap(value_name = "PACKAGE")] @@ -64,9 +70,11 @@ pub struct AddCommand { impl AddCommand { /// Executes the command pub async fn exec(self) -> Result<()> { - let config = Config::new(self.common.new_terminal())?; + let config = Config::new(self.common.new_terminal(), self.common.config.clone())?; let metadata = load_metadata(self.manifest_path.as_deref())?; + let client = config.client(self.common.cache_dir.clone()).await?; + let spec = match &self.spec { Some(spec) => Some(spec.clone()), None => CargoPackageSpec::find_current_package_spec(&metadata), @@ -104,7 +112,7 @@ impl AddCommand { ), )?; } else { - let version = self.resolve_version(&config, &metadata, name, true).await?; + let version = self.resolve_version(client, name).await?; let version = version.trim_start_matches('^'); self.add(package, version)?; @@ -119,18 +127,10 @@ impl AddCommand { async fn resolve_version( &self, - config: &Config, - metadata: &ComponentMetadata, - name: &PackageName, - network_allowed: bool, + client: Arc>, + name: &PackageRef, ) -> Result { - let mut resolver = DependencyResolver::new( - config.warg(), - &metadata.section.registries, - None, - config.terminal(), - network_allowed, - )?; + let mut resolver = DependencyResolver::new_with_client(client, None); let dependency = Dependency::Package(RegistryPackage { name: Some(self.package.name.clone()), version: self @@ -231,13 +231,15 @@ impl AddCommand { self.with_dependencies(pkg, |dependencies| { match self.name.as_ref() { Some(name) => { - dependencies[name.as_ref()] = value(InlineTable::from_iter([ + let str_name = name.to_string(); + dependencies[&str_name] = value(InlineTable::from_iter([ ("package", Value::from(self.package.name.to_string())), ("version", Value::from(version)), ])); } _ => { - dependencies[self.package.name.as_ref()] = value(version); + let str_name = self.package.name.to_string(); + dependencies[&str_name] = value(version); } } Ok(()) @@ -247,11 +249,11 @@ impl AddCommand { fn add_from_path(&self, pkg: &Package, path: &Path) -> Result<()> { self.with_dependencies(pkg, |dependencies| { let key = match self.name.as_ref() { - Some(name) => name.as_ref(), - None => self.package.name.as_ref(), + Some(name) => name.to_string(), + None => self.package.name.to_string(), }; - dependencies[key] = value(InlineTable::from_iter([( + dependencies[&key] = value(InlineTable::from_iter([( "path", Value::from(path.to_str().unwrap()), )])); @@ -260,7 +262,7 @@ impl AddCommand { }) } - fn validate(&self, metadata: &ComponentMetadata, name: &PackageName) -> Result<()> { + fn validate(&self, metadata: &ComponentMetadata, name: &PackageRef) -> Result<()> { if self.target { match &metadata.section.target { Target::Package { .. } => { diff --git a/src/commands/new.rs b/src/commands/new.rs index fa09a1b4..9f3c784a 100644 --- a/src/commands/new.rs +++ b/src/commands/new.rs @@ -1,4 +1,11 @@ -use crate::{config::Config, generator::SourceGenerator, metadata, metadata::DEFAULT_WIT_DIR}; +use std::{ + borrow::Cow, + fs, + path::{Path, PathBuf}, + process::Command, + sync::Arc, +}; + use anyhow::{bail, Context, Result}; use cargo_component_core::{ command::CommonOptions, @@ -7,15 +14,10 @@ use cargo_component_core::{ use clap::Args; use heck::ToKebabCase; use semver::VersionReq; -use std::{ - borrow::Cow, - collections::HashMap, - fs, - path::{Path, PathBuf}, - process::Command, -}; use toml_edit::{table, value, DocumentMut, Item, Table, Value}; -use url::Url; +use wasm_pkg_client::caching::{CachingClient, FileCache}; + +use crate::{config::Config, generator::SourceGenerator, metadata, metadata::DEFAULT_WIT_DIR}; const WIT_BINDGEN_RT_CRATE: &str = "wit-bindgen-rt"; @@ -143,25 +145,22 @@ impl NewCommand { pub async fn exec(self) -> Result<()> { log::debug!("executing new command"); - let config = Config::new(self.common.new_terminal())?; + let config = Config::new(self.common.new_terminal(), self.common.config.clone())?; let name = PackageName::new(&self.namespace, self.name.as_deref(), &self.path)?; let out_dir = std::env::current_dir() .with_context(|| "couldn't get the current directory of the process")? .join(&self.path); - let registries = self.registries()?; let target: Option = match self.target.as_deref() { Some(s) if s.contains('@') => Some(s.parse()?), Some(s) => Some(format!("{s}@{version}", version = VersionReq::STAR).parse()?), None => None, }; - - let target = self - .resolve_target(&config, ®istries, target, true) - .await?; - let source = self.generate_source(&target)?; + let client = config.client(self.common.cache_dir.clone()).await?; + let target = self.resolve_target(client, target).await?; + let source = self.generate_source(&target).await?; let mut command = self.new_command(); match command.status() { @@ -175,7 +174,15 @@ impl NewCommand { } } - self.update_manifest(&config, &name, &out_dir, ®istries, &target)?; + let target = target.map(|(res, world)| { + match res { + DependencyResolution::Registry(reg) => (reg, world), + // This is unreachable because when we got the initial target, we made sure it was a + // registry target. + _ => unreachable!(), + } + }); + self.update_manifest(&config, &name, &out_dir, &target)?; self.create_source_file(&config, &out_dir, source.as_ref(), &target)?; self.create_targets_file(&name, &out_dir)?; self.create_editor_settings_file(&out_dir)?; @@ -222,7 +229,6 @@ impl NewCommand { config: &Config, name: &PackageName, out_dir: &Path, - registries: &HashMap, target: &Option<(RegistryResolution, Option)>, ) -> Result<()> { let manifest_path = out_dir.join("Cargo.toml"); @@ -287,14 +293,6 @@ impl NewCommand { component["dependencies"] = Item::Table(Table::new()); - if !registries.is_empty() { - let mut table = Table::new(); - for (name, url) in registries { - table[name] = value(url.as_str()); - } - component["registries"] = Item::Table(table); - } - if self.proxy { component["proxy"] = value(true); } @@ -339,15 +337,15 @@ impl NewCommand { self.bin || !self.lib } - fn generate_source( + async fn generate_source( &self, - target: &Option<(RegistryResolution, Option)>, + target: &Option<(DependencyResolution, Option)>, ) -> Result> { match target { Some((resolution, world)) => { let generator = - SourceGenerator::new(&resolution.name, &resolution.path, !self.no_rustfmt); - generator.generate(world.as_deref()).map(Into::into) + SourceGenerator::new(resolution, resolution.name(), !self.no_rustfmt); + generator.generate(world.as_deref()).await.map(Into::into) } None => { if self.is_command() { @@ -520,26 +518,20 @@ world example {{ } } + /// This will always return a registry resolution if it is `Some`, but we return the + /// `DependencyResolution` instead so we can actually resolve the dependency. async fn resolve_target( &self, - config: &Config, - registries: &HashMap, + client: Arc>, target: Option, - network_allowed: bool, - ) -> Result)>> { + ) -> Result)>> { match target { Some(metadata::Target::Package { name, package, world, }) => { - let mut resolver = DependencyResolver::new( - config.warg(), - registries, - None, - config.terminal(), - network_allowed, - )?; + let mut resolver = DependencyResolver::new_with_client(client, None); let dependency = Dependency::Package(package); resolver.add_dependency(&name, &dependency).await?; @@ -547,29 +539,15 @@ world example {{ let dependencies = resolver.resolve().await?; assert_eq!(dependencies.len(), 1); - match dependencies - .into_values() - .next() - .expect("expected a target resolution") - { - DependencyResolution::Registry(resolution) => Ok(Some((resolution, world))), - _ => unreachable!(), - } + Ok(Some(( + dependencies + .into_values() + .next() + .expect("expected a target resolution"), + world, + ))) } _ => Ok(None), } } - - fn registries(&self) -> Result> { - let mut registries = HashMap::new(); - - if let Some(url) = self.registry.as_deref() { - registries.insert( - "default".to_string(), - url.parse().context("failed to parse registry URL")?, - ); - } - - Ok(registries) - } } diff --git a/src/commands/publish.rs b/src/commands/publish.rs index 5e934096..4c8b8841 100644 --- a/src/commands/publish.rs +++ b/src/commands/publish.rs @@ -1,13 +1,16 @@ +use std::path::PathBuf; + +use anyhow::{bail, Context, Result}; +use cargo_component_core::{command::CommonOptions, registry::find_url}; +use clap::Args; +use warg_crypto::signing::PrivateKey; +use warg_protocol::registry::PackageName; + use crate::{ config::{CargoArguments, CargoPackageSpec, Config}, is_wasm_target, load_metadata, publish, run_cargo_command, PackageComponentMetadata, PublishOptions, }; -use anyhow::{bail, Context, Result}; -use cargo_component_core::{command::CommonOptions, registry::find_url}; -use clap::Args; -use std::path::PathBuf; -use warg_crypto::signing::PrivateKey; /// Publish a package to a registry. #[derive(Args)] @@ -79,7 +82,8 @@ impl PublishCommand { pub async fn exec(self) -> Result<()> { log::debug!("executing publish command"); - let config = Config::new(self.common.new_terminal())?; + let config = Config::new(self.common.new_terminal(), self.common.config.clone())?; + let client = config.client(self.common.cache_dir.clone()).await?; if let Some(target) = &self.target { if !is_wasm_target(target) { @@ -153,6 +157,7 @@ impl PublishCommand { let spawn_args = self.build_args()?; let outputs = run_cargo_command( + client, &config, &metadata, &packages, @@ -167,12 +172,13 @@ impl PublishCommand { len = outputs.len() ); } - + // Safe to unwrap here because we already know a PackageRef is valid + let package_name = PackageName::new(name.to_string()).unwrap(); let options = PublishOptions { package, registry_url, init: self.init, - name, + name: &package_name, version: &component_metadata.version, path: &outputs[0], signing_key, diff --git a/src/commands/update.rs b/src/commands/update.rs index 3f890b9c..a4fdf834 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -1,9 +1,10 @@ -use crate::{load_component_metadata, load_metadata, Config}; use anyhow::Result; use cargo_component_core::command::CommonOptions; use clap::Args; use std::path::PathBuf; +use crate::{load_component_metadata, load_metadata, Config}; + /// Update dependencies as recorded in the component lock file #[derive(Args)] #[clap(disable_version_flag = true)] @@ -37,17 +38,17 @@ impl UpdateCommand { /// Executes the command. pub async fn exec(self) -> Result<()> { log::debug!("executing update command"); - let config = Config::new(self.common.new_terminal())?; + let config = Config::new(self.common.new_terminal(), self.common.config)?; let metadata = load_metadata(self.manifest_path.as_deref())?; let packages = load_component_metadata(&metadata, [].iter(), true)?; - let network_allowed = !self.frozen && !self.offline; let lock_update_allowed = !self.frozen && !self.locked; + let client = config.client(self.common.cache_dir).await?; crate::update_lockfile( + client, &config, &metadata, &packages, - network_allowed, lock_update_allowed, self.locked, self.dry_run, diff --git a/src/config.rs b/src/config.rs index 3c880c2f..6743b5f1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,14 +19,18 @@ //! to function. use anyhow::{anyhow, bail, Context, Result}; +use cargo_component_core::cache_dir; use cargo_component_core::terminal::{Color, Terminal}; use cargo_metadata::Metadata; use parse_arg::{iter_short, match_arg}; use semver::Version; use std::fmt; use std::str::FromStr; +use std::sync::Arc; use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; use toml_edit::DocumentMut; +use wasm_pkg_client::caching::{CachingClient, FileCache}; +use wasm_pkg_client::Client; /// Represents a cargo package specifier. /// @@ -489,15 +493,22 @@ impl CargoArguments { pub struct Config { /// The warg client configuration. pub warg: warg_client::Config, + /// The package configuration to use + pub pkg_config: wasm_pkg_client::Config, /// The terminal to use. terminal: Terminal, } impl Config { /// Create a new `Config` with the given terminal. - pub fn new(terminal: Terminal) -> Result { + pub fn new(terminal: Terminal, config_path: Option) -> Result { + let pkg_config = match config_path { + Some(path) => wasm_pkg_client::Config::from_file(path)?, + None => wasm_pkg_client::Config::global_defaults()?, + }; Ok(Self { warg: warg_client::Config::from_default_file()?.unwrap_or_default(), + pkg_config, terminal, }) } @@ -507,10 +518,26 @@ impl Config { &self.warg } + /// Gets the package configuration. + pub fn pkg_config(&self) -> &wasm_pkg_client::Config { + &self.pkg_config + } + /// Gets a reference to the terminal for writing messages. pub fn terminal(&self) -> &Terminal { &self.terminal } + + /// Creates a [`Client`] from this configuration. + pub async fn client( + &self, + cache: Option, + ) -> anyhow::Result>> { + Ok(Arc::new(CachingClient::new( + Client::new(self.pkg_config.clone()), + FileCache::new(cache_dir(cache)?).await?, + ))) + } } #[cfg(test)] diff --git a/src/generator.rs b/src/generator.rs index 3391b5eb..61088688 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,21 +1,19 @@ //! A module for implementing the Rust source generator used for //! the `--target` option of the `new` command. - -use anyhow::{bail, Context, Result}; -use heck::{AsSnakeCase, ToSnakeCase, ToUpperCamelCase}; -use indexmap::{map::Entry, IndexMap, IndexSet}; use std::{ borrow::Cow, collections::{BTreeMap, BTreeSet}, fmt::{self, Write}, - fs, io::Read, - path::Path, process::{Command, Stdio}, }; -use warg_protocol::registry::PackageName; + +use anyhow::{bail, Context, Result}; +use cargo_component_core::registry::DependencyResolution; +use heck::{AsSnakeCase, ToSnakeCase, ToUpperCamelCase}; +use indexmap::{map::Entry, IndexMap, IndexSet}; +use wasm_pkg_client::PackageRef; use wit_bindgen_rust::to_rust_ident; -use wit_component::DecodedWasm; use wit_parser::{ Function, FunctionKind, Handle, Interface, Resolve, Type, TypeDef, TypeDefKind, TypeId, TypeOwner, World, WorldId, WorldItem, WorldKey, @@ -741,8 +739,8 @@ impl<'a> ImplementationGenerator<'a> { /// The generated source defines a component that will implement the expected /// export traits for the given world. pub struct SourceGenerator<'a> { - name: &'a PackageName, - path: &'a Path, + resolution: &'a DependencyResolution, + name: &'a PackageRef, format: bool, } @@ -751,13 +749,17 @@ impl<'a> SourceGenerator<'a> { /// a binary-encoded target wit package. /// /// If `format` is true, then `cargo fmt` will be run on the generated source. - pub fn new(name: &'a PackageName, path: &'a Path, format: bool) -> Self { - Self { name, path, format } + pub fn new(resolution: &'a DependencyResolution, name: &'a PackageRef, format: bool) -> Self { + Self { + resolution, + name, + format, + } } /// Generates the Rust source code for the given world. - pub fn generate(&self, world: Option<&str>) -> Result { - let (resolve, world) = self.decode(world)?; + pub async fn generate(&self, world: Option<&str>) -> Result { + let (resolve, world) = self.decode(world).await?; let mut names = ReservedNames::default(); let generator = ImplementationGenerator::new(&resolve, &resolve.worlds[world], &mut names); @@ -815,34 +817,14 @@ impl<'a> SourceGenerator<'a> { Ok(source) } - fn decode(&self, world: Option<&str>) -> Result<(Resolve, WorldId)> { - let bytes = fs::read(self.path).with_context(|| { - format!( - "failed to read the content of target package `{name}` path `{path}`", - name = self.name, - path = self.path.display() - ) - })?; - - let decoded = wit_component::decode(&bytes).with_context(|| { + async fn decode(&self, world: Option<&str>) -> Result<(Resolve, WorldId)> { + let (resolve, pkg_id, _) = self.resolution.decode().await?.resolve()?; + let world = resolve.select_world(pkg_id, world).with_context(|| { format!( - "failed to decode the content of target package `{name}` path `{path}`", - name = self.name, - path = self.path.display() + "failed to select world from target package `{name}`", + name = self.name ) })?; - - match decoded { - DecodedWasm::WitPackage(resolve, package) => { - let world = resolve.select_world(package, world).with_context(|| { - format!( - "failed to select world from target package `{name}`", - name = self.name - ) - })?; - Ok((resolve, world)) - } - DecodedWasm::Component(..) => bail!("target is not a WIT package"), - } + Ok((resolve, world)) } } diff --git a/src/lib.rs b/src/lib.rs index 000be812..5035cfb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,19 @@ #![deny(missing_docs)] -use crate::target::install_wasm32_wasip1; +use std::{ + borrow::Cow, + collections::HashMap, + env, + fmt::{self, Write}, + fs::{self, File}, + io::{BufRead, BufReader, Read, Seek, SeekFrom}, + path::{Path, PathBuf}, + process::{Command, Stdio}, + sync::Arc, + time::{Duration, SystemTime}, +}; + use anyhow::{bail, Context, Result}; use bindings::BindingsGenerator; use bytes::Bytes; @@ -13,31 +25,24 @@ use cargo_component_core::{ }; use cargo_config2::{PathAndArgs, TargetTripleRef}; use cargo_metadata::{Artifact, Message, Metadata, MetadataCommand, Package}; -use config::{CargoArguments, CargoPackageSpec, Config}; -use lock::{acquire_lock_file_ro, acquire_lock_file_rw}; -use metadata::ComponentMetadata; -use registry::{PackageDependencyResolution, PackageResolutionMap}; use semver::Version; use shell_escape::escape; -use std::{ - borrow::Cow, - collections::HashMap, - env, - fmt::{self, Write}, - fs::{self, File}, - io::{BufRead, BufReader, Read, Seek, SeekFrom}, - path::{Path, PathBuf}, - process::{Command, Stdio}, - time::{Duration, SystemTime}, -}; use tempfile::NamedTempFile; use warg_client::storage::{ContentStorage, PublishEntry, PublishInfo}; use warg_crypto::signing::PrivateKey; use warg_protocol::registry::PackageName; use wasm_metadata::{Link, LinkType, RegistryMetadata}; +use wasm_pkg_client::caching::{CachingClient, FileCache}; use wasmparser::{Parser, Payload}; use wit_component::ComponentEncoder; +use crate::target::install_wasm32_wasip1; + +use config::{CargoArguments, CargoPackageSpec, Config}; +use lock::{acquire_lock_file_ro, acquire_lock_file_rw}; +use metadata::ComponentMetadata; +use registry::{PackageDependencyResolution, PackageResolutionMap}; + mod bindings; pub mod commands; pub mod config; @@ -135,6 +140,7 @@ impl From<&str> for CargoCommand { /// /// Returns any relevant output components. pub async fn run_cargo_command( + client: Arc>, config: &Config, metadata: &Metadata, packages: &[PackageComponentMetadata<'_>], @@ -142,7 +148,7 @@ pub async fn run_cargo_command( cargo_args: &CargoArguments, spawn_args: &[String], ) -> Result> { - let import_name_map = generate_bindings(config, metadata, packages, cargo_args).await?; + let import_name_map = generate_bindings(client, config, metadata, packages, cargo_args).await?; let cargo_path = std::env::var("CARGO") .map(PathBuf::from) @@ -729,12 +735,12 @@ pub fn load_component_metadata<'a>( } async fn generate_bindings( + client: Arc>, config: &Config, metadata: &Metadata, packages: &[PackageComponentMetadata<'_>], cargo_args: &CargoArguments, ) -> Result>> { - let last_modified_exe = last_modified_time(&std::env::current_exe()?)?; let file_lock = acquire_lock_file_ro(config.terminal(), metadata)?; let lock_file = file_lock .as_ref() @@ -752,14 +758,13 @@ async fn generate_bindings( env::current_dir().with_context(|| "couldn't get the current directory of the process")?; let resolver = lock_file.as_ref().map(LockFileResolver::new); - let resolution_map = - create_resolution_map(config, packages, resolver, cargo_args.network_allowed()).await?; + let resolution_map = create_resolution_map(client, packages, resolver).await?; let mut import_name_map = HashMap::new(); for PackageComponentMetadata { package, .. } in packages { let resolution = resolution_map.get(&package.id).expect("missing resolution"); import_name_map.insert( package.name.clone(), - generate_package_bindings(config, resolution, last_modified_exe, &cwd).await?, + generate_package_bindings(config, resolution, &cwd).await?, ); } @@ -789,16 +794,15 @@ async fn generate_bindings( } async fn create_resolution_map<'a>( - config: &Config, + client: Arc>, packages: &'a [PackageComponentMetadata<'_>], lock_file: Option>, - network_allowed: bool, ) -> Result> { let mut map = PackageResolutionMap::default(); for PackageComponentMetadata { package, metadata } in packages { let resolution = - PackageDependencyResolution::new(config, metadata, lock_file, network_allowed).await?; + PackageDependencyResolution::new(client.clone(), metadata, lock_file).await?; map.insert(package.id.clone(), resolution); } @@ -809,7 +813,6 @@ async fn create_resolution_map<'a>( async fn generate_package_bindings( config: &Config, resolution: &PackageDependencyResolution<'_>, - last_modified_exe: SystemTime, cwd: &Path, ) -> Result> { if !resolution.metadata.section_present && resolution.metadata.target_path().is_none() { @@ -821,7 +824,7 @@ async fn generate_package_bindings( } // If there is no wit files and no dependencies, stop generating the bindings file for it. - let (generator, import_name_map) = match BindingsGenerator::new(resolution)? { + let (generator, import_name_map) = match BindingsGenerator::new(resolution).await? { Some(v) => v, None => return Ok(HashMap::new()), }; @@ -835,54 +838,32 @@ async fn generate_package_bindings( .join("src"); let bindings_path = output_dir.join("bindings.rs"); - let last_modified_output = bindings_path - .is_file() - .then(|| last_modified_time(&bindings_path)) - .transpose()?; - - match generator.reason(last_modified_exe, last_modified_output)? { - Some(reason) => { - log::debug!( - "generating bindings for package `{name}` at `{path}` because {reason}", - name = resolution.metadata.name, - path = bindings_path.display(), - ); - - config.terminal().status( - "Generating", - format!( - "bindings for {name} ({path})", - name = resolution.metadata.name, - path = bindings_path - .strip_prefix(cwd) - .unwrap_or(&bindings_path) - .display() - ), - )?; + config.terminal().status( + "Generating", + format!( + "bindings for {name} ({path})", + name = resolution.metadata.name, + path = bindings_path + .strip_prefix(cwd) + .unwrap_or(&bindings_path) + .display() + ), + )?; - let bindings = generator.generate()?; - fs::create_dir_all(&output_dir).with_context(|| { - format!( - "failed to create output directory `{path}`", - path = output_dir.display() - ) - })?; + let bindings = generator.generate()?; + fs::create_dir_all(&output_dir).with_context(|| { + format!( + "failed to create output directory `{path}`", + path = output_dir.display() + ) + })?; - fs::write(&bindings_path, bindings).with_context(|| { - format!( - "failed to write bindings file `{path}`", - path = bindings_path.display() - ) - })?; - } - None => { - log::debug!( - "existing bindings for package `{name}` at `{path}` is up-to-date", - name = resolution.metadata.name, - path = bindings_path.display(), - ); - } - } + fs::write(&bindings_path, bindings).with_context(|| { + format!( + "failed to write bindings file `{path}`", + path = bindings_path.display() + ) + })?; Ok(import_name_map) } @@ -1176,16 +1157,16 @@ pub async fn publish(config: &Config, options: &PublishOptions<'_>) -> Result<() /// /// This updates only `Cargo-component.lock`. pub async fn update_lockfile( + client: Arc>, config: &Config, metadata: &Metadata, packages: &[PackageComponentMetadata<'_>], - network_allowed: bool, lock_update_allowed: bool, locked: bool, dry_run: bool, ) -> Result<()> { // Read the current lock file and generate a new one - let map = create_resolution_map(config, packages, None, network_allowed).await?; + let map = create_resolution_map(client, packages, None).await?; let file_lock = acquire_lock_file_ro(config.terminal(), metadata)?; let orig_lock_file = file_lock diff --git a/src/metadata.rs b/src/metadata.rs index 486279bd..4eac2117 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -1,4 +1,11 @@ //! Module for component metadata representation in `Cargo.toml`. +use std::{ + borrow::Cow, + collections::HashMap, + path::{Path, PathBuf}, + str::FromStr, + time::SystemTime, +}; use anyhow::{bail, Context, Result}; use cargo_component_core::registry::{Dependency, RegistryPackage}; @@ -9,15 +16,8 @@ use serde::{ Deserialize, }; use serde_json::from_value; -use std::{ - borrow::Cow, - collections::HashMap, - path::{Path, PathBuf}, - str::FromStr, - time::SystemTime, -}; use url::Url; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::PackageRef; /// The default directory to look for a target WIT file. pub const DEFAULT_WIT_DIR: &str = "wit"; @@ -133,7 +133,7 @@ pub enum Target { /// The target is a world from a registry package. Package { /// The name of the target package (e.g. `wasi:http`). - name: PackageName, + name: PackageRef, /// The registry package being targeted. package: RegistryPackage, /// The name of the world being targeted. @@ -158,13 +158,13 @@ pub enum Target { /// [select-world]: https://docs.rs/wit-parser/latest/wit_parser/struct.Resolve.html#method.select_world world: Option, /// The dependencies of the wit document being targeted. - dependencies: HashMap, + dependencies: HashMap, }, } impl Target { /// Gets the dependencies of the target. - pub fn dependencies(&self) -> Cow> { + pub fn dependencies(&self) -> Cow> { match self { Self::Package { name, package, .. } => Cow::Owned(HashMap::from_iter([( name.clone(), @@ -260,7 +260,7 @@ impl<'de> Deserialize<'de> for Target { world: Option, registry: Option, path: Option, - dependencies: HashMap, + dependencies: HashMap, } let entry = Entry::deserialize(MapAccessDeserializer::new(map))?; @@ -320,13 +320,13 @@ impl<'de> Deserialize<'de> for Target { #[serde(default, deny_unknown_fields)] pub struct ComponentSection { /// The package name of the component, for publishing. - pub package: Option, + pub package: Option, /// The world targeted by the component. pub target: Target, /// The path to the WASI adapter to use. pub adapter: Option, /// The dependencies of the component. - pub dependencies: HashMap, + pub dependencies: HashMap, /// The registries to use for the component. pub registries: HashMap, /// The configuration for bindings generation. @@ -433,7 +433,7 @@ impl ComponentMetadata { /// Gets the target package name. /// /// Returns `None` if the target is not a registry package. - pub fn target_package(&self) -> Option<&PackageName> { + pub fn target_package(&self) -> Option<&PackageRef> { match &self.section.target { Target::Package { name, .. } => Some(name), _ => None, diff --git a/src/registry.rs b/src/registry.rs index 640470ea..fe69a894 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -1,6 +1,6 @@ //! Module for interacting with component registries. +use std::{collections::HashMap, sync::Arc}; -use crate::{config::Config, metadata::ComponentMetadata}; use anyhow::Result; use cargo_component_core::{ lock::{LockFile, LockFileResolver, LockedPackage, LockedPackageVersion}, @@ -8,9 +8,12 @@ use cargo_component_core::{ }; use cargo_metadata::PackageId; use semver::Version; -use std::collections::HashMap; -use warg_crypto::hash::AnyHash; -use warg_protocol::registry::PackageName; +use wasm_pkg_client::{ + caching::{CachingClient, FileCache}, + ContentDigest, PackageRef, +}; + +use crate::metadata::ComponentMetadata; /// Represents a resolution of dependencies for a Cargo package. #[derive(Debug, Clone)] @@ -28,49 +31,36 @@ impl<'a> PackageDependencyResolution<'a> { /// /// Returns `Ok(None)` if the package is not a component package. pub async fn new( - config: &Config, + client: Arc>, metadata: &'a ComponentMetadata, lock_file: Option>, - network_allowed: bool, ) -> Result> { Ok(Self { metadata, - target_resolutions: Self::resolve_target_deps( - config, - metadata, - lock_file, - network_allowed, - ) - .await?, - resolutions: Self::resolve_deps(config, metadata, lock_file, network_allowed).await?, + target_resolutions: Self::resolve_target_deps(client.clone(), metadata, lock_file) + .await?, + resolutions: Self::resolve_deps(client, metadata, lock_file).await?, }) } /// Iterates over all dependency resolutions of the package. - pub fn all(&self) -> impl Iterator { + pub fn all(&self) -> impl Iterator { self.target_resolutions .iter() .chain(self.resolutions.iter()) } async fn resolve_target_deps( - config: &Config, + client: Arc>, metadata: &ComponentMetadata, lock_file: Option>, - network_allowed: bool, ) -> Result { let target_deps = metadata.section.target.dependencies(); if target_deps.is_empty() { return Ok(Default::default()); } - let mut resolver = DependencyResolver::new( - config.warg(), - &metadata.section.registries, - lock_file, - config.terminal(), - network_allowed, - )?; + let mut resolver = DependencyResolver::new_with_client(client, lock_file); for (name, dependency) in target_deps.iter() { resolver.add_dependency(name, dependency).await?; @@ -80,22 +70,15 @@ impl<'a> PackageDependencyResolution<'a> { } async fn resolve_deps( - config: &Config, + client: Arc>, metadata: &ComponentMetadata, lock_file: Option>, - network_allowed: bool, ) -> Result { if metadata.section.dependencies.is_empty() { return Ok(Default::default()); } - let mut resolver = DependencyResolver::new( - config.warg(), - &metadata.section.registries, - lock_file, - config.terminal(), - network_allowed, - )?; + let mut resolver = DependencyResolver::new_with_client(client, lock_file); for (name, dependency) in &metadata.section.dependencies { resolver.add_dependency(name, dependency).await?; @@ -129,8 +112,8 @@ impl<'a> PackageResolutionMap<'a> { /// Converts the resolution map into a lock file. pub fn to_lock_file(&self) -> LockFile { - type PackageKey = (PackageName, Option); - type VersionsMap = HashMap; + type PackageKey = (PackageRef, Option); + type VersionsMap = HashMap; let mut packages: HashMap = HashMap::new(); for resolution in self.0.values() { diff --git a/tests/add.rs b/tests/add.rs index 59ea0c2f..12d917e9 100644 --- a/tests/add.rs +++ b/tests/add.rs @@ -1,17 +1,20 @@ -use crate::support::*; +use std::{fs, rc::Rc}; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::{prelude::*, str::contains}; -use std::{fs, rc::Rc}; use tempfile::TempDir; use toml_edit::value; +use wasm_pkg_client::warg::WargRegistryConfig; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help add", "add -h", "add --help"] { - cargo_component(arg) + cargo_component(arg.split_whitespace()) .assert() .stdout(contains("Add a dependency for a WebAssembly component")) .success(); @@ -20,7 +23,7 @@ fn help() { #[test] fn requires_package() { - cargo_component("add") + cargo_component(["add"]) .assert() .stderr(contains("cargo component add ")) .failure(); @@ -28,16 +31,14 @@ fn requires_package() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn validate_the_package_exists() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(["foo"]).await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", true, Vec::::new())?; project - .cargo_component("add foo:bar") + .cargo_component(["add", "foo:bar"]) .assert() - .stderr(contains("package `foo:bar` does not exist")) + .stderr(contains("package `foo:bar` was not found")) .failure(); Ok(()) @@ -45,16 +46,25 @@ async fn validate_the_package_exists() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn validate_the_version_exists() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; - - publish_component(&config, "test:bar", "1.1.0", "(component)", true).await?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + // NOTE(thomastaylor312): Once we have publishing in wasm_pkg_client, we won't need to get the config directly like this + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); + + publish_component( + &warg_config.client_config, + "test:bar", + "1.1.0", + "(component)", + true, + ) + .await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", true, Vec::::new())?; project - .cargo_component("add test:bar") + .cargo_component(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.1.0`")) .success(); @@ -63,7 +73,7 @@ async fn validate_the_version_exists() -> Result<()> { assert!(contains(r#""test:bar" = "1.1.0""#).eval(&manifest)); project - .cargo_component("add --name test:bar2 test:bar@2.0.0") + .cargo_component(["add", "--name", "test:bar2", "test:bar@2.0.0"]) .assert() .stderr(contains( "component registry package `test:bar` has no release matching version requirement `^2.0.0`", @@ -75,19 +85,27 @@ async fn validate_the_version_exists() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn adds_dependencies_to_target_component() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); - publish_component(&config, "test:bar", "1.1.0", "(component)", true).await?; + publish_component( + &warg_config.client_config, + "test:bar", + "1.1.0", + "(component)", + true, + ) + .await?; - let project = Project::with_dir(dir.clone(), "foo_target", "")?; + let project = server.project("foo_target", true, Vec::::new())?; let manifest = fs::read_to_string(project.root().join("Cargo.toml"))?; assert!(!contains("package.metadata.component.target.dependencies").eval(&manifest)); project - .cargo_component("add test:bar --target") + .cargo_component(["add", "test:bar", "--target"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.1.0`")); @@ -96,7 +114,7 @@ async fn adds_dependencies_to_target_component() -> Result<()> { assert!(contains("package.metadata.component.target.dependencies").eval(&manifest)); project - .cargo_component("add test:bar --target") + .cargo_component(["add", "test:bar", "--target"]) .assert() .stderr(contains( "cannot add dependency `test:bar` as it conflicts with an existing dependency", @@ -107,14 +125,14 @@ async fn adds_dependencies_to_target_component() -> Result<()> { #[test] fn checks_for_duplicate_dependencies() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["dependencies"]["foo:bar"] = value("1.2.3"); Ok(doc) })?; project - .cargo_component("add foo:bar") + .cargo_component(["add", "foo:bar"]) .assert() .stderr(contains( "cannot add dependency `foo:bar` as it conflicts with an existing dependency", @@ -126,16 +144,24 @@ fn checks_for_duplicate_dependencies() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn prints_modified_manifest_for_dry_run() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); - publish_component(&config, "test:bar", "1.2.3", "(component)", true).await?; + publish_component( + &warg_config.client_config, + "test:bar", + "1.2.3", + "(component)", + true, + ) + .await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", true, Vec::::new())?; project - .cargo_component("add --dry-run test:bar") + .cargo_component(["add", "--dry-run", "test:bar"]) .assert() .stderr(contains( r#"Added dependency `test:bar` with version `1.2.3`"#, @@ -152,12 +178,12 @@ async fn prints_modified_manifest_for_dry_run() -> Result<()> { fn validate_add_from_path(project: &Project) -> Result<()> { project - .cargo_component("add --path foo/baz foo:baz") + .cargo_component(["add", "--path", "foo/baz", "foo:baz"]) .assert() .stderr(contains("Added dependency `foo:baz` from path `foo/baz`")); project - .cargo_component("add --target --path foo/qux foo:qux") + .cargo_component(["add", "--target", "--path", "foo/qux", "foo:qux"]) .assert() .stderr(contains("Added dependency `foo:qux` from path `foo/qux`")); @@ -169,7 +195,7 @@ fn validate_add_from_path(project: &Project) -> Result<()> { #[test] fn test_validate_add_from_path() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; validate_add_from_path(&project)?; Ok(()) } @@ -191,8 +217,8 @@ resolver = "2" cargo_workspace = cargo_workspace.display() ) })?; - let p1 = Project::with_dir(temp_dir.clone(), "foo", "")?; - let p2 = Project::with_dir(temp_dir.clone(), "bar", "")?; + let p1 = Project::with_dir(temp_dir.clone(), "foo", true, Vec::::new())?; + let p2 = Project::with_dir(temp_dir.clone(), "bar", true, Vec::::new())?; validate_add_from_path(&p1)?; validate_add_from_path(&p2)?; diff --git a/tests/bench.rs b/tests/bench.rs index 191186a2..72f61e17 100644 --- a/tests/bench.rs +++ b/tests/bench.rs @@ -1,8 +1,10 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::str::contains; -use std::fs; + +use crate::support::*; mod support; @@ -12,7 +14,7 @@ mod support; ignore = "test is currently failing in ci and needs to be debugged" )] fn it_runs_bench_with_basic_component() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; fs::write( project.root().join("wit/world.wit"), @@ -69,7 +71,7 @@ fn bench_recursive_fibonacci(b: &mut Bencher) { )?; project - .cargo_component("bench") + .cargo_component(["bench"]) .env("RUSTUP_TOOLCHAIN", "nightly") .assert() .stdout(contains("test bench_recursive_fibonacci ...")) diff --git a/tests/build.rs b/tests/build.rs index 57a3bdd5..453d7473 100644 --- a/tests/build.rs +++ b/tests/build.rs @@ -1,19 +1,21 @@ -use crate::support::*; +use std::{fs, process::Command, rc::Rc}; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::{prelude::PredicateBooleanExt, str::contains}; -use std::{fs, process::Command, rc::Rc}; use tempfile::TempDir; use toml_edit::{value, Array, Item, Table}; +use crate::support::*; + mod support; #[test] fn it_builds_debug() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -31,10 +33,10 @@ fn it_builds_debug() -> Result<()> { #[test] fn it_builds_a_bin_project_with_snake_case() -> Result<()> { - let project = Project::new_bin("hello_world")?; + let project = Project::new("hello_world", false)?; project - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -46,10 +48,10 @@ fn it_builds_a_bin_project_with_snake_case() -> Result<()> { #[test] fn it_builds_a_bin_project() -> Result<()> { - let project = Project::new_bin("foo")?; + let project = Project::new("foo", false)?; project - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -62,10 +64,7 @@ fn it_builds_a_bin_project() -> Result<()> { #[test] fn it_builds_a_workspace() -> Result<()> { let dir = Rc::new(TempDir::new()?); - let project = Project { - dir: dir.clone(), - root: dir.path().to_owned(), - }; + let project = Project::new_uninitialized(dir.clone(), dir.path().to_owned()); project.file( "baz/Cargo.toml", @@ -81,13 +80,13 @@ edition = "2021" project.file("baz/src/lib.rs", "")?; project - .cargo_component("new --lib foo") + .cargo_component(["new", "--lib", "foo"]) .assert() .stderr(contains("Updated manifest of package `foo`")) .success(); project - .cargo_component("new --lib bar") + .cargo_component(["new", "--lib", "bar"]) .assert() .stderr(contains("Updated manifest of package `bar`")) .success(); @@ -101,7 +100,7 @@ edition = "2021" )?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -116,10 +115,10 @@ edition = "2021" #[test] fn it_supports_wit_keywords() -> Result<()> { - let project = Project::new("interface")?; + let project = Project::new("interface", true)?; project - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -131,10 +130,10 @@ fn it_supports_wit_keywords() -> Result<()> { #[test] fn it_adds_a_producers_field() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -161,10 +160,10 @@ fn it_adds_a_producers_field() -> Result<()> { #[test] fn it_builds_wasm32_unknown_unknown_from_cli() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("build --target wasm32-unknown-unknown") + .cargo_component(["build", "--target", "wasm32-unknown-unknown"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -184,7 +183,7 @@ fn it_builds_wasm32_unknown_unknown_from_cli() -> Result<()> { #[test] fn it_builds_wasm32_unknown_unknown_from_config() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.file( ".cargo/config.toml", @@ -194,7 +193,7 @@ target = "wasm32-unknown-unknown" )?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -214,10 +213,10 @@ target = "wasm32-unknown-unknown" #[test] fn it_builds_wasm32_unknown_unknown_from_env() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("build") + .cargo_component(["build"]) .env("CARGO_BUILD_TARGET", "wasm32-unknown-unknown") .assert() .stderr(contains( @@ -238,14 +237,14 @@ fn it_builds_wasm32_unknown_unknown_from_env() -> Result<()> { #[test] fn it_regenerates_target_if_wit_changed() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["target"]["world"] = value("example"); Ok(doc) })?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -254,16 +253,10 @@ fn it_regenerates_target_if_wit_changed() -> Result<()> { validate_component(&project.debug_wasm("foo"))?; - project - .cargo_component("build") - .assert() - .stderr(contains("Generating bindings").not()) - .success(); - fs::write(project.root().join("wit/other.wit"), "world foo {}")?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains("Generating bindings")) .success(); @@ -273,7 +266,7 @@ fn it_regenerates_target_if_wit_changed() -> Result<()> { #[test] fn it_builds_with_local_wit_deps() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { let mut dependencies = Table::new(); dependencies["foo:bar"]["path"] = value("wit/deps/foo-bar"); @@ -353,7 +346,7 @@ bindings::export!(Component with_types_in bindings); )?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -367,7 +360,7 @@ bindings::export!(Component with_types_in bindings); #[test] fn empty_world_with_dep_valid() -> Result<()> { - let project = Project::new("dep")?; + let project = Project::new("dep", true)?; fs::write( project.root().join("wit/world.wit"), @@ -402,12 +395,12 @@ fn empty_world_with_dep_valid() -> Result<()> { ", )?; - project.cargo_component("build").assert().success(); + project.cargo_component(["build"]).assert().success(); let dep = project.debug_wasm("dep"); validate_component(&dep)?; - let project = Project::with_dir(project.dir().clone(), "main", "")?; + let project = Project::with_dir(project.dir().clone(), "main", true, Vec::::new())?; project.update_manifest(|mut doc| { let table = doc["package"]["metadata"]["component"] .as_table_mut() @@ -435,7 +428,7 @@ fn empty_world_with_dep_valid() -> Result<()> { ", )?; - project.cargo_component("build").assert().success(); + project.cargo_component(["build"]).assert().success(); validate_component(&project.debug_wasm("main"))?; Ok(()) @@ -443,7 +436,7 @@ fn empty_world_with_dep_valid() -> Result<()> { #[test] fn it_builds_with_resources() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; fs::write( project.root().join("wit/world.wit"), @@ -501,7 +494,7 @@ fn it_builds_with_resources() -> Result<()> { "#, )?; - project.cargo_component("build").assert().success(); + project.cargo_component(["build"]).assert().success(); let dep = project.debug_wasm("foo"); validate_component(&dep)?; @@ -511,7 +504,7 @@ fn it_builds_with_resources() -> Result<()> { #[test] fn it_builds_resources_with_specified_ownership_model() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["bindings"]["ownership"] = value("borrowing-duplicate-if-necessary"); @@ -574,7 +567,7 @@ fn it_builds_resources_with_specified_ownership_model() -> Result<()> { "#, )?; - project.cargo_component("build").assert().success(); + project.cargo_component(["build"]).assert().success(); let dep = project.debug_wasm("foo"); validate_component(&dep)?; @@ -584,8 +577,7 @@ fn it_builds_resources_with_specified_ownership_model() -> Result<()> { #[test] fn it_builds_with_a_component_dependency() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let comp1 = Project::with_dir(dir.clone(), "comp1", "")?; + let comp1 = Project::new("comp1", true)?; fs::write( comp1.root().join("wit/world.wit"), @@ -642,7 +634,7 @@ bindings::export!(Component with_types_in bindings); )?; comp1 - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -650,7 +642,7 @@ bindings::export!(Component with_types_in bindings); let dep = comp1.release_wasm("comp1"); validate_component(&dep)?; - let comp2 = Project::with_dir(dir.clone(), "comp2", "")?; + let comp2 = Project::with_dir(comp1.dir.clone(), "comp2", true, Vec::::new())?; comp2.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["dependencies"]["my:comp1"]["path"] = value(dep.display().to_string()); @@ -689,7 +681,7 @@ bindings::export!(Component with_types_in bindings); )?; comp2 - .cargo_component("build --release") + .cargo_component(["build", "--release"]) .assert() .stderr(contains("Finished `release` profile [optimized] target(s)")) .success(); @@ -702,19 +694,19 @@ bindings::export!(Component with_types_in bindings); #[test] fn it_builds_with_adapter() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["adapter"] = value("not-a-valid-path"); Ok(doc) })?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains("error: failed to read module adapter")) .failure(); - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; let adapter_path = "adapter/wasi_snapshot_preview1.wasm"; project.file( adapter_path, @@ -726,7 +718,7 @@ fn it_builds_with_adapter() -> Result<()> { })?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -740,7 +732,7 @@ fn it_builds_with_adapter() -> Result<()> { #[test] fn it_errors_if_adapter_is_not_wasm() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["adapter"] = value("foo.wasm"); Ok(doc) @@ -749,7 +741,7 @@ fn it_errors_if_adapter_is_not_wasm() -> Result<()> { fs::write(project.root().join("foo.wasm"), "not wasm")?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains("error: failed to load adapter module")) .failure(); @@ -759,7 +751,7 @@ fn it_errors_if_adapter_is_not_wasm() -> Result<()> { #[test] fn it_adds_additional_derives() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["bindings"]["derives"] = value(Array::from_iter(["serde::Serialize", "serde::Deserialize"])); @@ -819,7 +811,7 @@ bindings::export!(Component with_types_in bindings); )?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -833,7 +825,7 @@ bindings::export!(Component with_types_in bindings); #[test] fn it_builds_with_versioned_wit() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; fs::write( project.root().join("wit/world.wit"), @@ -866,7 +858,7 @@ fn it_builds_with_versioned_wit() -> Result<()> { "#, )?; - project.cargo_component("build").assert().success(); + project.cargo_component(["build"]).assert().success(); let dep = project.debug_wasm("foo"); validate_component(&dep)?; @@ -876,14 +868,14 @@ fn it_builds_with_versioned_wit() -> Result<()> { #[test] fn it_warns_on_proxy_setting_for_command() -> Result<()> { - let project = Project::new_bin("foo")?; + let project = Project::new("foo", false)?; project.update_manifest(|mut doc| { doc["package"]["metadata"]["component"]["proxy"] = value(true); Ok(doc) })?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "warning: ignoring `proxy` setting in `Cargo.toml` for command component", @@ -897,7 +889,7 @@ fn it_warns_on_proxy_setting_for_command() -> Result<()> { #[test] fn it_warns_with_proxy_and_adapter_settings() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; let adapter_path = "adapter/wasi_snapshot_preview1.wasm"; project.file( adapter_path, @@ -910,7 +902,7 @@ fn it_warns_with_proxy_and_adapter_settings() -> Result<()> { })?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains("warning: ignoring `proxy` setting due to `adapter` setting being present in `Cargo.toml`")) .success(); @@ -922,11 +914,10 @@ fn it_warns_with_proxy_and_adapter_settings() -> Result<()> { #[test] fn it_builds_with_proxy_adapter() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let project = Project::with_dir(dir.clone(), "foo", "--proxy")?; + let project = Project::new_with_args("foo", true, ["--proxy"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -955,7 +946,7 @@ fn it_does_not_generate_bindings_for_cargo_projects() -> Result<()> { cmd.arg(name); cmd.assert().stderr(contains("Creating")).success(); - let mut cmd = cargo_component("build"); + let mut cmd = cargo_component(["build"]); cmd.current_dir(dir.path().join(name)); cmd.assert() .stderr(contains("Generating bindings").not()) diff --git a/tests/check.rs b/tests/check.rs index 4cd9ee61..72bfb2cd 100644 --- a/tests/check.rs +++ b/tests/check.rs @@ -1,18 +1,20 @@ -use crate::support::*; +use std::{fmt::Write, fs, rc::Rc}; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::{boolean::PredicateBooleanExt, str::contains}; -use std::{fmt::Write, fs, rc::Rc}; use tempfile::TempDir; +use crate::support::*; + mod support; #[test] fn it_checks_a_new_project() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("check") + .cargo_component(["check"]) .assert() .stderr(contains("Checking foo v0.1.0")) .success(); @@ -22,7 +24,7 @@ fn it_checks_a_new_project() -> Result<()> { #[test] fn it_finds_errors() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; let mut src = fs::read_to_string(project.root().join("src/lib.rs"))?; write!(&mut src, "\n\nfn foo() -> String {{\n \"foo\"\n}}\n")?; @@ -30,7 +32,7 @@ fn it_finds_errors() -> Result<()> { fs::write(project.root().join("src/lib.rs"), src)?; project - .cargo_component("check") + .cargo_component(["check"]) .assert() .stderr(contains("Checking foo v0.1.0").and(contains("expected `String`, found `&str`"))) .failure(); @@ -41,10 +43,8 @@ fn it_finds_errors() -> Result<()> { #[test] fn it_checks_a_workspace() -> Result<()> { let dir = Rc::new(TempDir::new()?); - let project = Project { - dir: dir.clone(), - root: dir.path().to_owned(), - }; + let root = dir.path().to_owned(); + let project = Project::new_uninitialized(dir, root); project.file( "baz/Cargo.toml", @@ -60,13 +60,13 @@ edition = "2021" project.file("baz/src/lib.rs", "")?; project - .cargo_component("new --lib foo") + .cargo_component(["new", "--lib", "foo"]) .assert() .stderr(contains("Updated manifest of package `foo`")) .success(); project - .cargo_component("new --lib bar") + .cargo_component(["new", "--lib", "bar"]) .assert() .stderr(contains("Updated manifest of package `bar`")) .success(); @@ -80,7 +80,7 @@ edition = "2021" )?; project - .cargo_component("check") + .cargo_component(["check"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", diff --git a/tests/clippy.rs b/tests/clippy.rs index 75f77330..8b40296e 100644 --- a/tests/clippy.rs +++ b/tests/clippy.rs @@ -1,18 +1,20 @@ -use crate::support::*; +use std::{fmt::Write, fs, rc::Rc}; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::{boolean::PredicateBooleanExt, str::contains}; -use std::{fmt::Write, fs, rc::Rc}; use tempfile::TempDir; +use crate::support::*; + mod support; #[test] fn it_checks_a_new_project() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("clippy") + .cargo_component(["clippy"]) .assert() .stderr(contains("Checking foo v0.1.0")) .success(); @@ -22,7 +24,7 @@ fn it_checks_a_new_project() -> Result<()> { #[test] fn it_finds_errors() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; let mut src = fs::read_to_string(project.root().join("src/lib.rs"))?; write!(&mut src, "\n\nfn foo() -> String {{\n \"foo\"\n}}\n")?; @@ -30,7 +32,7 @@ fn it_finds_errors() -> Result<()> { fs::write(project.root().join("src/lib.rs"), src)?; project - .cargo_component("clippy") + .cargo_component(["clippy"]) .assert() .stderr(contains("Checking foo v0.1.0").and(contains("expected `String`, found `&str`"))) .failure(); @@ -40,7 +42,7 @@ fn it_finds_errors() -> Result<()> { #[test] fn it_finds_clippy_warnings() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; let mut src = fs::read_to_string(project.root().join("src/lib.rs"))?; write!( @@ -51,7 +53,7 @@ fn it_finds_clippy_warnings() -> Result<()> { fs::write(project.root().join("src/lib.rs"), src)?; project - .cargo_component("clippy") + .cargo_component(["clippy"]) .assert() .stderr(contains("Checking foo v0.1.0").and(contains("clippy::needless_return"))) .success(); @@ -62,10 +64,8 @@ fn it_finds_clippy_warnings() -> Result<()> { #[test] fn it_checks_a_workspace() -> Result<()> { let dir = Rc::new(TempDir::new()?); - let project = Project { - dir: dir.clone(), - root: dir.path().to_owned(), - }; + let root = dir.path().to_owned(); + let project = Project::new_uninitialized(dir, root); project.file( "baz/Cargo.toml", @@ -81,13 +81,13 @@ edition = "2021" project.file("baz/src/lib.rs", "")?; project - .cargo_component("new --lib foo") + .cargo_component(["new", "--lib", "foo"]) .assert() .stderr(contains("Updated manifest of package `foo`")) .success(); project - .cargo_component("new --lib bar") + .cargo_component(["new", "--lib", "bar"]) .assert() .stderr(contains("Updated manifest of package `bar`")) .success(); @@ -101,7 +101,7 @@ members = ["foo", "bar", "baz"] )?; project - .cargo_component("clippy") + .cargo_component(["clippy"]) .assert() .stderr(contains("Checking foo v0.1.0").and(contains("Checking bar v0.1.0"))) .success(); diff --git a/tests/doc.rs b/tests/doc.rs index 777d91a6..f4e1f989 100644 --- a/tests/doc.rs +++ b/tests/doc.rs @@ -1,17 +1,19 @@ -use crate::support::*; +use std::fs; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::str::contains; -use std::fs; + +use crate::support::*; mod support; #[test] fn it_documents() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("doc") + .cargo_component(["doc"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", diff --git a/tests/metadata.rs b/tests/metadata.rs index f0837ba3..cad6fbc6 100644 --- a/tests/metadata.rs +++ b/tests/metadata.rs @@ -1,19 +1,20 @@ use std::rc::Rc; -use crate::support::*; use anyhow::Result; use assert_cmd::prelude::*; use predicates::{prelude::PredicateBooleanExt, str::contains}; use tempfile::TempDir; +use crate::support::*; + mod support; #[test] fn it_prints_metadata() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; project - .cargo_component("metadata --format-version 1") + .cargo_component(["metadata", "--format-version", "1"]) .assert() .stdout(contains(r#""name":"foo","version":"0.1.0""#)) .success(); @@ -23,11 +24,11 @@ fn it_prints_metadata() -> Result<()> { #[test] fn it_rejects_invalid_format_versions() -> Result<()> { - let project = Project::new("foo")?; + let project = Project::new("foo", true)?; for arg in ["7", "0", "42"] { project - .cargo_component(&format!("metadata --format-version {arg}")) + .cargo_component(["metadata", "--format-version", arg]) .assert() .stderr(contains("invalid value")) .failure(); @@ -39,10 +40,8 @@ fn it_rejects_invalid_format_versions() -> Result<()> { #[test] fn it_prints_workspace_metadata() -> Result<()> { let dir = Rc::new(TempDir::new()?); - let project = Project { - dir: dir.clone(), - root: dir.path().to_owned(), - }; + let root = dir.path().to_owned(); + let project = Project::new_uninitialized(dir, root); project.file( "baz/Cargo.toml", @@ -58,13 +57,13 @@ edition = "2021" project.file("baz/src/lib.rs", "")?; project - .cargo_component("new --lib foo") + .cargo_component(["new", "--lib", "foo"]) .assert() .stderr(contains("Updated manifest of package `foo`")) .success(); project - .cargo_component("new --lib bar") + .cargo_component(["new", "--lib", "bar"]) .assert() .stderr(contains("Updated manifest of package `bar`")) .success(); @@ -78,7 +77,7 @@ members = ["foo", "bar", "baz"] )?; project - .cargo_component("metadata --format-version 1") + .cargo_component(["metadata", "--format-version", "1"]) .assert() .stdout( contains(r#"name":"foo","version":"0.1.0""#).and( diff --git a/tests/new.rs b/tests/new.rs index d53d0dcd..95edfddb 100644 --- a/tests/new.rs +++ b/tests/new.rs @@ -1,16 +1,19 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::{str::contains, Predicate}; -use std::{fs, rc::Rc}; use tempfile::TempDir; +use wasm_pkg_client::warg::WargRegistryConfig; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help new", "new -h", "new --help"] { - cargo_component(arg) + cargo_component(arg.split_whitespace()) .assert() .stdout(contains( "Create a new WebAssembly component package at ", @@ -23,7 +26,7 @@ fn help() { fn it_creates_the_expected_files_for_bin() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --bin foo") + cargo_component(["new", "--bin", "foo"]) .current_dir(dir.path()) .assert() .stderr(contains("Updated manifest of package `foo")) @@ -44,7 +47,7 @@ fn it_creates_the_expected_files_for_bin() -> Result<()> { fn it_creates_the_expected_files() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --lib foo") + cargo_component(["new", "--lib", "foo"]) .current_dir(dir.path()) .assert() .stderr(contains("Updated manifest of package `foo`")) @@ -65,7 +68,7 @@ fn it_creates_the_expected_files() -> Result<()> { fn it_supports_editor_option() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --lib foo --editor none") + cargo_component(["new", "--lib", "foo", "--editor", "none"]) .current_dir(dir.path()) .assert() .stderr(contains("Updated manifest of package `foo")) @@ -85,7 +88,7 @@ fn it_supports_editor_option() -> Result<()> { fn it_supports_edition_option() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --lib foo --edition 2018") + cargo_component(["new", "--lib", "foo", "--edition", "2018"]) .current_dir(dir.path()) .assert() .stderr(contains("Updated manifest of package `foo")) @@ -102,7 +105,7 @@ fn it_supports_edition_option() -> Result<()> { fn it_supports_name_option() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --lib foo --name bar") + cargo_component(["new", "--lib", "foo", "--name", "bar"]) .current_dir(dir.path()) .assert() .stderr(contains("Updated manifest of package `bar`")) @@ -119,7 +122,7 @@ fn it_supports_name_option() -> Result<()> { fn it_rejects_rust_keywords() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --lib foo --name fn") + cargo_component(["new", "--lib", "foo", "--name", "fn"]) .current_dir(dir.path()) .assert() .stderr(contains( @@ -132,12 +135,13 @@ fn it_rejects_rust_keywords() -> Result<()> { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_targets_a_world() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.2.3", r#"package test:bar@1.2.3; @@ -241,9 +245,9 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "component", "--target test:bar/foo@1.0.0")?; + let project = server.project("component", true, ["--target", "test:bar/foo@1.0.0"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -256,13 +260,14 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_errors_if_target_does_not_exist() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, _, _) = spawn_server(["foo"]).await?; - match Project::with_dir(dir.clone(), "component", "--target foo:bar@1.0.0") { + match server.project("component", true, ["--target", "foo:bar@1.0.0"]) { Ok(_) => panic!("expected error"), - Err(e) => assert!(contains("package `foo:bar` does not exist").eval(&e.to_string())), + Err(e) => assert!( + contains("package `foo:bar` was not found").eval(&e.to_string()), + "Should contain error message {e:?}" + ), } Ok(()) @@ -272,7 +277,7 @@ async fn it_errors_if_target_does_not_exist() -> Result<()> { fn it_supports_the_command_option() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --command foo") + cargo_component(["new", "--command", "foo"]) .current_dir(dir.path()) .assert() .try_success()?; @@ -284,7 +289,7 @@ fn it_supports_the_command_option() -> Result<()> { fn it_supports_the_reactor_option() -> Result<()> { let dir = TempDir::new()?; - cargo_component("new --reactor foo") + cargo_component(["new", "--reactor", "foo"]) .current_dir(dir.path()) .assert() .try_success()?; @@ -296,7 +301,7 @@ fn it_supports_the_reactor_option() -> Result<()> { fn it_supports_the_proxy_option() -> Result<()> { let dir: TempDir = TempDir::new()?; - cargo_component("new --lib --proxy foo") + cargo_component(["new", "--lib", "--proxy", "foo"]) .current_dir(dir.path()) .assert() .try_success()?; diff --git a/tests/publish.rs b/tests/publish.rs index 0513dbb9..4ddd875b 100644 --- a/tests/publish.rs +++ b/tests/publish.rs @@ -1,21 +1,23 @@ -use crate::support::*; +use std::fs; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::str::contains; use semver::Version; -use std::{fs, rc::Rc}; -use tempfile::TempDir; use toml_edit::{value, Array}; use warg_client::Client; use warg_protocol::registry::PackageName; use wasm_metadata::LinkType; +use wasm_pkg_client::warg::WargRegistryConfig; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help publish", "publish -h", "publish --help"] { - cargo_component(arg) + cargo_component(arg.split_whitespace()) .assert() .stdout(contains("Publish a package to a registry")) .success(); @@ -24,12 +26,13 @@ fn help() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_publishes_a_component() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:world", "1.0.0", r#"package test:%world@1.0.0; @@ -41,14 +44,18 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "foo", "--namespace test --target test:world")?; + let project = server.project( + "foo", + true, + ["--namespace", "test", "--target", "test:world"], + )?; // Ensure there's a using declaration in the generated source let source = fs::read_to_string(project.root().join("src/lib.rs"))?; assert!(source.contains("use bindings::Guest;")); project - .cargo_component("publish --init") + .cargo_component(["publish", "--init"]) .env("CARGO_COMPONENT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:foo` v0.1.0")) @@ -67,12 +74,13 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_fails_if_package_does_not_exist() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:world", "1.0.0", r#"package test:%world@1.0.0; @@ -84,10 +92,13 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "foo", "--namespace test --target test:world")?; - + let project = server.project( + "foo", + true, + ["--namespace", "test", "--target", "test:world"], + )?; project - .cargo_component("publish") + .cargo_component(["publish"]) .env("CARGO_COMPONENT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains( @@ -100,12 +111,13 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_publishes_a_dependency() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:world", "1.0.0", r#"package test:%world@1.0.0; @@ -116,14 +128,14 @@ world foo { ) .await?; - let project = Project::with_dir( - dir.clone(), + let project = server.project( "foo", - "--namespace test --target test:world/foo", + true, + ["--namespace", "test", "--target", "test:world/foo"], )?; project - .cargo_component("publish --init") + .cargo_component(["publish", "--init"]) .env("CARGO_COMPONENT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:foo` v0.1.0")) @@ -131,10 +143,13 @@ world foo { validate_component(&project.release_wasm("foo"))?; - let project = Project::with_dir(dir.clone(), "bar", "--namespace test --target test:world")?; - + let project = server.project( + "bar", + true, + ["--namespace", "test", "--target", "test:world"], + )?; project - .cargo_component("add test:foo") + .cargo_component(["add", "test:foo"]) .assert() .stderr(contains("Added dependency `test:foo` with version `0.1.0`")) .success(); @@ -156,7 +171,7 @@ bindings::export!(Component with_types_in bindings); fs::write(project.root().join("src/lib.rs"), source)?; project - .cargo_component("publish --init") + .cargo_component(["publish", "--init"]) .env("CARGO_COMPONENT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:bar` v0.1.0")) @@ -169,9 +184,10 @@ bindings::export!(Component with_types_in bindings); #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn it_publishes_with_registry_metadata() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); let authors = ["Jane Doe "]; let categories = ["wasm"]; @@ -181,7 +197,7 @@ async fn it_publishes_with_registry_metadata() -> Result<()> { let homepage = "https://example.com/home"; let repository = "https://example.com/repo"; - let project = Project::with_dir(dir.clone(), "foo", "--namespace test")?; + let project = server.project("foo", true, ["--namespace", "test"])?; project.update_manifest(|mut doc| { let package = &mut doc["package"]; package["authors"] = value(Array::from_iter(authors)); @@ -195,7 +211,7 @@ async fn it_publishes_with_registry_metadata() -> Result<()> { })?; project - .cargo_component("publish --init") + .cargo_component(["publish", "--init"]) .env("CARGO_COMPONENT_PUBLISH_KEY", test_signing_key()) .assert() .stderr(contains("Published package `test:foo` v0.1.0")) @@ -203,7 +219,7 @@ async fn it_publishes_with_registry_metadata() -> Result<()> { validate_component(&project.release_wasm("foo"))?; - let client = Client::new_with_config(None, &config, None).await?; + let client = Client::new_with_config(None, &warg_config.client_config, None).await?; let download = client .download_exact(&PackageName::new("test:foo")?, &Version::parse("0.1.0")?) .await?; diff --git a/tests/run.rs b/tests/run.rs index b4b9e692..b0ebf789 100644 --- a/tests/run.rs +++ b/tests/run.rs @@ -1,15 +1,17 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::str::contains; -use std::fs; use toml_edit::{value, Item, Table}; +use crate::support::*; + mod support; #[test] fn it_runs_with_command_component() -> Result<()> { - let project = Project::new_bin("bar")?; + let project = Project::new("bar", false)?; fs::write( project.root().join("src/main.rs"), @@ -22,7 +24,7 @@ fn main() { )?; project - .cargo_component("run") + .cargo_component(["run"]) .arg("--") .arg("--verbose") .assert() @@ -36,7 +38,7 @@ fn main() { #[test] fn it_runs_with_reactor_component() -> Result<()> { - let project = Project::new("baz")?; + let project = Project::new("baz", true)?; project.update_manifest(|mut doc| { let mut dependencies = Table::new(); dependencies["wasi:cli"]["path"] = value("wit/deps/cli"); @@ -94,7 +96,7 @@ bindings::export!(Component with_types_in bindings); )?; project - .cargo_component("run") + .cargo_component(["run"]) .env( "CARGO_TARGET_WASM32_WASIP1_RUNNER", "wasmtime --env APP_NAME=CargoComponent -C cache=no -W component-model -S preview2 -S cli", diff --git a/tests/support/mod.rs b/tests/support/mod.rs index 07cf5531..f645e4af 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -1,15 +1,17 @@ #![allow(dead_code)] - -use anyhow::{bail, Context, Result}; -use assert_cmd::prelude::OutputAssertExt; -use indexmap::IndexSet; use std::{ + ffi::OsStr, fs, path::{Path, PathBuf}, process::Command, rc::Rc, time::Duration, }; + +use anyhow::{bail, Context, Result}; +use assert_cmd::prelude::OutputAssertExt; +use cargo_component_core::command::{CACHE_DIR_ENV_VAR, CONFIG_FILE_ENV_VAR}; +use indexmap::IndexSet; use tempfile::TempDir; use tokio::task::JoinHandle; use tokio_util::sync::CancellationToken; @@ -21,9 +23,13 @@ use warg_client::{ use warg_crypto::signing::PrivateKey; use warg_protocol::{operator::NamespaceState, registry::PackageName}; use warg_server::{policy::content::WasmContentPolicy, Config, Server}; +use wasm_pkg_client::Registry; use wasmparser::{Chunk, Encoding, Parser, Payload, Validator}; use wit_parser::{Resolve, UnresolvedPackage}; +const WARG_CONFIG_NAME: &str = "warg-config.json"; +const WASM_PKG_CONFIG_NAME: &str = "wasm-pkg-config.json"; + pub fn test_operator_key() -> &'static str { "ecdsa-p256:I+UlDo0HxyBBFeelhPPWmD+LnklOpqZDkrFP5VduASk=" } @@ -32,7 +38,11 @@ pub fn test_signing_key() -> &'static str { "ecdsa-p256:2CV1EpLaSYEn4In4OAEDAj5O4Hzu8AFAxgHXuG310Ew=" } -pub fn cargo_component(args: &str) -> Command { +pub fn cargo_component(args: I) -> Command +where + I: IntoIterator, + S: AsRef, +{ let mut exe = std::env::current_exe().unwrap(); exe.pop(); // remove test exe name exe.pop(); // remove `deps` @@ -41,9 +51,7 @@ pub fn cargo_component(args: &str) -> Command { let mut cmd = Command::new(&exe); cmd.arg("component"); - for arg in args.split_whitespace() { - cmd.arg(arg); - } + cmd.args(args); cmd } @@ -135,6 +143,25 @@ pub async fn publish_wit( pub struct ServerInstance { task: Option>, shutdown: CancellationToken, + root: Rc, +} + +impl ServerInstance { + /// Returns a `Project` that is configured to use the server instance with the correct config. + pub fn project(&self, name: &str, lib: bool, additional_args: I) -> Result + where + I: IntoIterator, + S: Into, + { + let proj = Project { + dir: self.root.clone(), + root: self.root.path().join(name), + config_file: Some(self.root.path().join(WASM_PKG_CONFIG_NAME)), + }; + + proj.new_inner(name, lib, additional_args)?; + Ok(proj) + } } impl Drop for ServerInstance { @@ -146,17 +173,20 @@ impl Drop for ServerInstance { } } -/// Spawns a server as a background task. -pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::Config)> { +/// Spawns a server as a background task. This will start a +pub async fn spawn_server( + additional_namespaces: I, +) -> Result<(ServerInstance, wasm_pkg_client::Config, Registry)> +where + I: IntoIterator, + S: AsRef, +{ + let root = Rc::new(TempDir::new().context("failed to create temp dir")?); let shutdown = CancellationToken::new(); let config = Config::new( PrivateKey::decode(test_operator_key().to_string())?, - Some( - [("test".to_string(), NamespaceState::Defined)] - .into_iter() - .collect(), - ), - root.join("server"), + Some(vec![("test".to_string(), NamespaceState::Defined)]), + root.path().join("server"), ) .with_addr(([127, 0, 0, 1], 0)) .with_shutdown(shutdown.clone().cancelled_owned()) @@ -173,13 +203,14 @@ pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::C let instance = ServerInstance { task: Some(task), shutdown, + root: root.to_owned(), }; - let config = warg_client::Config { + let warg_config = warg_client::Config { home_url: Some(format!("http://{addr}")), - registries_dir: Some(root.join("registries")), - content_dir: Some(root.join("content")), - namespace_map_path: Some(root.join("namespaces")), + registries_dir: Some(root.path().join("registries")), + content_dir: Some(root.path().join("content")), + namespace_map_path: Some(root.path().join("namespaces")), keys: IndexSet::new(), keyring_auth: false, keyring_backend: None, @@ -188,57 +219,125 @@ pub async fn spawn_server(root: &Path) -> Result<(ServerInstance, warg_client::C disable_interactive: true, }; - Ok((instance, config)) + let config_file = root.path().join(WARG_CONFIG_NAME); + warg_config.write_to_file(&config_file)?; + + let mut config = wasm_pkg_client::Config::default(); + // We should probably update wasm-pkg-tools to use http for "localhost" or "127.0.0.1" + let registry: Registry = format!("localhost:{}", addr.port()).parse().unwrap(); + config.set_namespace_registry("test".parse().unwrap(), registry.clone()); + for ns in additional_namespaces { + config.set_namespace_registry(ns.as_ref().parse().unwrap(), registry.clone()); + } + let reg_conf = config.get_or_insert_registry_config_mut(®istry); + reg_conf.set_default_backend(Some("warg".to_string())); + reg_conf + .set_backend_config( + "warg", + wasm_pkg_client::warg::WargRegistryConfig { + client_config: warg_config, + auth_token: None, + config_file: Some(config_file), + }, + ) + .expect("Should be able to set backend config"); + + config.to_file(root.path().join(WASM_PKG_CONFIG_NAME))?; + + Ok((instance, config, registry)) } #[derive(Debug)] pub struct Project { pub dir: Rc, pub root: PathBuf, + config_file: Option, } impl Project { - pub fn new(name: &str) -> Result { + /// Creates a new project with the given name and whether or not to create a library instead of + /// a binary. This should only be used if you want an "empty" project that doesn't have things + /// like warg config or wasm pkg tools config configured. If you want a project with a warg + /// config and wasm pkg tools config, use the `project` method of `ServerInstance`. + pub fn new(name: &str, lib: bool) -> Result { let dir = TempDir::new()?; - - cargo_component(&format!("new --lib {name}")) - .current_dir(dir.path()) - .assert() - .try_success()?; - let root = dir.path().join(name); - - Ok(Self { + let proj = Self { dir: Rc::new(dir), root, - }) - } + config_file: None, + }; - pub fn new_bin(name: &str) -> Result { - let dir = TempDir::new()?; + proj.new_inner(name, lib, Vec::::new())?; - cargo_component(&format!("new {name}")) - .current_dir(dir.path()) - .assert() - .try_success()?; + Ok(proj) + } + /// Same as `new` but allows you to specify additional arguments to pass to `cargo component + /// new` + pub fn new_with_args(name: &str, lib: bool, additional_args: I) -> Result + where + I: IntoIterator, + S: Into, + { + let dir = TempDir::new()?; let root = dir.path().join(name); - - Ok(Self { + let proj = Self { dir: Rc::new(dir), root, - }) + config_file: None, + }; + + proj.new_inner(name, lib, additional_args)?; + + Ok(proj) } - pub fn with_dir(dir: Rc, name: &str, args: &str) -> Result { - cargo_component(&format!("new --lib {name} {args}")) - .current_dir(dir.path()) + fn new_inner(&self, name: &str, lib: bool, additional_args: I) -> Result<()> + where + I: IntoIterator, + S: Into, + { + let mut args = vec!["new".to_string(), name.to_string()]; + if lib { + args.push("--lib".to_string()); + } + args.extend(additional_args.into_iter().map(|arg| arg.into())); + + self.cargo_component(args) + .current_dir(self.dir.path()) .assert() .try_success()?; + Ok(()) + } + + /// Same as `new` but uses the given temp directory instead of creating a new one. + pub fn with_dir(dir: Rc, name: &str, lib: bool, args: I) -> Result + where + I: IntoIterator, + S: Into, + { let root = dir.path().join(name); + let proj = Self { + dir, + root, + config_file: None, + }; + + proj.new_inner(name, lib, args)?; - Ok(Self { dir, root }) + Ok(proj) + } + + /// Creates a new project that hasn't been initialized yet. This is useful for testing workflows + /// of `cargo component new` + pub fn new_uninitialized(dir: Rc, root: PathBuf) -> Self { + Self { + dir, + root, + config_file: None, + } } pub fn root(&self) -> &Path { @@ -290,8 +389,25 @@ impl Project { .join(format!("{name}.wasm")) } - pub fn cargo_component(&self, cmd: &str) -> Command { - let mut cmd = cargo_component(cmd); + pub fn cache_dir(&self) -> PathBuf { + self.dir.path().join("cache") + } + + pub fn config_file(&self) -> Option<&Path> { + self.config_file.as_deref() + } + + pub fn cargo_component(&self, args: I) -> Command + where + I: IntoIterator, + S: AsRef, + { + let mut cmd = cargo_component(args); + // Set the cache dir and the config file env var for every command + if let Some(config_file) = self.config_file() { + cmd.env(CONFIG_FILE_ENV_VAR, config_file); + } + cmd.env(CACHE_DIR_ENV_VAR, self.cache_dir()); cmd.current_dir(&self.root); cmd } diff --git a/tests/test.rs b/tests/test.rs index dfd63525..1a4002b6 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,14 +1,16 @@ -use crate::support::*; +use std::fs; + use anyhow::Result; use assert_cmd::prelude::*; use predicates::str::contains; -use std::fs; + +use crate::support::*; mod support; #[test] fn it_runs_test_with_command_component() -> Result<()> { - let project = Project::new_bin("foo-bar")?; + let project = Project::new("foo-bar", false)?; fs::create_dir_all(project.root().join(".cargo"))?; fs::write( @@ -70,7 +72,7 @@ pub fn test_random_component() { )?; project - .cargo_component("test") + .cargo_component(["test"]) .assert() .stdout(contains("test test_random_component ... ok")) .stdout(contains("test result: ok.")) @@ -81,7 +83,7 @@ pub fn test_random_component() { #[test] fn it_runs_test_with_reactor_component() -> Result<()> { - let project = Project::new("foo-bar")?; + let project = Project::new("foo-bar", true)?; fs::write( project.root().join("wit/world.wit"), @@ -120,7 +122,7 @@ pub fn test_random_component() { )?; project - .cargo_component("test") + .cargo_component(["test"]) .assert() .stdout(contains("test test_random_component ... ok")) .stdout(contains("test result: ok.")) diff --git a/tests/update.rs b/tests/update.rs index 4d7a95f1..e439009c 100644 --- a/tests/update.rs +++ b/tests/update.rs @@ -1,17 +1,19 @@ -use crate::support::*; +use std::fs; + use anyhow::{Context, Result}; use assert_cmd::prelude::*; use predicates::{prelude::PredicateBooleanExt, str::contains}; -use std::{fs, rc::Rc}; -use tempfile::TempDir; use toml_edit::value; +use wasm_pkg_client::warg::WargRegistryConfig; + +use crate::support::*; mod support; #[test] fn help() { for arg in ["help update", "update -h", "update --help"] { - cargo_component(arg) + cargo_component(arg.split_whitespace()) .assert() .stdout(contains( "Update dependencies as recorded in the component lock file", @@ -22,12 +24,13 @@ fn help() { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_without_changes_is_a_noop() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.0.0", r#"package test:bar@1.0.0; @@ -39,10 +42,9 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "component", "--target test:bar@1.0.0")?; - + let project = server.project("component", true, ["--target", "test:bar@1.0.0"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -51,7 +53,7 @@ world foo { validate_component(&project.debug_wasm("component"))?; project - .cargo_component("update") + .cargo_component(["update"]) .assert() .success() .stderr(contains("test:bar").not()); @@ -61,12 +63,13 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_without_compatible_changes_is_a_noop() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.0.0", r#"package test:bar@1.0.0; @@ -78,10 +81,9 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "component", "--target test:bar@1.0.0")?; - + let project = server.project("component", true, ["--target", "test:bar@1.0.0"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -90,7 +92,7 @@ world foo { validate_component(&project.debug_wasm("component"))?; publish_wit( - &config, + &warg_config.client_config, "test:bar", "2.0.0", r#"package test:bar@2.0.0; @@ -102,13 +104,13 @@ world foo { .await?; project - .cargo_component("update") + .cargo_component(["update"]) .assert() .success() .stderr(contains("test:bar").not()); project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -121,12 +123,13 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_compatible_changes() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.0.0", r#"package test:bar@1.0.0; @@ -138,10 +141,9 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "component", "--target test:bar@1.0.0")?; - + let project = server.project("component", true, ["--target", "test:bar@1.0.0"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -150,7 +152,7 @@ world foo { validate_component(&project.debug_wasm("component"))?; publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.1.0", r#"package test:bar@1.1.0; @@ -164,7 +166,7 @@ world foo { .await?; project - .cargo_component("update") + .cargo_component(["update"]) .assert() .success() .stderr(contains("`test:bar` v1.0.0 -> v1.1.0")); @@ -186,7 +188,7 @@ bindings::export!(Component with_types_in bindings); fs::write(project.root().join("src/lib.rs"), source)?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -199,12 +201,13 @@ bindings::export!(Component with_types_in bindings); #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_compatible_changes_is_noop_for_dryrun() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.0.0", r#"package test:bar@1.0.0; @@ -216,10 +219,9 @@ world foo { ) .await?; - let project = Project::with_dir(dir.clone(), "component", "--target test:bar@1.0.0")?; - + let project = server.project("component", true, ["--target", "test:bar@1.0.0"])?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -228,7 +230,7 @@ world foo { validate_component(&project.debug_wasm("component"))?; publish_wit( - &config, + &warg_config.client_config, "test:bar", "1.1.0", r#"package test:bar@1.1.0; @@ -242,7 +244,7 @@ world foo { .await?; project - .cargo_component("update --dry-run") + .cargo_component(["update", "--dry-run"]) .assert() .success() .stderr(contains( @@ -250,7 +252,7 @@ world foo { )); project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -264,17 +266,32 @@ world foo { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn update_with_changed_dependencies() -> Result<()> { - let dir = Rc::new(TempDir::new()?); - let (_server, config) = spawn_server(dir.path()).await?; - config.write_to_file(&dir.path().join("warg-config.json"))?; + let (server, config, registry) = spawn_server(Vec::::new()).await?; + + let warg_config = + WargRegistryConfig::try_from(config.registry_config(®istry).unwrap()).unwrap(); - publish_component(&config, "test:bar", "1.0.0", "(component)", true).await?; - publish_component(&config, "test:baz", "1.0.0", "(component)", true).await?; + publish_component( + &warg_config.client_config, + "test:bar", + "1.0.0", + "(component)", + true, + ) + .await?; + publish_component( + &warg_config.client_config, + "test:baz", + "1.0.0", + "(component)", + true, + ) + .await?; - let project = Project::with_dir(dir.clone(), "foo", "")?; + let project = server.project("foo", true, Vec::::new())?; project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -284,13 +301,13 @@ async fn update_with_changed_dependencies() -> Result<()> { validate_component(&project.debug_wasm("foo"))?; project - .cargo_component("add test:bar") + .cargo_component(["add", "test:bar"]) .assert() .stderr(contains("Added dependency `test:bar` with version `1.0.0`")) .success(); project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", @@ -307,7 +324,7 @@ async fn update_with_changed_dependencies() -> Result<()> { })?; project - .cargo_component("update") + .cargo_component(["update"]) .assert() .stderr( contains("Removing dependency `test:bar` v1.0.0") @@ -316,7 +333,7 @@ async fn update_with_changed_dependencies() -> Result<()> { .success(); project - .cargo_component("build") + .cargo_component(["build"]) .assert() .stderr(contains( "Finished `dev` profile [unoptimized + debuginfo] target(s)", diff --git a/tests/version.rs b/tests/version.rs index 8ec2c542..420b23fd 100644 --- a/tests/version.rs +++ b/tests/version.rs @@ -7,7 +7,7 @@ mod support; #[test] fn help() { for arg in ["-V", "--version"] { - cargo_component(arg) + cargo_component([arg]) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))) .success();