diff --git a/Cargo.lock b/Cargo.lock index 92f3b7c653..a74867d89d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,6 +193,30 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "async-compression" +version = "0.4.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" +dependencies = [ + "compression-codecs", + "compression-core", + "futures-core", + "pin-project-lite", + "tokio", +] + +[[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", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -483,6 +507,23 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "compression-codecs" +version = "0.4.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" +dependencies = [ + "compression-core", + "zstd", + "zstd-safe", +] + +[[package]] +name = "compression-core" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d" + [[package]] name = "console" version = "0.15.11" @@ -524,6 +565,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -563,6 +614,21 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -630,7 +696,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "socket2", + "socket2 0.6.0", "windows-sys 0.59.0", ] @@ -823,6 +889,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -897,6 +975,21 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1180,6 +1273,52 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.2", + "ring", + "thiserror 2.0.17", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.2", + "resolv-conf", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1291,6 +1430,39 @@ dependencies = [ "pin-utils", "smallvec", "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", ] [[package]] @@ -1299,13 +1471,24 @@ version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" dependencies = [ + "base64 0.22.1", "bytes", + "futures-channel", "futures-core", + "futures-util", "http", "http-body", "hyper", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", + "socket2 0.6.0", + "system-configuration", "tokio", + "tower-service", + "tracing", + "windows-registry", ] [[package]] @@ -1491,6 +1674,12 @@ dependencies = [ "regex", ] +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" + [[package]] name = "inout" version = "0.1.4" @@ -1534,6 +1723,34 @@ dependencies = [ "libc", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.10", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is-terminal" version = "0.4.16" @@ -1748,6 +1965,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" +[[package]] +name = "mediatype" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120fa187be19d9962f0926633453784691731018a2bf936ddb4e29101b79c4a7" + [[package]] name = "memchr" version = "2.7.6" @@ -1763,6 +1986,12 @@ dependencies = [ "libc", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1813,6 +2042,41 @@ dependencies = [ "tokio", ] +[[package]] +name = "moka" +version = "0.12.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "rustc_version", + "smallvec", + "tagptr", + "uuid", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1878,11 +2142,48 @@ dependencies = [ "memchr", ] +[[package]] +name = "objectstore-client" +version = "0.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "260ccf94ed55dc83c0a5b470a4d9404d9f15e4b975d6c6e734e89296eef75b59" +dependencies = [ + "async-compression", + "bytes", + "futures-util", + "infer", + "objectstore-types", + "reqwest", + "sentry-core", + "serde", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "url", +] + +[[package]] +name = "objectstore-types" +version = "0.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da8b79e6156554da409ff350f06dea1b5ea0b1f863ca753fe9222a74e917592b" +dependencies = [ + "http", + "humantime", + "mediatype", + "serde", + "thiserror 2.0.17", +] + [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] [[package]] name = "once_cell_polyfill" @@ -1900,6 +2201,32 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "openssl" +version = "0.10.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "openssl-probe" version = "0.1.6" @@ -1917,9 +2244,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -2164,6 +2491,12 @@ dependencies = [ "time", ] +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "potential_utf" version = "0.1.3" @@ -2428,6 +2761,71 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "reqwest" +version = "0.12.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "hickory-resolver", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rstest" version = "0.18.2" @@ -2526,6 +2924,39 @@ dependencies = [ "windows-sys 0.61.1", ] +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -2621,6 +3052,19 @@ dependencies = [ "zeroize", ] +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + [[package]] name = "security-framework-sys" version = "2.15.0" @@ -2708,6 +3152,7 @@ dependencies = [ "mac-process-info", "magic_string", "mockito", + "objectstore-client", "open", "openssl-probe", "parking_lot", @@ -2728,10 +3173,12 @@ dependencies = [ "serde_json", "serial_test", "sha1_smol", + "sha2", "sourcemap", "symbolic", "tempfile", "thiserror 1.0.69", + "tokio", "trycmd", "url", "uuid", @@ -2973,6 +3420,16 @@ dependencies = [ "anstream", ] +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "socket2" version = "0.6.0" @@ -3144,6 +3601,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -3155,6 +3621,33 @@ dependencies = [ "syn", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "tap" version = "1.0.1" @@ -3282,6 +3775,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.47.1" @@ -3296,10 +3804,42 @@ dependencies = [ "parking_lot", "pin-project-lite", "slab", - "socket2", + "socket2 0.6.0", + "tokio-macros", "windows-sys 0.59.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.16" @@ -3342,6 +3882,51 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + [[package]] name = "tracing" version = "0.1.41" @@ -3373,6 +3958,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "trycmd" version = "0.14.21" @@ -3434,6 +4025,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +[[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.7" @@ -3514,6 +4111,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3571,6 +4177,19 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.104" @@ -3603,6 +4222,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasmparser" version = "0.214.0" @@ -3660,6 +4292,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + [[package]] name = "winapi" version = "0.3.9" @@ -3700,8 +4338,8 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link 0.2.0", - "windows-result", - "windows-strings", + "windows-result 0.4.0", + "windows-strings 0.5.0", ] [[package]] @@ -3738,6 +4376,26 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-result" version = "0.4.0" @@ -3747,6 +4405,15 @@ dependencies = [ "windows-link 0.2.0", ] +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-strings" version = "0.5.0" @@ -4053,6 +4720,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/Cargo.toml b/Cargo.toml index 189837ad44..7fa90334bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,9 @@ chrono-tz = "0.8.4" secrecy = "0.8.0" lru = "0.16.0" backon = { version = "1.5.2", features = ["std", "std-blocking-sleep"] } +objectstore-client = "0.0.14" +sha2 = "0.10" +tokio = { version = "1.47", features = ["rt", "macros"] } [dev-dependencies] assert_cmd = "2.0.11" diff --git a/src/commands/build/mod.rs b/src/commands/build/mod.rs index 72b2216b78..d302aa0791 100644 --- a/src/commands/build/mod.rs +++ b/src/commands/build/mod.rs @@ -3,10 +3,12 @@ use clap::{ArgMatches, Command}; use crate::utils::args::ArgExt as _; +pub mod snapshots; pub mod upload; macro_rules! each_subcommand { ($mac:ident) => { + $mac!(snapshots); $mac!(upload); }; } diff --git a/src/commands/build/snapshots.rs b/src/commands/build/snapshots.rs new file mode 100644 index 0000000000..2c0e3ff99c --- /dev/null +++ b/src/commands/build/snapshots.rs @@ -0,0 +1,208 @@ +use std::fs; +use std::path::Path; + +use anyhow::{Context as _, Result}; +use clap::{Arg, ArgMatches, Command}; +use console::style; +use log::{debug, info}; +use objectstore_client::{Client, Usecase}; +use sha2::{Digest as _, Sha256}; +use walkdir::WalkDir; + +use crate::config::Config; +use crate::utils::args::ArgExt as _; + +const EXPERIMENTAL_WARNING: &str = + "[EXPERIMENTAL] The \"build snapshots\" command is experimental. \ + The command is subject to breaking changes, including removal, in any Sentry CLI release."; + +pub fn make_command(command: Command) -> Command { + command + .about("[EXPERIMENTAL] Upload build snapshots to a project.") + .long_about(format!( + "Upload build snapshots to a project.\n\n{EXPERIMENTAL_WARNING}" + )) + .org_arg() + .project_arg(true) + .arg( + Arg::new("path") + .value_name("PATH") + .help("The path to the folder containing build snapshots.") + .required(true), + ) + .arg( + Arg::new("snapshot_id") + .long("snapshot-id") + .value_name("ID") + .help("The snapshot identifier to associate with the upload.") + .required(true), + ) + .arg( + Arg::new("shard_index") + .long("shard-index") + .value_name("INDEX") + .value_parser(clap::value_parser!(u32)) + .default_value("0") + .help("The shard index for this snapshot upload."), + ) +} + +pub fn execute(matches: &ArgMatches) -> Result<()> { + eprintln!("{EXPERIMENTAL_WARNING}"); + + let config = Config::current(); + let org = config.get_org(matches)?; + let project = config.get_project(matches)?; + + let path = matches + .get_one::("path") + .expect("path argument is required"); + let snapshot_id = matches + .get_one::("snapshot_id") + .expect("snapshot_id argument is required"); + let shard_index = matches + .get_one::("shard_index") + .expect("shard_index has a default value"); + + info!("Processing build snapshots from: {path}"); + info!("Using snapshot ID: {snapshot_id}"); + info!("Shard index: {shard_index}"); + info!("Organization: {org}"); + info!("Project: {project}"); + + // Collect files to upload + let files = collect_files(Path::new(path))?; + + if files.is_empty() { + println!("{} No files found to upload", style("!").yellow()); + return Ok(()); + } + + println!( + "{} Found {} {} to upload", + style(">").dim(), + style(files.len()).yellow(), + if files.len() == 1 { "file" } else { "files" } + ); + + // Upload files using objectstore client + upload_files(&files, &org, &project, snapshot_id, *shard_index)?; + + println!("{} Successfully uploaded snapshots", style(">").dim()); + Ok(()) +} + +fn collect_files(path: &Path) -> Result> { + if !path.exists() { + anyhow::bail!("Path does not exist: {}", path.display()); + } + + let mut files = Vec::new(); + + if path.is_file() { + // Only add if not hidden + if !is_hidden_file(path) { + files.push(path.to_path_buf()); + } + } else if path.is_dir() { + for entry in WalkDir::new(path) + .follow_links(true) + .into_iter() + .filter_map(Result::ok) + { + if entry.metadata()?.is_file() { + let entry_path = entry.path(); + // Skip hidden files + if !is_hidden_file(entry_path) { + files.push(entry_path.to_path_buf()); + } + } + } + } else { + anyhow::bail!("Path is neither a file nor directory: {}", path.display()); + } + + Ok(files) +} + +fn is_hidden_file(path: &Path) -> bool { + path.file_name() + .and_then(|name| name.to_str()) + .map(|name| name.starts_with('.')) + .unwrap_or(false) +} + +fn is_json_file(path: &Path) -> bool { + path.extension() + .and_then(|ext| ext.to_str()) + .map(|ext| ext.eq_ignore_ascii_case("json")) + .unwrap_or(false) +} + +fn upload_files( + files: &[std::path::PathBuf], + org: &str, + project: &str, + snapshot_id: &str, + _shard_index: u32, +) -> Result<()> { + // Create objectstore client + let client = Client::new("http://127.0.0.1:8888/")?; + let session = Usecase::new("preprod").for_project(1, 2).session(&client)?; + + // Create a multi-threaded tokio runtime for async operations + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .context("Failed to create tokio runtime")?; + + for file_path in files { + debug!("Processing file: {}", file_path.display()); + + // Read file contents + let contents = fs::read(file_path) + .with_context(|| format!("Failed to read file: {}", file_path.display()))?; + + // Determine the key based on file type + let key = if is_json_file(file_path) { + // For JSON files, use {org}/{snapshotId}/{filename} + let filename = file_path + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("unknown.json"); + format!("{org}/{snapshot_id}/{filename}") + } else { + // For other files, use {org}/{project}/{hash} + let hash = compute_sha256_hash(&contents); + format!("{org}/{project}/{hash}") + }; + + info!("Uploading {} as {key}", file_path.display()); + + // Upload to objectstore using the runtime thread pool + runtime.block_on(async { + session + .put(contents) + .key(&key) + .send() + .await + .with_context(|| format!("Failed to upload file: {}", file_path.display())) + })?; + + println!( + "{} Uploaded {} (key: {})", + style(">").dim(), + file_path.display(), + style(&key).cyan() + ); + } + + Ok(()) +} + +fn compute_sha256_hash(data: &[u8]) -> String { + let mut hasher = Sha256::new(); + hasher.update(data); + let result = hasher.finalize(); + format!("{result:x}") +} diff --git a/tests/integration/_cases/build/build-help.trycmd b/tests/integration/_cases/build/build-help.trycmd index ca926a2b6b..a04443131c 100644 --- a/tests/integration/_cases/build/build-help.trycmd +++ b/tests/integration/_cases/build/build-help.trycmd @@ -6,8 +6,9 @@ Manage builds. Usage: sentry-cli[EXE] build [OPTIONS] Commands: - upload Upload builds to a project. - help Print this message or the help of the given subcommand(s) + snapshots [EXPERIMENTAL] Upload build snapshots to a project. + upload Upload builds to a project. + help Print this message or the help of the given subcommand(s) Options: -o, --org The organization ID or slug. diff --git a/tests/integration/_cases/build/build-snapshots-help.trycmd b/tests/integration/_cases/build/build-snapshots-help.trycmd new file mode 100644 index 0000000000..e9daddb3d6 --- /dev/null +++ b/tests/integration/_cases/build/build-snapshots-help.trycmd @@ -0,0 +1,50 @@ +``` +$ sentry-cli build snapshots --help +? success +Upload build snapshots to a project. + +[EXPERIMENTAL] The "build snapshots" command is experimental. The command is subject to breaking +changes, including removal, in any Sentry CLI release. + +Usage: sentry-cli build snapshots [OPTIONS] --snapshot-id + +Arguments: + + The path to the folder containing build snapshots. + +Options: + -o, --org + The organization ID or slug. + + --header + Custom headers that should be attached to all requests + in key:value format. + + -p, --project + The project ID or slug. + + --auth-token + Use the given Sentry auth token. + + --snapshot-id + The snapshot identifier to associate with the upload. + + --log-level + Set the log output verbosity. [possible values: trace, debug, info, warn, error] + + --shard-index + The shard index for this snapshot upload. + + [default: 0] + + --quiet + Do not print any output while preserving correct exit code. This flag is currently + implemented only for selected subcommands. + + [aliases: --silent] + + -h, --help + Print help (see a summary with '-h') + +``` + diff --git a/tests/integration/build/mod.rs b/tests/integration/build/mod.rs index f73e2c8f36..239def73c5 100644 --- a/tests/integration/build/mod.rs +++ b/tests/integration/build/mod.rs @@ -6,3 +6,8 @@ mod upload; fn command_build_help() { TestManager::new().register_trycmd_test("build/build-help.trycmd"); } + +#[test] +fn command_build_snapshots_help() { + TestManager::new().register_trycmd_test("build/build-snapshots-help.trycmd"); +}