sentry-cli 3.3.3__tar.gz → 3.3.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/Cargo.lock +3 -3
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/Cargo.toml +1 -1
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/PKG-INFO +1 -1
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/sentry_cli.egg-info/PKG-INFO +1 -1
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/sentry_cli.egg-info/SOURCES.txt +4 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/build.rs +7 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/mod.rs +1 -1
- sentry_cli-3.3.5/src/api/data_types/code_mappings.rs +37 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/mod.rs +2 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/snapshots.rs +2 -14
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/mod.rs +31 -1
- sentry_cli-3.3.5/src/commands/build/download.rs +106 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/build/mod.rs +2 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/build/snapshots.rs +49 -18
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/build/upload.rs +15 -0
- sentry_cli-3.3.5/src/commands/code_mappings/mod.rs +45 -0
- sentry_cli-3.3.5/src/commands/code_mappings/upload.rs +452 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/mod.rs +2 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/progress.rs +1 -8
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/sourcemaps.rs +6 -1
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/vcs.rs +19 -7
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/LICENSE +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/MANIFEST.in +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/README.md +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/AGENTS.md +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/CLAUDE.md +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/Cargo.toml +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/build.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Package.swift +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/AssetCatalogParser/AssetCatalogReader.swift +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/include/safeValueForKey.h +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/safeValueForKey.m +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/AssetCatalogParserTests.swift +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Info.plist +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Products/Applications/DemoApp.app/Assets.car +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/src/asset_catalog.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/apple-catalog-parsing/src/lib.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/build.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/pyproject.toml +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/sentry_cli.egg-info/dependency_links.txt +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/sentry_cli.egg-info/top_level.txt +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/setup.cfg +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/setup.py +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/AGENTS.md +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/CLAUDE.md +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/connection_manager.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/artifact.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/compression.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/dif.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/file_state.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/upload/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/chunking/upload/options.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/data_types/deploy.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/encoding.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/envelopes_api.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/errors/api_error.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/errors/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/errors/sentry_error.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/pagination.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/api/serialization.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/bashsupport.sh +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/bash_hook.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/dart_symbol_map/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/dart_symbol_map/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/bundle_jvm.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/bundle_sources.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/check.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/find.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/print_sources.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/debug_files/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/deploys/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/deploys/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/deploys/new.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/derive_parser.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/events/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/events/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/info.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/issues/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/issues/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/issues/mute.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/issues/resolve.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/issues/unresolve.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/login.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/logs/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/logs/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/monitors/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/monitors/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/monitors/run.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/organizations/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/organizations/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/proguard/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/proguard/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/proguard/uuid.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/projects/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/projects/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/react_native/gradle.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/react_native/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/react_native/xcode.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/archive.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/delete.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/finalize.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/info.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/new.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/propose_version.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/restore.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/releases/set_commits.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/repos/list.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/repos/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_envelope.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_event.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_metric/common_args.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_metric/increment.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_metric/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/send_metric/set.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/sourcemaps/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/sourcemaps/resolve.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/sourcemaps/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/uninstall.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/update.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/upload_dif.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/upload_dsym.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/commands/upload_proguard.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/config.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/constants.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/main.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/android.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/args.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/auth_token_impl.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/error.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/org_auth_token.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/redacting.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/test.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/auth_token/user_auth_token.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/build/apple.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/build/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/build/normalize.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/build/validation.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/build_vcs.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/chunks/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/chunks/options.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/chunks/types.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/chunks/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/ci.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/cordova.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/dif.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/dif_upload/error.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/dif_upload/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/event.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/file_search.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/file_upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/formatting.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/fs.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/http.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/logging.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/non_empty.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/proguard/mapping.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/proguard/mod.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/proguard/upload.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/releases.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/retry.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/source_bundle.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/sourcemaps/inject.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/system.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/ui.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/update.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/value_parsers.rs +0 -0
- {sentry_cli-3.3.3 → sentry_cli-3.3.5}/src/utils/xcode.rs +0 -0
|
@@ -3230,9 +3230,9 @@ dependencies = [
|
|
|
3230
3230
|
|
|
3231
3231
|
[[package]]
|
|
3232
3232
|
name = "rustls-webpki"
|
|
3233
|
-
version = "0.103.
|
|
3233
|
+
version = "0.103.10"
|
|
3234
3234
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
3235
|
-
checksum = "
|
|
3235
|
+
checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef"
|
|
3236
3236
|
dependencies = [
|
|
3237
3237
|
"ring",
|
|
3238
3238
|
"rustls-pki-types",
|
|
@@ -3414,7 +3414,7 @@ dependencies = [
|
|
|
3414
3414
|
|
|
3415
3415
|
[[package]]
|
|
3416
3416
|
name = "sentry-cli"
|
|
3417
|
-
version = "3.3.
|
|
3417
|
+
version = "3.3.5"
|
|
3418
3418
|
dependencies = [
|
|
3419
3419
|
"anyhow",
|
|
3420
3420
|
"anylog",
|
|
@@ -36,6 +36,7 @@ src/api/envelopes_api.rs
|
|
|
36
36
|
src/api/mod.rs
|
|
37
37
|
src/api/pagination.rs
|
|
38
38
|
src/api/serialization.rs
|
|
39
|
+
src/api/data_types/code_mappings.rs
|
|
39
40
|
src/api/data_types/deploy.rs
|
|
40
41
|
src/api/data_types/mod.rs
|
|
41
42
|
src/api/data_types/snapshots.rs
|
|
@@ -63,9 +64,12 @@ src/commands/update.rs
|
|
|
63
64
|
src/commands/upload_dif.rs
|
|
64
65
|
src/commands/upload_dsym.rs
|
|
65
66
|
src/commands/upload_proguard.rs
|
|
67
|
+
src/commands/build/download.rs
|
|
66
68
|
src/commands/build/mod.rs
|
|
67
69
|
src/commands/build/snapshots.rs
|
|
68
70
|
src/commands/build/upload.rs
|
|
71
|
+
src/commands/code_mappings/mod.rs
|
|
72
|
+
src/commands/code_mappings/upload.rs
|
|
69
73
|
src/commands/dart_symbol_map/mod.rs
|
|
70
74
|
src/commands/dart_symbol_map/upload.rs
|
|
71
75
|
src/commands/debug_files/bundle_jvm.rs
|
|
@@ -28,6 +28,13 @@ pub struct AssembleBuildResponse {
|
|
|
28
28
|
pub artifact_url: Option<String>,
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
#[derive(Debug, Deserialize)]
|
|
32
|
+
#[serde(rename_all = "camelCase")]
|
|
33
|
+
pub struct BuildInstallDetails {
|
|
34
|
+
pub is_installable: bool,
|
|
35
|
+
pub install_url: Option<String>,
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
/// VCS information for build app uploads
|
|
32
39
|
#[derive(Debug, Serialize)]
|
|
33
40
|
pub struct VcsInfo<'a> {
|
|
@@ -10,7 +10,7 @@ mod hash_algorithm;
|
|
|
10
10
|
mod upload;
|
|
11
11
|
|
|
12
12
|
pub use self::artifact::{AssembleArtifactsResponse, ChunkedArtifactRequest};
|
|
13
|
-
pub use self::build::{AssembleBuildResponse, ChunkedBuildRequest, VcsInfo};
|
|
13
|
+
pub use self::build::{AssembleBuildResponse, BuildInstallDetails, ChunkedBuildRequest, VcsInfo};
|
|
14
14
|
pub use self::compression::ChunkCompression;
|
|
15
15
|
pub use self::dif::{AssembleDifsRequest, AssembleDifsResponse, ChunkedDifRequest};
|
|
16
16
|
pub use self::file_state::ChunkedFileState;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//! Data types for the bulk code mappings API.
|
|
2
|
+
|
|
3
|
+
use serde::{Deserialize, Serialize};
|
|
4
|
+
|
|
5
|
+
#[derive(Debug, Serialize)]
|
|
6
|
+
#[serde(rename_all = "camelCase")]
|
|
7
|
+
pub struct BulkCodeMappingsRequest<'a> {
|
|
8
|
+
pub project: &'a str,
|
|
9
|
+
pub repository: &'a str,
|
|
10
|
+
pub default_branch: &'a str,
|
|
11
|
+
pub mappings: &'a [BulkCodeMapping],
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
#[derive(Debug, Deserialize, Serialize)]
|
|
15
|
+
#[serde(rename_all = "camelCase")]
|
|
16
|
+
pub struct BulkCodeMapping {
|
|
17
|
+
pub stack_root: String,
|
|
18
|
+
pub source_root: String,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
#[derive(Debug, Deserialize)]
|
|
22
|
+
pub struct BulkCodeMappingsResponse {
|
|
23
|
+
pub created: u64,
|
|
24
|
+
pub updated: u64,
|
|
25
|
+
pub errors: u64,
|
|
26
|
+
pub mappings: Vec<BulkCodeMappingResult>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[derive(Debug, Deserialize)]
|
|
30
|
+
#[serde(rename_all = "camelCase")]
|
|
31
|
+
pub struct BulkCodeMappingResult {
|
|
32
|
+
pub stack_root: String,
|
|
33
|
+
pub source_root: String,
|
|
34
|
+
pub status: String,
|
|
35
|
+
#[serde(default)]
|
|
36
|
+
pub detail: Option<String>,
|
|
37
|
+
}
|
|
@@ -7,7 +7,6 @@ use serde_json::Value;
|
|
|
7
7
|
|
|
8
8
|
use super::VcsInfo;
|
|
9
9
|
|
|
10
|
-
const IMAGE_FILE_NAME_FIELD: &str = "image_file_name";
|
|
11
10
|
const WIDTH_FIELD: &str = "width";
|
|
12
11
|
const HEIGHT_FIELD: &str = "height";
|
|
13
12
|
|
|
@@ -42,16 +41,7 @@ pub struct ImageMetadata {
|
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
impl ImageMetadata {
|
|
45
|
-
pub fn new(
|
|
46
|
-
image_file_name: String,
|
|
47
|
-
width: u32,
|
|
48
|
-
height: u32,
|
|
49
|
-
mut extra: HashMap<String, Value>,
|
|
50
|
-
) -> Self {
|
|
51
|
-
extra.insert(
|
|
52
|
-
IMAGE_FILE_NAME_FIELD.to_owned(),
|
|
53
|
-
Value::String(image_file_name),
|
|
54
|
-
);
|
|
44
|
+
pub fn new(width: u32, height: u32, mut extra: HashMap<String, Value>) -> Self {
|
|
55
45
|
extra.insert(WIDTH_FIELD.to_owned(), Value::from(width));
|
|
56
46
|
extra.insert(HEIGHT_FIELD.to_owned(), Value::from(height));
|
|
57
47
|
|
|
@@ -68,18 +58,16 @@ mod tests {
|
|
|
68
58
|
#[test]
|
|
69
59
|
fn cli_managed_fields_override_sidecar_fields() {
|
|
70
60
|
let extra = serde_json::from_value(json!({
|
|
71
|
-
(IMAGE_FILE_NAME_FIELD): "from-sidecar.png",
|
|
72
61
|
(WIDTH_FIELD): 1,
|
|
73
62
|
(HEIGHT_FIELD): 2,
|
|
74
63
|
"custom": "keep-me"
|
|
75
64
|
}))
|
|
76
65
|
.unwrap();
|
|
77
66
|
|
|
78
|
-
let metadata = ImageMetadata::new(
|
|
67
|
+
let metadata = ImageMetadata::new(100, 200, extra);
|
|
79
68
|
let serialized = serde_json::to_value(metadata).unwrap();
|
|
80
69
|
|
|
81
70
|
let expected = json!({
|
|
82
|
-
(IMAGE_FILE_NAME_FIELD): "from-cli.png",
|
|
83
71
|
(WIDTH_FIELD): 100,
|
|
84
72
|
(HEIGHT_FIELD): 200,
|
|
85
73
|
"custom": "keep-me"
|
|
@@ -16,7 +16,6 @@ use std::borrow::Cow;
|
|
|
16
16
|
use std::cell::RefCell;
|
|
17
17
|
use std::collections::HashMap;
|
|
18
18
|
use std::error::Error as _;
|
|
19
|
-
#[cfg(any(target_os = "macos", not(feature = "managed")))]
|
|
20
19
|
use std::fs::File;
|
|
21
20
|
use std::io::{self, Read as _, Write};
|
|
22
21
|
use std::rc::Rc;
|
|
@@ -724,6 +723,26 @@ impl AuthenticatedApi<'_> {
|
|
|
724
723
|
.convert_rnf(ApiErrorKind::ProjectNotFound)
|
|
725
724
|
}
|
|
726
725
|
|
|
726
|
+
pub fn get_build_install_details(
|
|
727
|
+
&self,
|
|
728
|
+
org: &str,
|
|
729
|
+
build_id: &str,
|
|
730
|
+
) -> ApiResult<BuildInstallDetails> {
|
|
731
|
+
let url = format!(
|
|
732
|
+
"/organizations/{}/preprodartifacts/{}/install-details/",
|
|
733
|
+
PathArg(org),
|
|
734
|
+
PathArg(build_id)
|
|
735
|
+
);
|
|
736
|
+
|
|
737
|
+
self.get(&url)?.convert()
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
pub fn download_installable_build(&self, url: &str, dst: &mut File) -> ApiResult<ApiResponse> {
|
|
741
|
+
self.request(Method::Get, url)?
|
|
742
|
+
.progress_bar_mode(ProgressBarMode::Response)
|
|
743
|
+
.send_into(dst)
|
|
744
|
+
}
|
|
745
|
+
|
|
727
746
|
/// List all organizations associated with the authenticated token
|
|
728
747
|
/// in the given `Region`. If no `Region` is provided, we assume
|
|
729
748
|
/// we're issuing a request to a monolith deployment.
|
|
@@ -978,6 +997,17 @@ impl AuthenticatedApi<'_> {
|
|
|
978
997
|
Ok(rv)
|
|
979
998
|
}
|
|
980
999
|
|
|
1000
|
+
/// Bulk uploads code mappings for an organization.
|
|
1001
|
+
pub fn bulk_upload_code_mappings(
|
|
1002
|
+
&self,
|
|
1003
|
+
org: &str,
|
|
1004
|
+
body: &BulkCodeMappingsRequest,
|
|
1005
|
+
) -> ApiResult<BulkCodeMappingsResponse> {
|
|
1006
|
+
let path = format!("/organizations/{}/code-mappings/bulk/", PathArg(org));
|
|
1007
|
+
self.post(&path, body)?
|
|
1008
|
+
.convert_rnf(ApiErrorKind::OrganizationNotFound)
|
|
1009
|
+
}
|
|
1010
|
+
|
|
981
1011
|
/// Creates a preprod snapshot artifact for the given project.
|
|
982
1012
|
pub fn create_preprod_snapshot<S: Serialize>(
|
|
983
1013
|
&self,
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
use std::fs;
|
|
2
|
+
use std::path::PathBuf;
|
|
3
|
+
|
|
4
|
+
use anyhow::{bail, Result};
|
|
5
|
+
use clap::{Arg, ArgMatches, Command};
|
|
6
|
+
use log::info;
|
|
7
|
+
|
|
8
|
+
use crate::api::Api;
|
|
9
|
+
use crate::config::Config;
|
|
10
|
+
use crate::utils::args::ArgExt as _;
|
|
11
|
+
use crate::utils::fs::TempFile;
|
|
12
|
+
|
|
13
|
+
const EXPERIMENTAL_WARNING: &str =
|
|
14
|
+
"[EXPERIMENTAL] The \"build download\" command is experimental. \
|
|
15
|
+
The command is subject to breaking changes, including removal, in any Sentry CLI release.";
|
|
16
|
+
|
|
17
|
+
pub fn make_command(command: Command) -> Command {
|
|
18
|
+
command
|
|
19
|
+
.about("[EXPERIMENTAL] Download a build artifact.")
|
|
20
|
+
.long_about(format!(
|
|
21
|
+
"Download a build artifact.\n\n{EXPERIMENTAL_WARNING}"
|
|
22
|
+
))
|
|
23
|
+
.org_arg()
|
|
24
|
+
.arg(
|
|
25
|
+
Arg::new("build_id")
|
|
26
|
+
.long("build-id")
|
|
27
|
+
.short('b')
|
|
28
|
+
.required(true)
|
|
29
|
+
.help("The ID of the build to download."),
|
|
30
|
+
)
|
|
31
|
+
.arg(Arg::new("output").long("output").help(
|
|
32
|
+
"The output file path. Defaults to \
|
|
33
|
+
'preprod_artifact_<build_id>.<ext>' in the current directory, \
|
|
34
|
+
where ext is ipa or apk depending on the platform.",
|
|
35
|
+
))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// For iOS builds, the install URL points to a plist manifest.
|
|
39
|
+
/// Replace the response_format to download the actual IPA binary instead.
|
|
40
|
+
fn ensure_binary_format(url: &str) -> String {
|
|
41
|
+
url.replace("response_format=plist", "response_format=ipa")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// Extract the file extension from the response_format query parameter.
|
|
45
|
+
fn extension_from_url(url: &str) -> Result<&str> {
|
|
46
|
+
if url.contains("response_format=ipa") {
|
|
47
|
+
Ok("ipa")
|
|
48
|
+
} else if url.contains("response_format=apk") {
|
|
49
|
+
Ok("apk")
|
|
50
|
+
} else {
|
|
51
|
+
bail!("Unsupported build format in download URL.")
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
56
|
+
eprintln!("{EXPERIMENTAL_WARNING}");
|
|
57
|
+
let config = Config::current();
|
|
58
|
+
let org = config.get_org(matches)?;
|
|
59
|
+
let build_id = matches
|
|
60
|
+
.get_one::<String>("build_id")
|
|
61
|
+
.expect("build_id is required");
|
|
62
|
+
|
|
63
|
+
let api = Api::current();
|
|
64
|
+
let authenticated_api = api.authenticated()?;
|
|
65
|
+
|
|
66
|
+
info!("Fetching install details for build {build_id}");
|
|
67
|
+
let details = authenticated_api.get_build_install_details(&org, build_id)?;
|
|
68
|
+
|
|
69
|
+
if !details.is_installable {
|
|
70
|
+
bail!("Build {build_id} is not installable.");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let install_url = details
|
|
74
|
+
.install_url
|
|
75
|
+
.ok_or_else(|| anyhow::anyhow!("Build {build_id} has no install URL."))?;
|
|
76
|
+
|
|
77
|
+
let download_url = ensure_binary_format(&install_url);
|
|
78
|
+
|
|
79
|
+
let output_path = match matches.get_one::<String>("output") {
|
|
80
|
+
Some(path) => PathBuf::from(path),
|
|
81
|
+
None => {
|
|
82
|
+
let ext = extension_from_url(&download_url)?;
|
|
83
|
+
PathBuf::from(format!("preprod_artifact_{build_id}.{ext}"))
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
info!("Downloading build {build_id} to {}", output_path.display());
|
|
88
|
+
|
|
89
|
+
let tmp = TempFile::create()?;
|
|
90
|
+
let mut file = tmp.open()?;
|
|
91
|
+
let response = authenticated_api.download_installable_build(&download_url, &mut file)?;
|
|
92
|
+
|
|
93
|
+
if response.failed() {
|
|
94
|
+
bail!(
|
|
95
|
+
"Failed to download build (server returned status {}).",
|
|
96
|
+
response.status()
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
drop(file);
|
|
101
|
+
fs::copy(tmp.path(), &output_path)?;
|
|
102
|
+
|
|
103
|
+
println!("Successfully downloaded build to {}", output_path.display());
|
|
104
|
+
|
|
105
|
+
Ok(())
|
|
106
|
+
}
|
|
@@ -3,11 +3,13 @@ use clap::{ArgMatches, Command};
|
|
|
3
3
|
|
|
4
4
|
use crate::utils::args::ArgExt as _;
|
|
5
5
|
|
|
6
|
+
pub mod download;
|
|
6
7
|
pub mod snapshots;
|
|
7
8
|
pub mod upload;
|
|
8
9
|
|
|
9
10
|
macro_rules! each_subcommand {
|
|
10
11
|
($mac:ident) => {
|
|
12
|
+
$mac!(download);
|
|
11
13
|
$mac!(snapshots);
|
|
12
14
|
$mac!(upload);
|
|
13
15
|
};
|
|
@@ -11,6 +11,7 @@ use console::style;
|
|
|
11
11
|
use itertools::Itertools as _;
|
|
12
12
|
use log::{debug, info, warn};
|
|
13
13
|
use objectstore_client::{ClientBuilder, ExpirationPolicy, Usecase};
|
|
14
|
+
use rayon::prelude::*;
|
|
14
15
|
use secrecy::ExposeSecret as _;
|
|
15
16
|
use serde_json::Value;
|
|
16
17
|
use sha2::{Digest as _, Sha256};
|
|
@@ -230,7 +231,7 @@ fn compute_sha256_hash(path: &Path) -> Result<String> {
|
|
|
230
231
|
let mut file = std::fs::File::open(path)
|
|
231
232
|
.with_context(|| format!("Failed to open image for hashing: {}", path.display()))?;
|
|
232
233
|
let mut hasher = Sha256::new();
|
|
233
|
-
let mut buffer = [0u8;
|
|
234
|
+
let mut buffer = [0u8; 65536];
|
|
234
235
|
loop {
|
|
235
236
|
let bytes_read = file
|
|
236
237
|
.read(&mut buffer)
|
|
@@ -331,12 +332,35 @@ fn upload_images(
|
|
|
331
332
|
|
|
332
333
|
let mut many_builder = session.many();
|
|
333
334
|
let mut manifest_entries = HashMap::new();
|
|
334
|
-
let
|
|
335
|
+
let mut collisions: HashMap<String, Vec<String>> = HashMap::new();
|
|
336
|
+
let mut kept_paths = HashMap::new();
|
|
337
|
+
|
|
338
|
+
let hashed_images: Vec<_> = images
|
|
339
|
+
.into_par_iter()
|
|
340
|
+
.map(|image| {
|
|
341
|
+
let hash = compute_sha256_hash(&image.path)?;
|
|
342
|
+
Ok((image, hash))
|
|
343
|
+
})
|
|
344
|
+
.collect::<Result<Vec<_>>>()?;
|
|
335
345
|
|
|
336
|
-
for image in
|
|
337
|
-
|
|
346
|
+
for (image, hash) in hashed_images {
|
|
347
|
+
let image_file_name = image
|
|
348
|
+
.relative_path
|
|
349
|
+
.file_name()
|
|
350
|
+
.unwrap_or_default()
|
|
351
|
+
.to_string_lossy()
|
|
352
|
+
.into_owned();
|
|
353
|
+
|
|
354
|
+
let relative_path = crate::utils::fs::path_as_url(&image.relative_path);
|
|
355
|
+
|
|
356
|
+
if manifest_entries.contains_key(&image_file_name) {
|
|
357
|
+
collisions
|
|
358
|
+
.entry(image_file_name)
|
|
359
|
+
.or_default()
|
|
360
|
+
.push(relative_path);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
338
363
|
|
|
339
|
-
let hash = compute_sha256_hash(&image.path)?;
|
|
340
364
|
let file = runtime
|
|
341
365
|
.block_on(tokio::fs::File::open(&image.path))
|
|
342
366
|
.with_context(|| {
|
|
@@ -353,33 +377,40 @@ fn upload_images(
|
|
|
353
377
|
.expiration_policy(expiration),
|
|
354
378
|
);
|
|
355
379
|
|
|
356
|
-
let
|
|
357
|
-
.relative_path
|
|
358
|
-
.file_name()
|
|
359
|
-
.unwrap_or_default()
|
|
360
|
-
.to_string_lossy()
|
|
361
|
-
.into_owned();
|
|
362
|
-
|
|
363
|
-
let extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
|
|
380
|
+
let mut extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
|
|
364
381
|
warn!("Error reading sidecar metadata, ignoring it instead: {err:#}");
|
|
365
382
|
HashMap::new()
|
|
366
383
|
});
|
|
384
|
+
extra.insert("content_hash".to_owned(), serde_json::Value::String(hash));
|
|
367
385
|
|
|
386
|
+
kept_paths.insert(image_file_name.clone(), relative_path);
|
|
368
387
|
manifest_entries.insert(
|
|
369
|
-
|
|
370
|
-
ImageMetadata::new(
|
|
388
|
+
image_file_name,
|
|
389
|
+
ImageMetadata::new(image.width, image.height, extra),
|
|
371
390
|
);
|
|
372
391
|
}
|
|
373
392
|
|
|
393
|
+
if !collisions.is_empty() {
|
|
394
|
+
let mut details = String::new();
|
|
395
|
+
for (name, excluded_paths) in &collisions {
|
|
396
|
+
let mut all_paths = vec![kept_paths[name].as_str()];
|
|
397
|
+
all_paths.extend(excluded_paths.iter().map(|s| s.as_str()));
|
|
398
|
+
details.push_str(&format!("\n {name}: {}", all_paths.join(", ")));
|
|
399
|
+
}
|
|
400
|
+
warn!("Some images share identical file names. Only the first occurrence of each is included:{details}");
|
|
401
|
+
}
|
|
402
|
+
|
|
374
403
|
let result = runtime.block_on(async { many_builder.send().error_for_failures().await });
|
|
375
404
|
|
|
405
|
+
let uploaded_count = manifest_entries.len();
|
|
406
|
+
|
|
376
407
|
match result {
|
|
377
408
|
Ok(()) => {
|
|
378
409
|
println!(
|
|
379
410
|
"{} Uploaded {} image {}",
|
|
380
411
|
style(">").dim(),
|
|
381
|
-
style(
|
|
382
|
-
if
|
|
412
|
+
style(uploaded_count).yellow(),
|
|
413
|
+
if uploaded_count == 1 { "file" } else { "files" }
|
|
383
414
|
);
|
|
384
415
|
Ok(manifest_entries)
|
|
385
416
|
}
|
|
@@ -391,7 +422,7 @@ fn upload_images(
|
|
|
391
422
|
eprintln!(" {}", style(format!("{error:#}")).red());
|
|
392
423
|
error_count += 1;
|
|
393
424
|
}
|
|
394
|
-
anyhow::bail!("Failed to upload {error_count} out of {
|
|
425
|
+
anyhow::bail!("Failed to upload {error_count} out of {uploaded_count} images")
|
|
395
426
|
}
|
|
396
427
|
}
|
|
397
428
|
}
|
|
@@ -143,6 +143,20 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
143
143
|
return Err(anyhow!("Path does not exist: {}", path.display()));
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
// On non-Apple Silicon, reject xcarchive/IPA early before trying to
|
|
147
|
+
// open the path as a file (xcarchive is a directory, so ByteView::open
|
|
148
|
+
// would fail with a confusing I/O error).
|
|
149
|
+
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
|
|
150
|
+
{
|
|
151
|
+
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
|
|
152
|
+
if ext.eq_ignore_ascii_case("xcarchive") || ext.eq_ignore_ascii_case("ipa") {
|
|
153
|
+
return Err(anyhow!(
|
|
154
|
+
"Uploading XCArchive and IPA files requires an Apple Silicon Mac: {}",
|
|
155
|
+
path.display()
|
|
156
|
+
));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
146
160
|
let byteview = ByteView::open(path)?;
|
|
147
161
|
debug!("Loaded file with {} bytes", byteview.len());
|
|
148
162
|
|
|
@@ -301,6 +315,7 @@ fn validate_is_supported_build(path: &Path, bytes: &[u8]) -> Result<()> {
|
|
|
301
315
|
}
|
|
302
316
|
|
|
303
317
|
debug!("File format validation failed");
|
|
318
|
+
|
|
304
319
|
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
|
305
320
|
let format_list = "APK, AAB, XCArchive, or IPA";
|
|
306
321
|
#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
use anyhow::Result;
|
|
2
|
+
use clap::{ArgMatches, Command};
|
|
3
|
+
|
|
4
|
+
use crate::utils::args::ArgExt as _;
|
|
5
|
+
|
|
6
|
+
pub mod upload;
|
|
7
|
+
|
|
8
|
+
macro_rules! each_subcommand {
|
|
9
|
+
($mac:ident) => {
|
|
10
|
+
$mac!(upload);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pub fn make_command(mut command: Command) -> Command {
|
|
15
|
+
macro_rules! add_subcommand {
|
|
16
|
+
($name:ident) => {{
|
|
17
|
+
command = command.subcommand(crate::commands::code_mappings::$name::make_command(
|
|
18
|
+
Command::new(stringify!($name).replace('_', "-")),
|
|
19
|
+
));
|
|
20
|
+
}};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
command = command
|
|
24
|
+
.about("Manage code mappings for Sentry. Code mappings link stack trace paths to source code paths in your repository, enabling source context and code linking in Sentry.")
|
|
25
|
+
.subcommand_required(true)
|
|
26
|
+
.arg_required_else_help(true)
|
|
27
|
+
.org_arg()
|
|
28
|
+
.project_arg(false);
|
|
29
|
+
each_subcommand!(add_subcommand);
|
|
30
|
+
command
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
34
|
+
macro_rules! execute_subcommand {
|
|
35
|
+
($name:ident) => {{
|
|
36
|
+
if let Some(sub_matches) =
|
|
37
|
+
matches.subcommand_matches(&stringify!($name).replace('_', "-"))
|
|
38
|
+
{
|
|
39
|
+
return crate::commands::code_mappings::$name::execute(&sub_matches);
|
|
40
|
+
}
|
|
41
|
+
}};
|
|
42
|
+
}
|
|
43
|
+
each_subcommand!(execute_subcommand);
|
|
44
|
+
unreachable!();
|
|
45
|
+
}
|