sentry-cli 2.45.0__tar.gz → 2.46.0a0__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-2.45.0 → sentry_cli-2.46.0a0}/Cargo.lock +1 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/Cargo.toml +1 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/PKG-INFO +1 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/sentry_cli.egg-info/PKG-INFO +1 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/errors/api_error.rs +0 -2
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/mod.rs +11 -67
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/bundle_sources.rs +8 -3
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/files/delete.rs +2 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/files/list.rs +2 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/files/mod.rs +6 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/files/upload.rs +2 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/react_native/gradle.rs +6 -6
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/finalize.rs +9 -2
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/sourcemaps/explain.rs +2 -1
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/sourcemaps/upload.rs +8 -6
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/config.rs +56 -8
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/file_upload.rs +73 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/sourcemaps.rs +45 -138
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/system.rs +24 -17
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/LICENSE +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/MANIFEST.in +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/README.md +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/build.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/pyproject.toml +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/sentry_cli.egg-info/SOURCES.txt +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/sentry_cli.egg-info/dependency_links.txt +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/sentry_cli.egg-info/top_level.txt +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/setup.cfg +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/setup.py +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/connection_manager.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/artifact.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/compression.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/dif.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/file_state.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/upload/capability.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/upload/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/chunking/upload/options.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/deploy.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/data_types/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/encoding.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/envelopes_api.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/errors/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/errors/sentry_error.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/api/pagination.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/bashsupport.sh +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/bash_hook.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/bundle_jvm.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/check.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/find.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/print_sources.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/debug_files/upload.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/deploys/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/deploys/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/deploys/new.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/derive_parser.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/events/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/events/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/info.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/issues/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/issues/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/issues/mute.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/issues/resolve.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/issues/unresolve.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/login.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/monitors/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/monitors/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/monitors/run.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/organizations/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/organizations/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/projects/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/projects/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/react_native/appcenter.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/react_native/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/react_native/xcode.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/archive.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/delete.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/info.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/new.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/propose_version.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/restore.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/releases/set_commits.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/repos/list.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/repos/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_envelope.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_event.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/common_args.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/distribution.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/gauge.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/increment.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/send_metric/set.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/sourcemaps/inject.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/sourcemaps/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/sourcemaps/resolve.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/uninstall.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/update.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/upload_dif.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/upload_dsym.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/commands/upload_proguard.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/constants.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/main.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/android.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/appcenter.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/args.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/auth_token_impl.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/error.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/org_auth_token.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/redacting.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/test.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/auth_token/user_auth_token.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/chunks/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/chunks/options.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/chunks/types.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/chunks/upload.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/cordova.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/dif.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/dif_upload/error.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/dif_upload/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/event.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/file_search.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/formatting.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/fs.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/http.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/logging.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/metrics.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/progress.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/proguard/mapping.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/proguard/mod.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/proguard/upload.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/releases.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/retry.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_default_twenty.snap +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_ignore_missing.snap +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_base.snap +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/snapshots/sentry_cli__utils__vcs__generate_patch_set_previous_commit.snap +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/snapshots/sentry_cli__utils__vcs__get_commits_from_git.snap +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/sourcemaps/inject.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/ui.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/update.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/value_parsers.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/vcs.rs +0 -0
- {sentry_cli-2.45.0 → sentry_cli-2.46.0a0}/src/utils/xcode.rs +0 -0
|
@@ -65,6 +65,13 @@ lazy_static! {
|
|
|
65
65
|
static ref API: Mutex<Option<Arc<Api>>> = Mutex::new(None);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
const RETRY_STATUS_CODES: &[u32] = &[
|
|
69
|
+
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
70
|
+
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
71
|
+
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
72
|
+
http::HTTP_STATUS_507_INSUFFICIENT_STORAGE,
|
|
73
|
+
];
|
|
74
|
+
|
|
68
75
|
/// Helper for the API access.
|
|
69
76
|
/// Implements the low-level API access methods, and provides high-level implementations for interacting
|
|
70
77
|
/// with portions of the API that do not require authentication via an auth token.
|
|
@@ -113,8 +120,6 @@ pub struct ApiRequest {
|
|
|
113
120
|
is_authenticated: bool,
|
|
114
121
|
body: Option<Vec<u8>>,
|
|
115
122
|
progress_bar_mode: ProgressBarMode,
|
|
116
|
-
max_retries: u32,
|
|
117
|
-
retry_on_statuses: &'static [u32],
|
|
118
123
|
}
|
|
119
124
|
|
|
120
125
|
/// Represents an API response.
|
|
@@ -395,14 +400,6 @@ impl Api {
|
|
|
395
400
|
let request = self
|
|
396
401
|
.request(Method::Post, url, None)?
|
|
397
402
|
.with_form_data(form)?
|
|
398
|
-
.with_retry(
|
|
399
|
-
self.config.get_max_retry_count().unwrap(),
|
|
400
|
-
&[
|
|
401
|
-
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
402
|
-
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
403
|
-
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
404
|
-
],
|
|
405
|
-
)
|
|
406
403
|
.progress_bar_mode(progress_bar_mode);
|
|
407
404
|
|
|
408
405
|
// The request is performed to an absolute URL. Thus, `Self::request()` will
|
|
@@ -967,14 +964,6 @@ impl<'a> AuthenticatedApi<'a> {
|
|
|
967
964
|
|
|
968
965
|
self.request(Method::Post, &url)?
|
|
969
966
|
.with_json_body(request)?
|
|
970
|
-
.with_retry(
|
|
971
|
-
self.api.config.get_max_retry_count().unwrap(),
|
|
972
|
-
&[
|
|
973
|
-
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
974
|
-
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
975
|
-
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
976
|
-
],
|
|
977
|
-
)
|
|
978
967
|
.send()?
|
|
979
968
|
.convert_rnf(ApiErrorKind::ProjectNotFound)
|
|
980
969
|
}
|
|
@@ -1000,14 +989,6 @@ impl<'a> AuthenticatedApi<'a> {
|
|
|
1000
989
|
version: None,
|
|
1001
990
|
dist: None,
|
|
1002
991
|
})?
|
|
1003
|
-
.with_retry(
|
|
1004
|
-
self.api.config.get_max_retry_count().unwrap(),
|
|
1005
|
-
&[
|
|
1006
|
-
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
1007
|
-
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
1008
|
-
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
1009
|
-
],
|
|
1010
|
-
)
|
|
1011
992
|
.send()?
|
|
1012
993
|
.convert_rnf(ApiErrorKind::ReleaseNotFound)
|
|
1013
994
|
}
|
|
@@ -1031,14 +1012,6 @@ impl<'a> AuthenticatedApi<'a> {
|
|
|
1031
1012
|
version,
|
|
1032
1013
|
dist,
|
|
1033
1014
|
})?
|
|
1034
|
-
.with_retry(
|
|
1035
|
-
self.api.config.get_max_retry_count().unwrap(),
|
|
1036
|
-
&[
|
|
1037
|
-
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
1038
|
-
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
1039
|
-
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
1040
|
-
],
|
|
1041
|
-
)
|
|
1042
1015
|
.send()?
|
|
1043
1016
|
.convert_rnf(ApiErrorKind::ReleaseNotFound)
|
|
1044
1017
|
}
|
|
@@ -1407,15 +1380,6 @@ impl RegionSpecificApi<'_> {
|
|
|
1407
1380
|
form.part("file").file(file).add()?;
|
|
1408
1381
|
self.request(Method::Post, &path)?
|
|
1409
1382
|
.with_form_data(form)?
|
|
1410
|
-
.with_retry(
|
|
1411
|
-
self.api.api.config.get_max_retry_count().map_err(|e| {
|
|
1412
|
-
ApiError::with_source(
|
|
1413
|
-
ApiErrorKind::ErrorPreparingRequest,
|
|
1414
|
-
e.context("Could not parse retry count"),
|
|
1415
|
-
)
|
|
1416
|
-
})?,
|
|
1417
|
-
&[http::HTTP_STATUS_507_INSUFFICIENT_STORAGE],
|
|
1418
|
-
)
|
|
1419
1383
|
.progress_bar_mode(ProgressBarMode::Request)
|
|
1420
1384
|
.send()?
|
|
1421
1385
|
.convert()
|
|
@@ -1471,14 +1435,6 @@ impl RegionSpecificApi<'_> {
|
|
|
1471
1435
|
let resp = self
|
|
1472
1436
|
.request(Method::Post, &path)?
|
|
1473
1437
|
.with_form_data(form)?
|
|
1474
|
-
.with_retry(
|
|
1475
|
-
self.api.api.config.get_max_retry_count().unwrap(),
|
|
1476
|
-
&[
|
|
1477
|
-
http::HTTP_STATUS_502_BAD_GATEWAY,
|
|
1478
|
-
http::HTTP_STATUS_503_SERVICE_UNAVAILABLE,
|
|
1479
|
-
http::HTTP_STATUS_504_GATEWAY_TIMEOUT,
|
|
1480
|
-
],
|
|
1481
|
-
)
|
|
1482
1438
|
.progress_bar_mode(progress_bar_mode)
|
|
1483
1439
|
.send()?;
|
|
1484
1440
|
if resp.status() == 409 {
|
|
@@ -1666,8 +1622,6 @@ impl ApiRequest {
|
|
|
1666
1622
|
is_authenticated: false,
|
|
1667
1623
|
body: None,
|
|
1668
1624
|
progress_bar_mode: ProgressBarMode::Disabled,
|
|
1669
|
-
max_retries: 0,
|
|
1670
|
-
retry_on_statuses: &[],
|
|
1671
1625
|
};
|
|
1672
1626
|
|
|
1673
1627
|
let request = match auth {
|
|
@@ -1741,13 +1695,6 @@ impl ApiRequest {
|
|
|
1741
1695
|
self
|
|
1742
1696
|
}
|
|
1743
1697
|
|
|
1744
|
-
pub fn with_retry(mut self, max_retries: u32, retry_on_statuses: &'static [u32]) -> Self {
|
|
1745
|
-
self.max_retries = max_retries;
|
|
1746
|
-
self.retry_on_statuses = retry_on_statuses;
|
|
1747
|
-
|
|
1748
|
-
self
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
1698
|
/// Get a copy of the header list
|
|
1752
1699
|
fn get_headers(&self) -> curl::easy::List {
|
|
1753
1700
|
let mut result = curl::easy::List::new();
|
|
@@ -1776,18 +1723,17 @@ impl ApiRequest {
|
|
|
1776
1723
|
|
|
1777
1724
|
/// Sends the request and reads the response body into the response object.
|
|
1778
1725
|
pub fn send(mut self) -> ApiResult<ApiResponse> {
|
|
1726
|
+
let max_retries = Config::current().max_retries();
|
|
1727
|
+
|
|
1779
1728
|
let mut backoff = get_default_backoff();
|
|
1780
1729
|
let mut retry_number = 0;
|
|
1781
1730
|
|
|
1782
1731
|
loop {
|
|
1783
1732
|
let mut out = vec![];
|
|
1784
|
-
debug!(
|
|
1785
|
-
"retry number {}, max retries: {}",
|
|
1786
|
-
retry_number, self.max_retries,
|
|
1787
|
-
);
|
|
1733
|
+
debug!("retry number {retry_number}, max retries: {max_retries}",);
|
|
1788
1734
|
|
|
1789
1735
|
let mut rv = self.send_into(&mut out)?;
|
|
1790
|
-
if retry_number >=
|
|
1736
|
+
if retry_number >= max_retries || !RETRY_STATUS_CODES.contains(&rv.status) {
|
|
1791
1737
|
rv.body = Some(out);
|
|
1792
1738
|
return Ok(rv);
|
|
1793
1739
|
}
|
|
@@ -2054,8 +2000,6 @@ pub struct UpdatedRelease {
|
|
|
2054
2000
|
pub projects: Option<Vec<String>>,
|
|
2055
2001
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
2056
2002
|
pub url: Option<String>,
|
|
2057
|
-
#[serde(rename = "dateStarted", skip_serializing_if = "Option::is_none")]
|
|
2058
|
-
pub date_started: Option<DateTime<Utc>>,
|
|
2059
2003
|
#[serde(rename = "dateReleased", skip_serializing_if = "Option::is_none")]
|
|
2060
2004
|
pub date_released: Option<DateTime<Utc>>,
|
|
2061
2005
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
@@ -71,12 +71,13 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
71
71
|
let output_path = matches.get_one::<String>("output").map(Path::new);
|
|
72
72
|
|
|
73
73
|
for orig_path in matches.get_many::<String>("paths").unwrap() {
|
|
74
|
+
let orig_path: &Path = orig_path.as_ref();
|
|
74
75
|
let canonical_path = get_canonical_path(orig_path)?;
|
|
75
76
|
|
|
76
77
|
let archive = match DifFile::open_path(&canonical_path, None)? {
|
|
77
78
|
DifFile::Archive(archive) => archive,
|
|
78
79
|
_ => {
|
|
79
|
-
warn!("Cannot build source bundles from {}", orig_path);
|
|
80
|
+
warn!("Cannot build source bundles from {}", orig_path.display());
|
|
80
81
|
continue;
|
|
81
82
|
}
|
|
82
83
|
};
|
|
@@ -88,7 +89,11 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
88
89
|
for (index, object) in archive.get().objects().enumerate() {
|
|
89
90
|
let object = object?;
|
|
90
91
|
|
|
91
|
-
let mut out = output_path.unwrap_or(parent_path).join(
|
|
92
|
+
let mut out = output_path.unwrap_or(parent_path).join(
|
|
93
|
+
orig_path
|
|
94
|
+
.file_name()
|
|
95
|
+
.expect("orig_path should have a file name"),
|
|
96
|
+
);
|
|
92
97
|
match index {
|
|
93
98
|
0 => out.set_extension("src.zip"),
|
|
94
99
|
index => out.set_extension(format!("{index}.src.zip")),
|
|
@@ -109,7 +114,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
109
114
|
)?;
|
|
110
115
|
|
|
111
116
|
if !written {
|
|
112
|
-
eprintln!("skipped {
|
|
117
|
+
eprintln!("skipped {} (no files found)", orig_path.display());
|
|
113
118
|
fs::remove_file(&out)?;
|
|
114
119
|
continue;
|
|
115
120
|
} else {
|
|
@@ -8,7 +8,8 @@ use crate::config::Config;
|
|
|
8
8
|
|
|
9
9
|
pub fn make_command(command: Command) -> Command {
|
|
10
10
|
command
|
|
11
|
-
.about("Delete a release file.")
|
|
11
|
+
.about("[DEPRECATED] Delete a release file.")
|
|
12
|
+
.hide(true)
|
|
12
13
|
// Backward compatibility with `releases files <VERSION>` commands.
|
|
13
14
|
.arg(Arg::new("version").long("version").hide(true))
|
|
14
15
|
.arg(
|
|
@@ -6,7 +6,8 @@ use crate::{api::Api, config::Config, utils::formatting::Table};
|
|
|
6
6
|
|
|
7
7
|
pub fn make_command(command: Command) -> Command {
|
|
8
8
|
command
|
|
9
|
-
.about("List all release files.")
|
|
9
|
+
.about("[DEPRECATED] List all release files.")
|
|
10
|
+
.hide(true)
|
|
10
11
|
// Backward compatibility with `releases files <VERSION>` commands.
|
|
11
12
|
.arg(Arg::new("version").long("version").hide(true))
|
|
12
13
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
use anyhow::Result;
|
|
2
2
|
use clap::{ArgMatches, Command};
|
|
3
|
+
use console::style;
|
|
3
4
|
|
|
4
5
|
use crate::utils::args::ArgExt;
|
|
5
6
|
|
|
@@ -25,7 +26,8 @@ pub fn make_command(mut command: Command) -> Command {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
command = command
|
|
28
|
-
.about("Manage release artifacts.")
|
|
29
|
+
.about("[DEPRECATED] Manage release artifacts.")
|
|
30
|
+
.hide(true)
|
|
29
31
|
.subcommand_required(true)
|
|
30
32
|
.arg_required_else_help(true)
|
|
31
33
|
.org_arg()
|
|
@@ -42,6 +44,9 @@ pub fn make_command(mut command: Command) -> Command {
|
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
47
|
+
eprintln!("{}", style("⚠ DEPRECATION NOTICE: This functionality will be removed in a future version of `sentry-cli`. \
|
|
48
|
+
Use the `sourcemaps` command instead.").yellow());
|
|
49
|
+
|
|
45
50
|
macro_rules! execute_subcommand {
|
|
46
51
|
($name:ident) => {{
|
|
47
52
|
if let Some(sub_matches) =
|
|
@@ -24,7 +24,8 @@ use crate::utils::progress::ProgressBarMode;
|
|
|
24
24
|
|
|
25
25
|
pub fn make_command(command: Command) -> Command {
|
|
26
26
|
command
|
|
27
|
-
.about("Upload files for a release.")
|
|
27
|
+
.about("[DEPRECATED] Upload files for a release.")
|
|
28
|
+
.hide(true)
|
|
28
29
|
// Backward compatibility with `releases files <VERSION>` commands.
|
|
29
30
|
.arg(Arg::new("version").long("version").hide(true))
|
|
30
31
|
.arg(
|
|
@@ -12,7 +12,7 @@ use crate::config::Config;
|
|
|
12
12
|
use crate::constants::DEFAULT_MAX_WAIT;
|
|
13
13
|
use crate::utils::args::{validate_distribution, ArgExt};
|
|
14
14
|
use crate::utils::file_search::ReleaseFileSearch;
|
|
15
|
-
use crate::utils::file_upload::UploadContext;
|
|
15
|
+
use crate::utils::file_upload::{SourceFile, UploadContext};
|
|
16
16
|
use crate::utils::sourcemaps::SourceMapProcessor;
|
|
17
17
|
|
|
18
18
|
pub fn make_command(command: Command) -> Command {
|
|
@@ -92,16 +92,16 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
92
92
|
&bundle_url,
|
|
93
93
|
ReleaseFileSearch::collect_file(bundle_path.clone())?,
|
|
94
94
|
);
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
ReleaseFileSearch::collect_file(sourcemap_path)?,
|
|
98
|
-
);
|
|
95
|
+
|
|
96
|
+
let sourcemap_match = ReleaseFileSearch::collect_file(sourcemap_path.clone())?;
|
|
99
97
|
|
|
100
98
|
if let Ok(ram_bundle) = RamBundle::parse_unbundle_from_path(&bundle_path) {
|
|
101
99
|
debug!("File RAM bundle found, extracting its contents...");
|
|
102
|
-
|
|
100
|
+
let sourcemap_source = SourceFile::from_release_file_match(&sourcemap_url, sourcemap_match);
|
|
101
|
+
processor.unpack_ram_bundle(&ram_bundle, &bundle_url, &sourcemap_source)?;
|
|
103
102
|
} else {
|
|
104
103
|
debug!("Non-file bundle found");
|
|
104
|
+
processor.add(&sourcemap_url, sourcemap_match);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
processor.rewrite(&[base.to_str().unwrap()])?;
|
|
@@ -20,9 +20,10 @@ pub fn make_command(command: Command) -> Command {
|
|
|
20
20
|
.arg(
|
|
21
21
|
Arg::new("started")
|
|
22
22
|
.long("started")
|
|
23
|
+
.hide(true)
|
|
23
24
|
.value_parser(get_timestamp)
|
|
24
25
|
.value_name("TIMESTAMP")
|
|
25
|
-
.help("
|
|
26
|
+
.help("[DEPRECATED] This value is ignored."),
|
|
26
27
|
)
|
|
27
28
|
.arg(
|
|
28
29
|
Arg::new("released")
|
|
@@ -38,13 +39,19 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
|
|
|
38
39
|
let api = Api::current();
|
|
39
40
|
let version = matches.get_one::<String>("version").unwrap();
|
|
40
41
|
|
|
42
|
+
if matches.get_one::<DateTime<Utc>>("started").is_some() {
|
|
43
|
+
log::warn!(
|
|
44
|
+
"The --started flag is deprecated. Its value is ignored, \
|
|
45
|
+
and the argument will be completely removed in a future version."
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
41
49
|
api.authenticated()?.update_release(
|
|
42
50
|
&config.get_org(matches)?,
|
|
43
51
|
version,
|
|
44
52
|
&UpdatedRelease {
|
|
45
53
|
projects: config.get_projects(matches).ok(),
|
|
46
54
|
url: matches.get_one::<String>("url").cloned(),
|
|
47
|
-
date_started: matches.get_one::<DateTime<Utc>>("started").copied(),
|
|
48
55
|
date_released: Some(
|
|
49
56
|
matches
|
|
50
57
|
.get_one::<DateTime<Utc>>("released")
|
|
@@ -16,7 +16,8 @@ use super::resolve::print_source;
|
|
|
16
16
|
|
|
17
17
|
pub fn make_command(command: Command) -> Command {
|
|
18
18
|
command
|
|
19
|
-
.about("Explain why sourcemaps are not working for a given event.")
|
|
19
|
+
.about("[DEPRECATED] Explain why sourcemaps are not working for a given event.")
|
|
20
|
+
.hide(true)
|
|
20
21
|
.alias("why")
|
|
21
22
|
.arg(
|
|
22
23
|
Arg::new("event")
|
|
@@ -13,7 +13,7 @@ use crate::config::Config;
|
|
|
13
13
|
use crate::constants::DEFAULT_MAX_WAIT;
|
|
14
14
|
use crate::utils::args::validate_distribution;
|
|
15
15
|
use crate::utils::file_search::ReleaseFileSearch;
|
|
16
|
-
use crate::utils::file_upload::UploadContext;
|
|
16
|
+
use crate::utils::file_upload::{SourceFile, UploadContext};
|
|
17
17
|
use crate::utils::fs::path_as_url;
|
|
18
18
|
use crate::utils::sourcemaps::SourceMapProcessor;
|
|
19
19
|
|
|
@@ -303,21 +303,23 @@ fn process_sources_from_bundle(
|
|
|
303
303
|
&bundle_url,
|
|
304
304
|
ReleaseFileSearch::collect_file(bundle_path.clone())?,
|
|
305
305
|
);
|
|
306
|
-
|
|
307
|
-
&sourcemap_url,
|
|
308
|
-
ReleaseFileSearch::collect_file(sourcemap_path)?,
|
|
309
|
-
);
|
|
306
|
+
let sourcemap_match = ReleaseFileSearch::collect_file(sourcemap_path)?;
|
|
310
307
|
|
|
311
308
|
if let Ok(ram_bundle) = sourcemap::ram_bundle::RamBundle::parse_unbundle_from_path(&bundle_path)
|
|
312
309
|
{
|
|
313
310
|
debug!("File RAM bundle found, extracting its contents...");
|
|
314
311
|
// For file ("unbundle") RAM bundles we need to explicitly unpack it, otherwise we cannot detect it
|
|
315
312
|
// reliably inside "processor.rewrite()"
|
|
316
|
-
|
|
313
|
+
|
|
314
|
+
let sourcemap_source = SourceFile::from_release_file_match(&sourcemap_url, sourcemap_match);
|
|
315
|
+
processor.unpack_ram_bundle(&ram_bundle, &bundle_url, &sourcemap_source)?;
|
|
317
316
|
} else if sourcemap::ram_bundle::RamBundle::parse_indexed_from_path(&bundle_path).is_ok() {
|
|
318
317
|
debug!("Indexed RAM bundle found");
|
|
318
|
+
let sourcemap_source = SourceFile::from_release_file_match(&sourcemap_url, sourcemap_match);
|
|
319
|
+
processor.unpack_indexed_ram_bundles(&sourcemap_source)?;
|
|
319
320
|
} else {
|
|
320
321
|
warn!("Regular bundle found");
|
|
322
|
+
processor.add(&sourcemap_url, sourcemap_match);
|
|
321
323
|
}
|
|
322
324
|
|
|
323
325
|
let mut prefixes = get_prefixes_from_args(matches);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
//! This module implements config access.
|
|
2
2
|
use std::env;
|
|
3
|
+
use std::env::VarError;
|
|
3
4
|
use std::fs;
|
|
4
5
|
use std::fs::OpenOptions;
|
|
5
6
|
use std::io;
|
|
7
|
+
use std::num::ParseIntError;
|
|
6
8
|
use std::path::{Path, PathBuf};
|
|
7
9
|
use std::sync::Arc;
|
|
8
10
|
|
|
@@ -26,6 +28,9 @@ use crate::utils::http::is_absolute_url;
|
|
|
26
28
|
#[cfg(target_os = "macos")]
|
|
27
29
|
use crate::utils::xcode;
|
|
28
30
|
|
|
31
|
+
const MAX_RETRIES_ENV_VAR: &str = "SENTRY_HTTP_MAX_RETRIES";
|
|
32
|
+
const MAX_RETRIES_INI_KEY: &str = "max_retries";
|
|
33
|
+
|
|
29
34
|
/// Represents the auth information
|
|
30
35
|
#[derive(Debug, Clone)]
|
|
31
36
|
pub enum Auth {
|
|
@@ -48,6 +53,7 @@ pub struct Config {
|
|
|
48
53
|
cached_log_level: log::LevelFilter,
|
|
49
54
|
cached_vcs_remote: String,
|
|
50
55
|
cached_token_data: Option<AuthTokenPayload>,
|
|
56
|
+
max_retries: u32,
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
impl Config {
|
|
@@ -86,6 +92,7 @@ impl Config {
|
|
|
86
92
|
cached_headers: get_default_headers(&ini),
|
|
87
93
|
cached_log_level: get_default_log_level(&ini),
|
|
88
94
|
cached_vcs_remote: get_default_vcs_remote(&ini),
|
|
95
|
+
max_retries: get_max_retries(&ini),
|
|
89
96
|
ini,
|
|
90
97
|
cached_token_data: token_embedded_data,
|
|
91
98
|
}
|
|
@@ -462,14 +469,9 @@ impl Config {
|
|
|
462
469
|
.unwrap_or(DEFAULT_MAX_DIF_ITEM_SIZE)
|
|
463
470
|
}
|
|
464
471
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
} else if let Some(val) = self.ini.get_from(Some("http"), "max_retries") {
|
|
469
|
-
Ok(val.parse()?)
|
|
470
|
-
} else {
|
|
471
|
-
Ok(DEFAULT_RETRIES)
|
|
472
|
-
}
|
|
472
|
+
/// Returns the configured maximum number of retries for failed HTTP requests.
|
|
473
|
+
pub fn max_retries(&self) -> u32 {
|
|
474
|
+
self.max_retries
|
|
473
475
|
}
|
|
474
476
|
|
|
475
477
|
/// Return the DSN
|
|
@@ -520,6 +522,50 @@ impl Config {
|
|
|
520
522
|
}
|
|
521
523
|
}
|
|
522
524
|
|
|
525
|
+
/// Obtains the maximum number of retries from the environment or the ini file.
|
|
526
|
+
/// Environment variable takes precedence over the ini file. If neither is set,
|
|
527
|
+
/// the default value is returned.
|
|
528
|
+
fn get_max_retries(ini: &Ini) -> u32 {
|
|
529
|
+
match max_retries_from_env() {
|
|
530
|
+
Ok(Some(val)) => return val,
|
|
531
|
+
Ok(None) => (),
|
|
532
|
+
Err(e) => {
|
|
533
|
+
warn!(
|
|
534
|
+
"Ignoring invalid {MAX_RETRIES_ENV_VAR} environment variable: {}",
|
|
535
|
+
e
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
match max_retries_from_ini(ini) {
|
|
541
|
+
Ok(Some(val)) => return val,
|
|
542
|
+
Ok(None) => (),
|
|
543
|
+
Err(e) => {
|
|
544
|
+
warn!("Ignoring invalid {MAX_RETRIES_INI_KEY} ini key: {}", e);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
DEFAULT_RETRIES
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/// Computes the maximum number of retries from the `SENTRY_HTTP_MAX_RETRIES` environment variable.
|
|
552
|
+
/// Returns `Ok(None)` if the environment variable is not set, other errors are returned as is.
|
|
553
|
+
fn max_retries_from_env() -> Result<Option<u32>> {
|
|
554
|
+
match env::var(MAX_RETRIES_ENV_VAR) {
|
|
555
|
+
Ok(val) => Ok(Some(val.parse()?)),
|
|
556
|
+
Err(VarError::NotPresent) => Ok(None),
|
|
557
|
+
Err(e) => Err(e.into()),
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/// Computes the maximum number of retries from the `max_retries` ini key.
|
|
562
|
+
/// Returns `Ok(None)` if the key is not set, other errors are returned as is.
|
|
563
|
+
fn max_retries_from_ini(ini: &Ini) -> Result<Option<u32>, ParseIntError> {
|
|
564
|
+
ini.get_from(Some("http"), MAX_RETRIES_INI_KEY)
|
|
565
|
+
.map(|val| val.parse())
|
|
566
|
+
.transpose()
|
|
567
|
+
}
|
|
568
|
+
|
|
523
569
|
fn warn_about_conflicting_urls(token_url: &str, manually_configured_url: Option<&str>) {
|
|
524
570
|
if let Some(manually_configured_url) = manually_configured_url {
|
|
525
571
|
if manually_configured_url != token_url {
|
|
@@ -672,6 +718,7 @@ impl Clone for Config {
|
|
|
672
718
|
cached_log_level: self.cached_log_level,
|
|
673
719
|
cached_vcs_remote: self.cached_vcs_remote.clone(),
|
|
674
720
|
cached_token_data: self.cached_token_data.clone(),
|
|
721
|
+
max_retries: self.max_retries,
|
|
675
722
|
}
|
|
676
723
|
}
|
|
677
724
|
}
|
|
@@ -757,6 +804,7 @@ mod tests {
|
|
|
757
804
|
cached_log_level: LevelFilter::Off,
|
|
758
805
|
cached_vcs_remote: String::new(),
|
|
759
806
|
cached_token_data: None,
|
|
807
|
+
max_retries: 0,
|
|
760
808
|
};
|
|
761
809
|
|
|
762
810
|
assert_eq!(
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//! Searches, processes and uploads release files.
|
|
2
2
|
use std::collections::{BTreeMap, HashMap};
|
|
3
|
+
use std::ffi::OsStr;
|
|
3
4
|
use std::fmt::{self, Display};
|
|
4
5
|
use std::io::BufWriter;
|
|
5
6
|
use std::path::PathBuf;
|
|
@@ -16,6 +17,7 @@ use rayon::ThreadPoolBuilder;
|
|
|
16
17
|
use sentry::types::DebugId;
|
|
17
18
|
use sha1_smol::Digest;
|
|
18
19
|
use symbolic::common::ByteView;
|
|
20
|
+
use symbolic::debuginfo::js;
|
|
19
21
|
use symbolic::debuginfo::sourcebundle::{
|
|
20
22
|
SourceBundleErrorKind, SourceBundleWriter, SourceFileInfo, SourceFileType,
|
|
21
23
|
};
|
|
@@ -29,6 +31,8 @@ use crate::utils::chunks::{upload_chunks, Chunk, ASSEMBLE_POLL_INTERVAL};
|
|
|
29
31
|
use crate::utils::fs::{get_sha1_checksum, get_sha1_checksums, TempFile};
|
|
30
32
|
use crate::utils::progress::{ProgressBar, ProgressBarMode, ProgressStyle};
|
|
31
33
|
|
|
34
|
+
use super::file_search::ReleaseFileMatch;
|
|
35
|
+
|
|
32
36
|
/// Fallback concurrency for release file uploads.
|
|
33
37
|
static DEFAULT_CONCURRENCY: usize = 4;
|
|
34
38
|
|
|
@@ -239,6 +243,68 @@ pub struct SourceFile {
|
|
|
239
243
|
}
|
|
240
244
|
|
|
241
245
|
impl SourceFile {
|
|
246
|
+
pub fn from_release_file_match(url: &str, mut file: ReleaseFileMatch) -> SourceFile {
|
|
247
|
+
let (ty, debug_id) = if sourcemap::is_sourcemap_slice(&file.contents) {
|
|
248
|
+
(
|
|
249
|
+
SourceFileType::SourceMap,
|
|
250
|
+
std::str::from_utf8(&file.contents)
|
|
251
|
+
.ok()
|
|
252
|
+
.and_then(js::discover_sourcemap_embedded_debug_id),
|
|
253
|
+
)
|
|
254
|
+
} else if file
|
|
255
|
+
.path
|
|
256
|
+
.file_name()
|
|
257
|
+
.and_then(OsStr::to_str)
|
|
258
|
+
.map(|x| x.ends_with("bundle"))
|
|
259
|
+
.unwrap_or(false)
|
|
260
|
+
&& sourcemap::ram_bundle::is_ram_bundle_slice(&file.contents)
|
|
261
|
+
{
|
|
262
|
+
(SourceFileType::IndexedRamBundle, None)
|
|
263
|
+
} else if is_hermes_bytecode(&file.contents) {
|
|
264
|
+
// This is actually a big hack:
|
|
265
|
+
// For the react-native Hermes case, we skip uploading the bytecode bundle,
|
|
266
|
+
// and rather flag it as an empty "minified source". That way, it
|
|
267
|
+
// will get a SourceMap reference, and the server side processor
|
|
268
|
+
// should deal with it accordingly.
|
|
269
|
+
file.contents.clear();
|
|
270
|
+
(SourceFileType::MinifiedSource, None)
|
|
271
|
+
} else {
|
|
272
|
+
// Here, we use MinifiedSource for historical reasons. We used to guess whether
|
|
273
|
+
// a JS file was a minified file or a source file, and we would treat these files
|
|
274
|
+
// differently when uploading or injecting them. However, the desired behavior is
|
|
275
|
+
// and has always been to treat all JS files the same, since users should be
|
|
276
|
+
// responsible for providing the file paths for only files they would like to have
|
|
277
|
+
// uploaded or injected. The minified file guessing furthermore was not reliable,
|
|
278
|
+
// since minification is not a necessary step in the JS build process.
|
|
279
|
+
//
|
|
280
|
+
// We use MinifiedSource here rather than Source because we want to treat all JS
|
|
281
|
+
// files the way we used to treat minified files only. To use Source, we would need
|
|
282
|
+
// to analyze all possible code paths that check this value, and update those as
|
|
283
|
+
// well. To keep the change minimal, we use MinifiedSource here.
|
|
284
|
+
(
|
|
285
|
+
SourceFileType::MinifiedSource,
|
|
286
|
+
std::str::from_utf8(&file.contents)
|
|
287
|
+
.ok()
|
|
288
|
+
.and_then(js::discover_debug_id),
|
|
289
|
+
)
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
let mut source_file = SourceFile {
|
|
293
|
+
url: url.into(),
|
|
294
|
+
path: file.path,
|
|
295
|
+
contents: file.contents.into(),
|
|
296
|
+
ty,
|
|
297
|
+
headers: BTreeMap::new(),
|
|
298
|
+
messages: vec![],
|
|
299
|
+
already_uploaded: false,
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
if let Some(debug_id) = debug_id {
|
|
303
|
+
source_file.set_debug_id(debug_id.to_string());
|
|
304
|
+
}
|
|
305
|
+
source_file
|
|
306
|
+
}
|
|
307
|
+
|
|
242
308
|
/// Calculates and returns the SHA1 checksum of the file.
|
|
243
309
|
pub fn checksum(&self) -> Result<Digest> {
|
|
244
310
|
get_sha1_checksum(&**self.contents)
|
|
@@ -753,6 +819,13 @@ fn print_upload_context_details(context: &UploadContext) {
|
|
|
753
819
|
);
|
|
754
820
|
}
|
|
755
821
|
|
|
822
|
+
fn is_hermes_bytecode(slice: &[u8]) -> bool {
|
|
823
|
+
// The hermes bytecode format magic is defined here:
|
|
824
|
+
// https://github.com/facebook/hermes/blob/5243222ef1d92b7393d00599fc5cff01d189a88a/include/hermes/BCGen/HBC/BytecodeFileFormat.h#L24-L25
|
|
825
|
+
const HERMES_MAGIC: [u8; 8] = [0xC6, 0x1F, 0xBC, 0x03, 0xC1, 0x03, 0x19, 0x1F];
|
|
826
|
+
slice.starts_with(&HERMES_MAGIC)
|
|
827
|
+
}
|
|
828
|
+
|
|
756
829
|
#[cfg(test)]
|
|
757
830
|
mod tests {
|
|
758
831
|
use sha1_smol::Sha1;
|