diff --git a/Cargo.lock b/Cargo.lock index aa04d37..8dc0cec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "aho-corasick" version = "1.1.4" @@ -26,15 +11,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "anstream" version = "1.0.0" @@ -91,82 +67,18 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "arc-swap" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" -dependencies = [ - "rustversion", -] - [[package]] name = "ascii" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" -[[package]] -name = "async-trait" -version = "0.1.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "aws-lc-rs" -version = "1.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" -dependencies = [ - "aws-lc-sys", - "untrusted 0.7.1", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "backtrace" -version = "0.3.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-link", -] - [[package]] name = "base64" version = "0.22.1" @@ -200,39 +112,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -[[package]] -name = "camino" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-platform" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" -dependencies = [ - "serde", - "serde_core", -] - -[[package]] -name = "cargo_metadata" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror 2.0.18", -] - [[package]] name = "cc" version = "1.2.61" @@ -240,8 +119,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" dependencies = [ "find-msvc-tools", - "jobserver", - "libc", "shlex", ] @@ -257,20 +134,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chrono" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" -dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - [[package]] name = "chunked_transfer" version = "1.5.0" @@ -305,10 +168,10 @@ version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -317,31 +180,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "console" version = "0.16.3" @@ -354,22 +198,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.17" @@ -379,17 +207,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cron" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5877d3fbf742507b66bc2a1945106bd30dd8504019d596901ddd012a4dd01740" -dependencies = [ - "chrono", - "once_cell", - "winnow 0.6.26", -] - [[package]] name = "crypto-common" version = "0.1.7" @@ -400,81 +217,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.117", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.117", -] - [[package]] name = "dialoguer" version = "0.12.0" @@ -527,21 +269,9 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -576,12 +306,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" @@ -597,27 +321,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.32" @@ -634,34 +337,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" -[[package]] -name = "futures-executor" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" -[[package]] -name = "futures-macro" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "futures-sink" version = "0.3.32" @@ -680,10 +361,8 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", "futures-io", - "futures-macro", "futures-sink", "futures-task", "memchr", @@ -741,26 +420,16 @@ dependencies = [ "wasip3", ] -[[package]] -name = "gimli" -version = "0.32.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" - [[package]] name = "git-sync" version = "0.1.0" dependencies = [ "anyhow", - "bytes", "clap", "console", "dialoguer", "directories", - "gitlab", "hmac", - "http", - "octocrab", "regex", "reqwest", "serde", @@ -768,96 +437,10 @@ dependencies = [ "sha2", "tempfile", "tiny_http", - "tokio", "toml", "url", ] -[[package]] -name = "gitlab" -version = "0.1811.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aa8d02b910ba60b3058293d84470cfcb664e4303d4ca9a587b0628bc8db8b32" -dependencies = [ - "async-trait", - "backtrace", - "base64", - "bytes", - "chrono", - "cron", - "derive_builder", - "futures-util", - "graphql_client", - "http", - "itertools", - "log", - "percent-encoding", - "reqwest", - "serde", - "serde_json", - "serde_urlencoded", - "thiserror 2.0.18", - "url", -] - -[[package]] -name = "graphql-introspection-query" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d" -dependencies = [ - "serde", -] - -[[package]] -name = "graphql-parser" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a818c0d883d7c0801df27be910917750932be279c7bc82dc541b8769425f409" -dependencies = [ - "combine", - "thiserror 1.0.69", -] - -[[package]] -name = "graphql_client" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50cfdc7f34b7f01909d55c2dcb71d4c13cbcbb4a1605d6c8bd760d654c1144b" -dependencies = [ - "graphql_query_derive", - "serde", - "serde_json", -] - -[[package]] -name = "graphql_client_codegen" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e27ed0c2cf0c0cc52c6bcf3b45c907f433015e580879d14005386251842fb0a" -dependencies = [ - "graphql-introspection-query", - "graphql-parser", - "heck 0.4.1", - "lazy_static", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 1.0.109", -] - -[[package]] -name = "graphql_query_derive" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83febfa838f898cfa73dfaa7a8eb69ff3409021ac06ee94cfb3d622f6eeb1a97" -dependencies = [ - "graphql_client_codegen", - "proc-macro2", - "syn 1.0.109", -] - [[package]] name = "hashbrown" version = "0.15.5" @@ -873,12 +456,6 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -968,25 +545,11 @@ dependencies = [ "http", "hyper", "hyper-util", - "log", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" -dependencies = [ - "hyper", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", + "webpki-roots", ] [[package]] @@ -1012,30 +575,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "iana-time-zone" -version = "0.1.65" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "icu_collections" version = "2.2.0" @@ -1124,12 +663,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "1.1.0" @@ -1185,80 +718,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys", - "log", - "simd_cesu8", - "thiserror 2.0.18", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn 2.0.117", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn 2.0.117", -] - -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] - [[package]] name = "js-sys" version = "0.3.97" @@ -1271,29 +736,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "10.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" -dependencies = [ - "aws-lc-rs", - "base64", - "getrandom 0.2.17", - "js-sys", - "pem", - "serde", - "serde_json", - "signature", - "simple_asn1", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - [[package]] name = "leb128fmt" version = "0.1.0" @@ -1345,15 +787,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] - [[package]] name = "mio" version = "1.2.0" @@ -1365,90 +798,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "object" -version = "0.37.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" -dependencies = [ - "memchr", -] - -[[package]] -name = "octocrab" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce7ace5d83b077dd50ff01214a81feea17e258b8f677590c2286add76dc8238e" -dependencies = [ - "arc-swap", - "async-trait", - "base64", - "bytes", - "cargo_metadata", - "cfg-if", - "chrono", - "futures", - "futures-util", - "getrandom 0.2.17", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-timeout", - "hyper-util", - "jsonwebtoken", - "once_cell", - "percent-encoding", - "pin-project", - "secrecy", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "snafu", - "tokio", - "tower", - "tower-http", - "tracing", - "url", - "web-time", -] - [[package]] name = "once_cell" version = "1.21.4" @@ -1461,54 +810,18 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl-probe" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" - [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "pem" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" -dependencies = [ - "base64", - "serde_core", -] - [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "pin-project" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf0d9e68100b3a7989b4901972f265cd542e560a3a8a724e1e20322f4d06ce9" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a990e22f43e84855daf260dded30524ef4a9021cc7541c26540500a50b624389" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "pin-project-lite" version = "0.2.17" @@ -1524,12 +837,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1546,7 +853,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.117", + "syn", ] [[package]] @@ -1584,7 +891,6 @@ version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ - "aws-lc-rs", "bytes", "getrandom 0.3.4", "lru-slab", @@ -1642,7 +948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha", - "rand_core 0.9.5", + "rand_core", ] [[package]] @@ -1652,16 +958,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.5", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.17", + "rand_core", ] [[package]] @@ -1715,9 +1012,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.3" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -1737,9 +1034,9 @@ dependencies = [ "quinn", "rustls", "rustls-pki-types", - "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", @@ -1750,6 +1047,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", ] [[package]] @@ -1762,31 +1060,16 @@ dependencies = [ "cfg-if", "getrandom 0.2.17", "libc", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" - [[package]] name = "rustc-hash" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1806,27 +1089,14 @@ version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ - "aws-lc-rs", - "log", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" -dependencies = [ - "openssl-probe", - "rustls-pki-types", - "schannel", - "security-framework", -] - [[package]] name = "rustls-pki-types" version = "1.14.1" @@ -1837,43 +1107,15 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-platform-verifier" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - [[package]] name = "rustls-webpki" version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -1888,65 +1130,11 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "secrecy" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" -dependencies = [ - "zeroize", -] - -[[package]] -name = "security-framework" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" -dependencies = [ - "serde", - "serde_core", -] [[package]] name = "serde" @@ -1975,7 +1163,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -1991,17 +1179,6 @@ dependencies = [ "zmij", ] -[[package]] -name = "serde_path_to_error" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" -dependencies = [ - "itoa", - "serde", - "serde_core", -] - [[package]] name = "serde_spanned" version = "0.6.9" @@ -2046,43 +1223,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "simd_cesu8" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "simple_asn1" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.18", - "time", -] - [[package]] name = "slab" version = "0.4.12" @@ -2095,27 +1235,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "snafu" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" -dependencies = [ - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "socket2" version = "0.6.3" @@ -2144,17 +1263,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.117" @@ -2183,7 +1291,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2225,7 +1333,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -2236,38 +1344,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", -] - -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" -dependencies = [ - "num-conv", - "time-core", + "syn", ] [[package]] @@ -2309,9 +1386,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.2" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -2331,19 +1408,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-util" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - [[package]] name = "toml" version = "0.8.23" @@ -2376,7 +1440,7 @@ dependencies = [ "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.15", + "winnow", ] [[package]] @@ -2396,10 +1460,8 @@ dependencies = [ "pin-project-lite", "sync_wrapper", "tokio", - "tokio-util", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -2418,7 +1480,6 @@ dependencies = [ "tower", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -2439,23 +1500,10 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "log", "pin-project-lite", - "tracing-attributes", "tracing-core", ] -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "tracing-core" version = "0.1.36" @@ -2495,12 +1543,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -2517,7 +1559,6 @@ dependencies = [ "idna", "percent-encoding", "serde", - "serde_derive", ] [[package]] @@ -2538,16 +1579,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -2623,7 +1654,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wasm-bindgen-shared", ] @@ -2687,87 +1718,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", - "serde", "wasm-bindgen", ] [[package]] -name = "webpki-root-certs" +name = "webpki-roots" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "windows-core" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-result" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" -dependencies = [ - "windows-link", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2990,15 +1958,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winnow" -version = "0.6.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.7.15" @@ -3030,7 +1989,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "wit-parser", ] @@ -3041,10 +2000,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", - "heck 0.5.0", + "heck", "indexmap", "prettyplease", - "syn 2.0.117", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -3060,7 +2019,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.117", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -3127,7 +2086,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -3148,7 +2107,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] @@ -3168,7 +2127,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", "synstructure", ] @@ -3208,7 +2167,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 7b70cfc..be2992e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,22 +5,17 @@ edition = "2024" [dependencies] anyhow = "1.0" -bytes = "1.11.1" clap = { version = "4.5", features = ["derive"] } console = "0.16" dialoguer = "0.12" directories = "5.0" -gitlab = "0.1811.0" hmac = "0.12" -http = "1.4.0" -octocrab = { version = "0.50.0", default-features = false, features = ["default-client", "follow-redirect", "jwt-aws-lc-rs", "retry", "rustls", "rustls-aws-lc-rs", "timeout", "tracing"] } +reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] } regex = "1.11" -reqwest = { version = "0.13", default-features = false, features = ["blocking", "json", "rustls"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" sha2 = "0.10" tempfile = "3.13" tiny_http = "0.12" -tokio = { version = "1.52.2", features = ["rt-multi-thread", "time"] } toml = "0.8" url = "2.5" diff --git a/src/provider.rs b/src/provider.rs index 3642952..3077b4c 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -1,16 +1,10 @@ use std::collections::HashMap; -use std::error::Error; -use std::fmt; use anyhow::{Context, Result, anyhow, bail}; -use bytes::Bytes; -use gitlab::api::{self, Pagination, Query}; -use octocrab::{Octocrab, Page}; use reqwest::blocking::{Client, Response}; use reqwest::header::{ACCEPT, AUTHORIZATION, HeaderMap, HeaderValue, USER_AGENT}; -use serde::{Deserialize, de::DeserializeOwned}; +use serde::Deserialize; use serde_json::json; -use tokio::runtime::Runtime; use url::Url; use crate::config::{EndpointConfig, NamespaceKind, ProviderKind, SiteConfig, Visibility}; @@ -33,82 +27,25 @@ pub struct ProviderClient<'a> { site: &'a SiteConfig, token: String, http: Client, - runtime: Runtime, - github: Option, - gitlab: Option, -} - -macro_rules! dispatch_provider { - ($provider:expr, github => $github:expr, gitlab => $gitlab:expr, gitea_like => $gitea:expr $(,)?) => { - match $provider { - ProviderKind::Github => $github, - ProviderKind::Gitlab => $gitlab, - ProviderKind::Gitea | ProviderKind::Forgejo => $gitea, - } - }; -} - -macro_rules! json_method { - ($name:ident, $method:ident, $verb:literal) => { - fn $name(&self, url: &str, body: &serde_json::Value) -> Result - where - T: for<'de> Deserialize<'de>, - { - self.request_headers(self.http.$method(url))? - .json(body) - .send() - .with_context(|| format!("{} {} failed", $verb, url)) - .and_then(|response| check_response($verb, url, response))? - .json() - .with_context(|| format!("invalid JSON from {url}")) - } - }; } impl<'a> ProviderClient<'a> { pub fn new(site: &'a SiteConfig) -> Result { let token = site.token()?; - let http = Client::builder().build()?; - let runtime = Runtime::new().context("failed to create async API runtime")?; - let github = if matches!(site.provider, ProviderKind::Github) { - let _runtime_context = runtime.enter(); - Some( - Octocrab::builder() - .personal_token(token.clone()) - .base_uri(site.api_base()) - .context("invalid GitHub API base URL")? - .build() - .context("failed to create GitHub API client")?, - ) - } else { - None - }; - let gitlab = if matches!(site.provider, ProviderKind::Gitlab) { - Some(GitlabApiClient::new( - site.api_base(), - token.clone(), - http.clone(), - )?) - } else { - None - }; Ok(Self { site, token, - http, - runtime, - github, - gitlab, + http: Client::builder().build()?, }) } pub fn list_repos(&self, endpoint: &EndpointConfig) -> Result> { - dispatch_provider!( - self.site.provider, - github => self.github_list_repos(endpoint), - gitlab => self.gitlab_list_repos(endpoint), - gitea_like => self.gitea_list_repos(endpoint), - ) + match self.site.provider { + ProviderKind::Github => self.github_list_repos(endpoint), + ProviderKind::Gitlab => self.gitlab_list_repos(endpoint), + ProviderKind::Gitea => self.gitea_list_repos(endpoint), + ProviderKind::Forgejo => self.gitea_list_repos(endpoint), + } } pub fn create_repo( @@ -118,12 +55,18 @@ impl<'a> ProviderClient<'a> { visibility: &Visibility, description: Option<&str>, ) -> Result { - dispatch_provider!( - self.site.provider, - github => self.github_create_repo(endpoint, name, visibility, description), - gitlab => self.gitlab_create_repo(endpoint, name, visibility, description), - gitea_like => self.gitea_create_repo(endpoint, name, visibility, description), - ) + match self.site.provider { + ProviderKind::Github => { + self.github_create_repo(endpoint, name, visibility, description) + } + ProviderKind::Gitlab => { + self.gitlab_create_repo(endpoint, name, visibility, description) + } + ProviderKind::Gitea => self.gitea_create_repo(endpoint, name, visibility, description), + ProviderKind::Forgejo => { + self.gitea_create_repo(endpoint, name, visibility, description) + } + } } pub fn install_webhook( @@ -133,12 +76,13 @@ impl<'a> ProviderClient<'a> { url: &str, secret: &str, ) -> Result<()> { - dispatch_provider!( - self.site.provider, - github => self.github_install_webhook(endpoint, repo, url, secret), - gitlab => self.gitlab_install_webhook(endpoint, repo, url, secret), - gitea_like => self.gitea_install_webhook(endpoint, repo, url, secret), - ) + match self.site.provider { + ProviderKind::Github => self.github_install_webhook(endpoint, repo, url, secret), + ProviderKind::Gitlab => self.gitlab_install_webhook(endpoint, repo, url, secret), + ProviderKind::Gitea | ProviderKind::Forgejo => { + self.gitea_install_webhook(endpoint, repo, url, secret) + } + } } pub fn uninstall_webhook( @@ -147,36 +91,27 @@ impl<'a> ProviderClient<'a> { repo_name: &str, url: &str, ) -> Result { - dispatch_provider!( - self.site.provider, - github => self.github_uninstall_webhook(endpoint, repo_name, url), - gitlab => self.gitlab_uninstall_webhook(endpoint, repo_name, url), - gitea_like => self.gitea_uninstall_webhook(endpoint, repo_name, url), - ) + match self.site.provider { + ProviderKind::Github => self.github_uninstall_webhook(endpoint, repo_name, url), + ProviderKind::Gitlab => self.gitlab_uninstall_webhook(endpoint, repo_name, url), + ProviderKind::Gitea | ProviderKind::Forgejo => { + self.gitea_uninstall_webhook(endpoint, repo_name, url) + } + } } pub fn validate_token(&self) -> Result<()> { - dispatch_provider!( - self.site.provider, - github => self.github_get_json::("/user").map(|_| ()), - gitlab => self.gitlab_query::( - gitlab::api::users::CurrentUser::builder().build()?, - ) - .map(|_| ()), - gitea_like => { - let url = format!("{}/user", self.site.api_base()); - self.get(&url).map(|_| ()) - }, - ) + let url = format!("{}/user", self.site.api_base()); + self.get(&url).map(|_| ()) } pub fn detect_namespace_kind(&self, namespace: &str) -> Result> { - dispatch_provider!( - self.site.provider, - github => self.github_detect_namespace_kind(namespace), - gitlab => self.gitlab_detect_namespace_kind(namespace), - gitea_like => self.gitea_detect_namespace_kind(namespace), - ) + match self.site.provider { + ProviderKind::Github => self.github_detect_namespace_kind(namespace), + ProviderKind::Gitlab => self.gitlab_detect_namespace_kind(namespace), + ProviderKind::Gitea => self.gitea_detect_namespace_kind(namespace), + ProviderKind::Forgejo => self.gitea_detect_namespace_kind(namespace), + } } pub fn authenticated_clone_url(&self, clone_url: &str) -> Result { @@ -204,134 +139,15 @@ impl<'a> ProviderClient<'a> { Ok(url.to_string()) } - fn github(&self) -> Result<&Octocrab> { - self.github - .as_ref() - .ok_or_else(|| anyhow!("GitHub API client is not configured")) - } - - fn github_paged(&self, route: &str) -> Result> - where - T: DeserializeOwned + Send + 'static, - { - let github = self.github()?; - let page = self - .runtime - .block_on(github.get::, _, _>(route, None::<&()>)) - .with_context(|| format!("GitHub GET {route} failed"))?; - self.runtime - .block_on(github.all_pages(page)) - .with_context(|| format!("GitHub pagination for {route} failed")) - } - - fn github_get_json(&self, route: &str) -> Result - where - T: DeserializeOwned + Send + 'static, - { - self.runtime - .block_on(self.github()?.get(route, None::<&()>)) - .with_context(|| format!("GitHub GET {route} failed")) - } - - fn github_post(&self, route: &str, body: &serde_json::Value) -> Result - where - T: DeserializeOwned + Send + 'static, - { - self.runtime - .block_on(self.github()?.post(route, Some(body))) - .with_context(|| format!("GitHub POST {route} failed")) - } - - fn github_patch(&self, route: &str, body: &serde_json::Value) -> Result - where - T: DeserializeOwned + Send + 'static, - { - self.runtime - .block_on(self.github()?.patch(route, Some(body))) - .with_context(|| format!("GitHub PATCH {route} failed")) - } - - fn github_delete(&self, route: &str) -> Result<()> { - let github = self.github()?; - self.runtime.block_on(async { - let response = github._delete(route, None::<&()>).await?; - if response.status().is_success() { - Ok(()) - } else { - let status = response.status(); - let body = github.body_to_string(response).await.unwrap_or_default(); - bail!("GitHub DELETE {route} returned {status}: {body}") - } - }) - } - - fn github_find_existing_hook( - &self, - hooks_route: &str, - target_url: &str, - ) -> Result> { - let hooks: Vec = self.github_paged(hooks_route)?; - Ok(hooks - .into_iter() - .find(|hook| hook.url() == Some(target_url))) - } - - fn gitlab(&self) -> Result<&GitlabApiClient> { - self.gitlab - .as_ref() - .ok_or_else(|| anyhow!("GitLab API client is not configured")) - } - - fn gitlab_query(&self, endpoint: E) -> Result - where - T: DeserializeOwned, - E: api::Endpoint, - { - endpoint - .query(self.gitlab()?) - .map_err(|error| anyhow!("GitLab API request failed: {error}")) - } - - fn gitlab_paged(&self, endpoint: E) -> Result> - where - T: DeserializeOwned + 'static, - E: api::Endpoint + api::Pageable, - { - api::paged(endpoint, Pagination::All) - .query(self.gitlab()?) - .map_err(|error| anyhow!("GitLab paged API request failed: {error}")) - } - - fn gitlab_ignore(&self, endpoint: E) -> Result<()> - where - E: api::Endpoint, - { - api::ignore(endpoint) - .query(self.gitlab()?) - .map_err(|error| anyhow!("GitLab API request failed: {error}")) - } - - fn gitlab_find_existing_hook( - &self, - project: &str, - target_url: &str, - ) -> Result> { - let endpoint = gitlab::api::projects::hooks::Hooks::builder() - .project(project) - .build()?; - let hooks: Vec = self.gitlab_paged(endpoint)?; - Ok(hooks - .into_iter() - .find(|hook| hook.url() == Some(target_url))) - } - fn github_list_repos(&self, endpoint: &EndpointConfig) -> Result> { match endpoint.kind { NamespaceKind::User => { + let url = format!( + "{}/user/repos?affiliation=owner&visibility=all&per_page=100", + self.site.api_base() + ); let repos: Vec = self - .github_paged::( - "/user/repos?affiliation=owner&visibility=all&per_page=100", - )? + .paged_get(&url)? .into_iter() .filter(|repo: &GithubRepo| { repo.owner.login.eq_ignore_ascii_case(&endpoint.namespace) @@ -340,8 +156,12 @@ impl<'a> ProviderClient<'a> { Ok(repos.into_iter().map(Into::into).collect()) } NamespaceKind::Org => { - let route = format!("/orgs/{}/repos?type=all&per_page=100", endpoint.namespace); - let repos: Vec = self.github_paged(&route)?; + let url = format!( + "{}/orgs/{}/repos?type=all&per_page=100", + self.site.api_base(), + endpoint.namespace + ); + let repos: Vec = self.paged_get(&url)?; Ok(repos.into_iter().map(Into::into).collect()) } NamespaceKind::Group => bail!("GitHub endpoints use kind 'user' or 'org'"), @@ -355,9 +175,11 @@ impl<'a> ProviderClient<'a> { visibility: &Visibility, description: Option<&str>, ) -> Result { - let route = match endpoint.kind { - NamespaceKind::User => "/user/repos".to_string(), - NamespaceKind::Org => format!("/orgs/{}/repos", endpoint.namespace), + let url = match endpoint.kind { + NamespaceKind::User => format!("{}/user/repos", self.site.api_base()), + NamespaceKind::Org => { + format!("{}/orgs/{}/repos", self.site.api_base(), endpoint.namespace) + } NamespaceKind::Group => bail!("GitHub endpoints use kind 'user' or 'org'"), }; let body = json!({ @@ -365,12 +187,12 @@ impl<'a> ProviderClient<'a> { "private": matches!(visibility, Visibility::Private), "description": description.unwrap_or(""), }); - self.github_post::(&route, &body) - .map(Into::into) + self.post_json::(&url, &body).map(Into::into) } fn github_detect_namespace_kind(&self, namespace: &str) -> Result> { - let value: serde_json::Value = self.github_get_json(&format!("/users/{namespace}"))?; + let url = format!("{}/users/{namespace}", self.site.api_base()); + let value: serde_json::Value = self.get_json(&url)?; Ok(match value.get("type").and_then(|value| value.as_str()) { Some("Organization") => Some(NamespaceKind::Org), Some("User") => Some(NamespaceKind::User), @@ -388,7 +210,12 @@ impl<'a> ProviderClient<'a> { if matches!(endpoint.kind, NamespaceKind::Group) { bail!("GitHub endpoints use kind 'user' or 'org'"); } - let hooks_route = format!("/repos/{}/{}/hooks", endpoint.namespace, repo.name); + let hooks_url = format!( + "{}/repos/{}/{}/hooks", + self.site.api_base(), + endpoint.namespace, + repo.name + ); let body = json!({ "name": "web", "active": true, @@ -400,11 +227,11 @@ impl<'a> ProviderClient<'a> { "insecure_ssl": "0", }, }); - if let Some(hook) = self.github_find_existing_hook(&hooks_route, url)? { - let update_route = format!("{hooks_route}/{}", hook.id); - self.github_patch::(&update_route, &body)?; + if let Some(hook) = self.find_existing_hook(&hooks_url, url)? { + let update_url = format!("{hooks_url}/{}", hook.id); + self.patch_json::(&update_url, &body)?; } else { - self.github_post::(&hooks_route, &body)?; + self.post_json::(&hooks_url, &body)?; } Ok(()) } @@ -418,32 +245,34 @@ impl<'a> ProviderClient<'a> { if matches!(endpoint.kind, NamespaceKind::Group) { bail!("GitHub endpoints use kind 'user' or 'org'"); } - let hooks_route = format!("/repos/{}/{}/hooks", endpoint.namespace, repo_name); - let Some(hook) = self.github_find_existing_hook(&hooks_route, url)? else { - return Ok(false); - }; - self.github_delete(&format!("{hooks_route}/{}", hook.id))?; - Ok(true) + let hooks_url = format!( + "{}/repos/{}/{}/hooks", + self.site.api_base(), + endpoint.namespace, + repo_name + ); + self.delete_matching_hook(&hooks_url, url) } fn gitlab_list_repos(&self, endpoint: &EndpointConfig) -> Result> { match endpoint.kind { NamespaceKind::User => { - let endpoint = gitlab::api::users::UserProjects::builder() - .user(endpoint.namespace.as_str()) - .simple(true) - .owned(true) - .build()?; - let repos: Vec = self.gitlab_paged(endpoint)?; + let url = format!( + "{}/users/{}/projects?simple=true&per_page=100&owned=true", + self.site.api_base(), + endpoint.namespace + ); + let repos: Vec = self.paged_get(&url)?; Ok(repos.into_iter().map(Into::into).collect()) } NamespaceKind::Org | NamespaceKind::Group => { - let endpoint = gitlab::api::groups::projects::GroupProjects::builder() - .group(endpoint.namespace.as_str()) - .simple(true) - .include_subgroups(false) - .build()?; - let repos: Vec = self.gitlab_paged(endpoint)?; + let encoded = urlencoding(&endpoint.namespace); + let url = format!( + "{}/groups/{}/projects?simple=true&include_subgroups=false&per_page=100", + self.site.api_base(), + encoded + ); + let repos: Vec = self.paged_get(&url)?; Ok(repos.into_iter().map(Into::into).collect()) } } @@ -456,42 +285,51 @@ impl<'a> ProviderClient<'a> { visibility: &Visibility, description: Option<&str>, ) -> Result { - let mut builder = gitlab::api::projects::CreateProject::builder(); - builder - .name(name) - .path(name) - .visibility(gitlab_visibility(visibility)) - .description(description.unwrap_or("")); + let mut body = serde_json::Map::from_iter([ + ("name".to_string(), json!(name)), + ("path".to_string(), json!(name)), + ( + "visibility".to_string(), + json!(match visibility { + Visibility::Private => "private", + Visibility::Public => "public", + }), + ), + ("description".to_string(), json!(description.unwrap_or(""))), + ]); + if matches!(endpoint.kind, NamespaceKind::Org | NamespaceKind::Group) { let group = self.gitlab_group(&endpoint.namespace)?; - builder.namespace_id(group.id); + body.insert("namespace_id".to_string(), json!(group.id)); } - self.gitlab_query::(builder.build()?) + + let url = format!("{}/projects", self.site.api_base()); + self.post_json::(&url, &serde_json::Value::Object(body)) .map(Into::into) } fn gitlab_group(&self, namespace: &str) -> Result { - self.gitlab_query( - gitlab::api::groups::Group::builder() - .group(namespace) - .build()?, - ) + let url = format!("{}/groups/{}", self.site.api_base(), urlencoding(namespace)); + self.get_json(&url) } fn gitlab_detect_namespace_kind(&self, namespace: &str) -> Result> { - let group = gitlab::api::groups::Group::builder() - .group(namespace) - .build()?; - if self.gitlab_query::(group).is_ok() { + let group_url = format!("{}/groups/{}", self.site.api_base(), urlencoding(namespace)); + if self.get(&group_url).is_ok() { return Ok(Some(NamespaceKind::Group)); } let username = namespace.rsplit('/').next().unwrap_or(namespace); - let users = gitlab::api::users::Users::builder() - .username(username) - .build()?; - let users: Vec = self.gitlab_query(users)?; - Ok((!users.is_empty()).then_some(NamespaceKind::User)) + let user_url = format!( + "{}/users?username={}", + self.site.api_base(), + urlencoding(username) + ); + let users: serde_json::Value = self.get_json(&user_url)?; + Ok(users + .as_array() + .is_some_and(|items| !items.is_empty()) + .then_some(NamespaceKind::User)) } fn gitlab_install_webhook( @@ -502,27 +340,23 @@ impl<'a> ProviderClient<'a> { secret: &str, ) -> Result<()> { let project = format!("{}/{}", endpoint.namespace, repo.name); - if let Some(hook) = self.gitlab_find_existing_hook(&project, url)? { - let endpoint = gitlab::api::projects::hooks::EditHook::builder() - .project(project) - .hook_id(hook.id) - .url(url) - .push_events(true) - .tag_push_events(true) - .token(secret) - .enable_ssl_verification(true) - .build()?; - self.gitlab_ignore(endpoint)?; + let hooks_url = format!( + "{}/projects/{}/hooks", + self.site.api_base(), + urlencoding(&project) + ); + let body = json!({ + "url": url, + "push_events": true, + "tag_push_events": true, + "token": secret, + "enable_ssl_verification": true, + }); + if let Some(hook) = self.find_existing_hook(&hooks_url, url)? { + let update_url = format!("{hooks_url}/{}", hook.id); + self.put_json::(&update_url, &body)?; } else { - let endpoint = gitlab::api::projects::hooks::CreateHook::builder() - .project(project) - .url(url) - .push_events(true) - .tag_push_events(true) - .token(secret) - .enable_ssl_verification(true) - .build()?; - self.gitlab_ignore(endpoint)?; + self.post_json::(&hooks_url, &body)?; } Ok(()) } @@ -534,15 +368,12 @@ impl<'a> ProviderClient<'a> { url: &str, ) -> Result { let project = format!("{}/{}", endpoint.namespace, repo_name); - let Some(hook) = self.gitlab_find_existing_hook(&project, url)? else { - return Ok(false); - }; - let endpoint = gitlab::api::projects::hooks::DeleteHook::builder() - .project(project) - .hook_id(hook.id) - .build()?; - self.gitlab_ignore(endpoint)?; - Ok(true) + let hooks_url = format!( + "{}/projects/{}/hooks", + self.site.api_base(), + urlencoding(&project) + ); + self.delete_matching_hook(&hooks_url, url) } fn gitea_list_repos(&self, endpoint: &EndpointConfig) -> Result> { @@ -696,8 +527,53 @@ impl<'a> ProviderClient<'a> { Ok(output) } - json_method!(post_json, post, "POST"); - json_method!(patch_json, patch, "PATCH"); + fn get_json(&self, url: &str) -> Result + where + T: for<'de> Deserialize<'de>, + { + self.get(url)? + .json() + .with_context(|| format!("invalid JSON from {url}")) + } + + fn post_json(&self, url: &str, body: &serde_json::Value) -> Result + where + T: for<'de> Deserialize<'de>, + { + self.request_headers(self.http.post(url))? + .json(body) + .send() + .with_context(|| format!("POST {url} failed")) + .and_then(|response| check_response("POST", url, response))? + .json() + .with_context(|| format!("invalid JSON from {url}")) + } + + fn put_json(&self, url: &str, body: &serde_json::Value) -> Result + where + T: for<'de> Deserialize<'de>, + { + self.request_headers(self.http.put(url))? + .json(body) + .send() + .with_context(|| format!("PUT {url} failed")) + .and_then(|response| check_response("PUT", url, response))? + .json() + .with_context(|| format!("invalid JSON from {url}")) + } + + fn patch_json(&self, url: &str, body: &serde_json::Value) -> Result + where + T: for<'de> Deserialize<'de>, + { + self.request_headers(self.http.patch(url))? + .json(body) + .send() + .with_context(|| format!("PATCH {url} failed")) + .and_then(|response| check_response("PATCH", url, response))? + .json() + .with_context(|| format!("invalid JSON from {url}")) + } fn get(&self, url: &str) -> Result { self.request_headers(self.http.get(url))? @@ -760,111 +636,6 @@ fn check_response(method: &str, url: &str, response: Response) -> Result Result { - let rest_url = Url::parse(&format!("{}/", api_base.trim_end_matches('/'))) - .context("invalid GitLab API base URL")?; - Ok(Self { - rest_url, - token, - http, - }) - } -} - -impl api::RestClient for GitlabApiClient { - type Error = GitlabClientError; - - fn rest_endpoint( - &self, - endpoint: &str, - ) -> std::result::Result> { - Ok(self.rest_url.join(endpoint)?) - } -} - -impl api::Client for GitlabApiClient { - fn rest( - &self, - request: http::request::Builder, - body: Vec, - ) -> std::result::Result, api::ApiError> { - self.rest_request(request, body) - .map_err(api::ApiError::client) - } -} - -impl GitlabApiClient { - fn rest_request( - &self, - request: http::request::Builder, - body: Vec, - ) -> std::result::Result, GitlabClientError> { - let request = request - .header( - "PRIVATE-TOKEN", - HeaderValue::from_str(&self.token) - .map_err(GitlabClientError::InvalidHeaderValue)?, - ) - .body(body) - .map_err(GitlabClientError::Http)?; - let (parts, body) = request.into_parts(); - let method = reqwest::Method::from_bytes(parts.method.as_str().as_bytes()) - .map_err(GitlabClientError::InvalidMethod)?; - let mut builder = self.http.request(method, parts.uri.to_string()); - for (name, value) in &parts.headers { - builder = builder.header(name.as_str(), value.as_bytes()); - } - let response = builder - .body(body) - .send() - .map_err(GitlabClientError::Reqwest)?; - let mut output = http::Response::builder().status(response.status()); - for (name, value) in response.headers() { - output = output.header(name.as_str(), value.as_bytes()); - } - output - .body(response.bytes().map_err(GitlabClientError::Reqwest)?) - .map_err(GitlabClientError::Http) - } -} - -#[derive(Debug)] -enum GitlabClientError { - Reqwest(reqwest::Error), - Http(http::Error), - InvalidHeaderValue(reqwest::header::InvalidHeaderValue), - InvalidMethod(http::method::InvalidMethod), -} - -impl fmt::Display for GitlabClientError { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Reqwest(error) => write!(formatter, "communication with GitLab: {error}"), - Self::Http(error) => write!(formatter, "HTTP request error: {error}"), - Self::InvalidHeaderValue(error) => { - write!(formatter, "invalid GitLab token header: {error}") - } - Self::InvalidMethod(error) => write!(formatter, "invalid GitLab HTTP method: {error}"), - } - } -} - -impl Error for GitlabClientError {} - -fn gitlab_visibility(visibility: &Visibility) -> gitlab::api::common::VisibilityLevel { - match visibility { - Visibility::Private => gitlab::api::common::VisibilityLevel::Private, - Visibility::Public => gitlab::api::common::VisibilityLevel::Public, - } -} - fn next_link(headers: &HeaderMap) -> Option { let header = headers.get("link")?.to_str().ok()?; for part in header.split(',') { @@ -881,6 +652,10 @@ fn next_link(headers: &HeaderMap) -> Option { None } +fn urlencoding(value: &str) -> String { + url::form_urlencoded::byte_serialize(value.as_bytes()).collect() +} + #[derive(Deserialize)] struct GithubRepo { name: String, @@ -1042,6 +817,11 @@ mod tests { ); } + #[test] + fn group_paths_are_url_encoded_for_gitlab() { + assert_eq!(urlencoding("parent/child group"), "parent%2Fchild+group"); + } + #[test] fn validate_token_checks_user_endpoint_with_provider_auth_header() { let (api_url, handle) = one_request_server("200 OK", "{}", |request| { @@ -1068,7 +848,7 @@ mod tests { #[test] fn validate_token_reports_provider_rejection() { let (api_url, handle) = one_request_server("401 Unauthorized", "bad token", |request| { - assert!(request.starts_with("GET /user"), "request was {request}"); + assert!(request.starts_with("GET /user "), "request was {request}"); assert!( request .to_ascii_lowercase() @@ -1086,7 +866,7 @@ mod tests { .validate_token() .unwrap_err() .to_string(); - assert!(err.contains("401") || err.contains("Unauthorized")); + assert!(err.contains("401 Unauthorized")); handle.join().unwrap(); }