sentry-cli 3.3.4__tar.gz → 3.4.0__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.
Files changed (180) hide show
  1. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/Cargo.lock +9 -30
  2. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/Cargo.toml +3 -3
  3. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/PKG-INFO +1 -1
  4. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/sentry_cli.egg-info/PKG-INFO +1 -1
  5. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/snapshots.rs +47 -0
  6. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/mod.rs +2 -1
  7. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/build/snapshots.rs +121 -88
  8. sentry_cli-3.4.0/src/commands/debug_files/bundle_jvm.rs +250 -0
  9. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/file_search.rs +12 -5
  10. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/logging.rs +4 -8
  11. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/progress.rs +2 -9
  12. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/source_bundle.rs +58 -32
  13. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/sourcemaps.rs +6 -1
  14. sentry_cli-3.3.4/src/commands/debug_files/bundle_jvm.rs +0 -102
  15. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/LICENSE +0 -0
  16. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/MANIFEST.in +0 -0
  17. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/README.md +0 -0
  18. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/AGENTS.md +0 -0
  19. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/CLAUDE.md +0 -0
  20. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/Cargo.toml +0 -0
  21. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/build.rs +0 -0
  22. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Package.swift +0 -0
  23. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/AssetCatalogParser/AssetCatalogReader.swift +0 -0
  24. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/include/safeValueForKey.h +0 -0
  25. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Sources/ObjcSupport/safeValueForKey.m +0 -0
  26. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/AssetCatalogParserTests.swift +0 -0
  27. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Info.plist +0 -0
  28. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/native/swift/AssetCatalogParser/Tests/AssetCatalogParserTests/Resources/test.xcarchive/Products/Applications/DemoApp.app/Assets.car +0 -0
  29. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/src/asset_catalog.rs +0 -0
  30. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/apple-catalog-parsing/src/lib.rs +0 -0
  31. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/build.rs +0 -0
  32. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/pyproject.toml +0 -0
  33. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/sentry_cli.egg-info/SOURCES.txt +0 -0
  34. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/sentry_cli.egg-info/dependency_links.txt +0 -0
  35. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/sentry_cli.egg-info/top_level.txt +0 -0
  36. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/setup.cfg +0 -0
  37. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/setup.py +0 -0
  38. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/AGENTS.md +0 -0
  39. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/CLAUDE.md +0 -0
  40. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/connection_manager.rs +0 -0
  41. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/artifact.rs +0 -0
  42. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/build.rs +0 -0
  43. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/compression.rs +0 -0
  44. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/dif.rs +0 -0
  45. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/file_state.rs +0 -0
  46. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/hash_algorithm.rs +0 -0
  47. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/mod.rs +0 -0
  48. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/upload/mod.rs +0 -0
  49. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/chunking/upload/options.rs +0 -0
  50. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/code_mappings.rs +0 -0
  51. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/deploy.rs +0 -0
  52. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/data_types/mod.rs +0 -0
  53. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/encoding.rs +0 -0
  54. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/envelopes_api.rs +0 -0
  55. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/errors/api_error.rs +0 -0
  56. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/errors/mod.rs +0 -0
  57. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/errors/sentry_error.rs +0 -0
  58. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/pagination.rs +0 -0
  59. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/api/serialization.rs +0 -0
  60. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/bashsupport.sh +0 -0
  61. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/bash_hook.rs +0 -0
  62. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/build/download.rs +0 -0
  63. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/build/mod.rs +0 -0
  64. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/build/upload.rs +0 -0
  65. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/code_mappings/mod.rs +0 -0
  66. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/code_mappings/upload.rs +0 -0
  67. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/dart_symbol_map/mod.rs +0 -0
  68. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/dart_symbol_map/upload.rs +0 -0
  69. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/bundle_sources.rs +0 -0
  70. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/check.rs +0 -0
  71. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/find.rs +0 -0
  72. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/mod.rs +0 -0
  73. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/print_sources.rs +0 -0
  74. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/debug_files/upload.rs +0 -0
  75. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/deploys/list.rs +0 -0
  76. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/deploys/mod.rs +0 -0
  77. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/deploys/new.rs +0 -0
  78. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/derive_parser.rs +0 -0
  79. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/events/list.rs +0 -0
  80. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/events/mod.rs +0 -0
  81. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/info.rs +0 -0
  82. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/issues/list.rs +0 -0
  83. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/issues/mod.rs +0 -0
  84. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/issues/mute.rs +0 -0
  85. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/issues/resolve.rs +0 -0
  86. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/issues/unresolve.rs +0 -0
  87. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/login.rs +0 -0
  88. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/logs/list.rs +0 -0
  89. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/logs/mod.rs +0 -0
  90. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/mod.rs +0 -0
  91. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/monitors/list.rs +0 -0
  92. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/monitors/mod.rs +0 -0
  93. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/monitors/run.rs +0 -0
  94. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/organizations/list.rs +0 -0
  95. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/organizations/mod.rs +0 -0
  96. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/proguard/mod.rs +0 -0
  97. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/proguard/upload.rs +0 -0
  98. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/proguard/uuid.rs +0 -0
  99. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/projects/list.rs +0 -0
  100. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/projects/mod.rs +0 -0
  101. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/react_native/gradle.rs +0 -0
  102. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/react_native/mod.rs +0 -0
  103. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/react_native/xcode.rs +0 -0
  104. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/archive.rs +0 -0
  105. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/delete.rs +0 -0
  106. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/finalize.rs +0 -0
  107. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/info.rs +0 -0
  108. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/list.rs +0 -0
  109. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/mod.rs +0 -0
  110. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/new.rs +0 -0
  111. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/propose_version.rs +0 -0
  112. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/restore.rs +0 -0
  113. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/releases/set_commits.rs +0 -0
  114. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/repos/list.rs +0 -0
  115. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/repos/mod.rs +0 -0
  116. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_envelope.rs +0 -0
  117. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_event.rs +0 -0
  118. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_metric/common_args.rs +0 -0
  119. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_metric/increment.rs +0 -0
  120. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_metric/mod.rs +0 -0
  121. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/send_metric/set.rs +0 -0
  122. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/sourcemaps/inject.rs +0 -0
  123. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/sourcemaps/mod.rs +0 -0
  124. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/sourcemaps/resolve.rs +0 -0
  125. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/sourcemaps/upload.rs +0 -0
  126. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/uninstall.rs +0 -0
  127. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/update.rs +0 -0
  128. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/upload_dif.rs +0 -0
  129. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/upload_dsym.rs +0 -0
  130. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/commands/upload_proguard.rs +0 -0
  131. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/config.rs +0 -0
  132. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/constants.rs +0 -0
  133. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/main.rs +0 -0
  134. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/android.rs +0 -0
  135. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/args.rs +0 -0
  136. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/auth_token_impl.rs +0 -0
  137. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/error.rs +0 -0
  138. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/mod.rs +0 -0
  139. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/org_auth_token.rs +0 -0
  140. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/redacting.rs +0 -0
  141. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/test.rs +0 -0
  142. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/auth_token/user_auth_token.rs +0 -0
  143. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/build/apple.rs +0 -0
  144. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/build/mod.rs +0 -0
  145. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/build/normalize.rs +0 -0
  146. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/build/validation.rs +0 -0
  147. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/build_vcs.rs +0 -0
  148. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/chunks/mod.rs +0 -0
  149. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/chunks/options.rs +0 -0
  150. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/chunks/types.rs +0 -0
  151. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/chunks/upload.rs +0 -0
  152. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/ci.rs +0 -0
  153. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/cordova.rs +0 -0
  154. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/dif.rs +0 -0
  155. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/dif_upload/error.rs +0 -0
  156. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/dif_upload/mod.rs +0 -0
  157. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/event.rs +0 -0
  158. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/file_upload.rs +0 -0
  159. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/formatting.rs +0 -0
  160. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/fs.rs +0 -0
  161. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/http.rs +0 -0
  162. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/mod.rs +0 -0
  163. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/non_empty.rs +0 -0
  164. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/proguard/mapping.rs +0 -0
  165. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/proguard/mod.rs +0 -0
  166. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/proguard/upload.rs +0 -0
  167. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/releases.rs +0 -0
  168. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/retry.rs +0 -0
  169. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_default_twenty.snap +0 -0
  170. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_ignore_missing.snap +0 -0
  171. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_base.snap +0 -0
  172. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/snapshots/sentry_cli__utils__vcs__tests__generate_patch_set_previous_commit.snap +0 -0
  173. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/snapshots/sentry_cli__utils__vcs__tests__get_commits_from_git.snap +0 -0
  174. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/sourcemaps/inject.rs +0 -0
  175. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/system.rs +0 -0
  176. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/ui.rs +0 -0
  177. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/update.rs +0 -0
  178. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/value_parsers.rs +0 -0
  179. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/vcs.rs +0 -0
  180. {sentry_cli-3.3.4 → sentry_cli-3.4.0}/src/utils/xcode.rs +0 -0
@@ -206,28 +206,6 @@ dependencies = [
206
206
  "tokio",
207
207
  ]
208
208
 
209
- [[package]]
210
- name = "async-stream"
211
- version = "0.3.6"
212
- source = "registry+https://github.com/rust-lang/crates.io-index"
213
- checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
214
- dependencies = [
215
- "async-stream-impl",
216
- "futures-core",
217
- "pin-project-lite",
218
- ]
219
-
220
- [[package]]
221
- name = "async-stream-impl"
222
- version = "0.3.6"
223
- source = "registry+https://github.com/rust-lang/crates.io-index"
224
- checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
225
- dependencies = [
226
- "proc-macro2",
227
- "quote",
228
- "syn",
229
- ]
230
-
231
209
  [[package]]
232
210
  name = "atomic-waker"
233
211
  version = "1.1.2"
@@ -2322,12 +2300,11 @@ dependencies = [
2322
2300
 
2323
2301
  [[package]]
2324
2302
  name = "objectstore-client"
2325
- version = "0.1.2"
2303
+ version = "0.1.6"
2326
2304
  source = "registry+https://github.com/rust-lang/crates.io-index"
2327
- checksum = "033eedf125e31b30962c0172842e964fc9983bbccd99d9ff033e7e413946861c"
2305
+ checksum = "f99caa869461b61decd1985c029d7e1462d1bde8e2448040db27d567165fcc1e"
2328
2306
  dependencies = [
2329
2307
  "async-compression",
2330
- "async-stream",
2331
2308
  "bytes",
2332
2309
  "futures-util",
2333
2310
  "infer",
@@ -2346,9 +2323,9 @@ dependencies = [
2346
2323
 
2347
2324
  [[package]]
2348
2325
  name = "objectstore-types"
2349
- version = "0.1.2"
2326
+ version = "0.1.6"
2350
2327
  source = "registry+https://github.com/rust-lang/crates.io-index"
2351
- checksum = "956cbdef3971ea108a15e5248625d6229870da3a3c637b6e7aada213526f8014"
2328
+ checksum = "c375bccef8773d1739eabb7e2b1bbd7e9a9071c8f9557e3b50dce7220e8c8736"
2352
2329
  dependencies = [
2353
2330
  "http",
2354
2331
  "humantime",
@@ -3230,9 +3207,9 @@ dependencies = [
3230
3207
 
3231
3208
  [[package]]
3232
3209
  name = "rustls-webpki"
3233
- version = "0.103.8"
3210
+ version = "0.103.10"
3234
3211
  source = "registry+https://github.com/rust-lang/crates.io-index"
3235
- checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
3212
+ checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef"
3236
3213
  dependencies = [
3237
3214
  "ring",
3238
3215
  "rustls-pki-types",
@@ -3345,6 +3322,7 @@ version = "0.8.0"
3345
3322
  source = "registry+https://github.com/rust-lang/crates.io-index"
3346
3323
  checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
3347
3324
  dependencies = [
3325
+ "serde",
3348
3326
  "zeroize",
3349
3327
  ]
3350
3328
 
@@ -3414,7 +3392,7 @@ dependencies = [
3414
3392
 
3415
3393
  [[package]]
3416
3394
  name = "sentry-cli"
3417
- version = "3.3.4"
3395
+ version = "3.4.0"
3418
3396
  dependencies = [
3419
3397
  "anyhow",
3420
3398
  "anylog",
@@ -4142,6 +4120,7 @@ dependencies = [
4142
4120
  "bytes",
4143
4121
  "futures-core",
4144
4122
  "futures-sink",
4123
+ "futures-util",
4145
4124
  "pin-project-lite",
4146
4125
  "tokio",
4147
4126
  ]
@@ -1,7 +1,7 @@
1
1
  [package]
2
2
  build = "build.rs"
3
3
  name = "sentry-cli"
4
- version = "3.3.4"
4
+ version = "3.4.0"
5
5
  edition = "2021"
6
6
  rust-version = "1.91"
7
7
 
@@ -44,7 +44,7 @@ java-properties = "2.0.0"
44
44
  lazy_static = "1.4.0"
45
45
  libc = "0.2.139"
46
46
  log = { version = "0.4.17", features = ["std"] }
47
- objectstore-client = { version = "0.1.2" , default-features = false, features = ["native-tls"] }
47
+ objectstore-client = { version = "0.1.6" , default-features = false, features = ["native-tls"] }
48
48
  open = "3.2.0"
49
49
  parking_lot = "0.12.1"
50
50
  percent-encoding = "2.2.0"
@@ -79,7 +79,7 @@ zip = "2.4.2"
79
79
  data-encoding = "2.3.3"
80
80
  magic_string = "0.3.4"
81
81
  chrono-tz = "0.8.4"
82
- secrecy = "0.8.0"
82
+ secrecy = { version = "0.8.0", features = ["serde"] }
83
83
  lru = "0.16.3"
84
84
  backon = { version = "1.5.2", features = ["std", "std-blocking-sleep"] }
85
85
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry_cli
3
- Version: 3.3.4
3
+ Version: 3.4.0
4
4
  Summary: A command line utility to work with Sentry.
5
5
  Home-page: https://github.com/getsentry/sentry-cli
6
6
  Author: Sentry
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sentry_cli
3
- Version: 3.3.4
3
+ Version: 3.4.0
4
4
  Summary: A command line utility to work with Sentry.
5
5
  Home-page: https://github.com/getsentry/sentry-cli
6
6
  Author: Sentry
@@ -25,6 +25,14 @@ pub struct CreateSnapshotResponse {
25
25
  pub struct SnapshotsManifest<'a> {
26
26
  pub app_id: String,
27
27
  pub images: HashMap<String, ImageMetadata>,
28
+ /// If set, Sentry will only report images as changed if their difference %
29
+ /// is greater than this value (e.g. 0.01 = only report changes >= 1%).
30
+ #[serde(skip_serializing_if = "Option::is_none")]
31
+ pub diff_threshold: Option<f64>,
32
+ /// When true, this upload contains only a subset of images.
33
+ /// Removals and renames will not be detected on PRs.
34
+ #[serde(skip_serializing_if = "std::ops::Not::not")]
35
+ pub selective: bool,
28
36
  #[serde(flatten)]
29
37
  pub vcs_info: VcsInfo<'a>,
30
38
  }
@@ -55,6 +63,45 @@ mod tests {
55
63
 
56
64
  use serde_json::json;
57
65
 
66
+ fn empty_vcs_info() -> VcsInfo<'static> {
67
+ VcsInfo {
68
+ head_sha: None,
69
+ base_sha: None,
70
+ vcs_provider: "".into(),
71
+ head_repo_name: "".into(),
72
+ base_repo_name: "".into(),
73
+ head_ref: "".into(),
74
+ base_ref: "".into(),
75
+ pr_number: None,
76
+ }
77
+ }
78
+
79
+ #[test]
80
+ fn manifest_omits_selective_when_false() {
81
+ let manifest = SnapshotsManifest {
82
+ app_id: "app".into(),
83
+ images: HashMap::new(),
84
+ diff_threshold: None,
85
+ selective: false,
86
+ vcs_info: empty_vcs_info(),
87
+ };
88
+ let json = serde_json::to_value(&manifest).unwrap();
89
+ assert!(!json.as_object().unwrap().contains_key("selective"));
90
+ }
91
+
92
+ #[test]
93
+ fn manifest_includes_selective_when_true() {
94
+ let manifest = SnapshotsManifest {
95
+ app_id: "app".into(),
96
+ images: HashMap::new(),
97
+ diff_threshold: None,
98
+ selective: true,
99
+ vcs_info: empty_vcs_info(),
100
+ };
101
+ let json = serde_json::to_value(&manifest).unwrap();
102
+ assert_eq!(json["selective"], json!(true));
103
+ }
104
+
58
105
  #[test]
59
106
  fn cli_managed_fields_override_sidecar_fields() {
60
107
  let extra = serde_json::from_value(json!({
@@ -33,7 +33,7 @@ use lazy_static::lazy_static;
33
33
  use log::{debug, info, warn};
34
34
  use parking_lot::Mutex;
35
35
  use regex::{Captures, Regex};
36
- use secrecy::ExposeSecret as _;
36
+ use secrecy::{ExposeSecret as _, SecretString};
37
37
  use serde::de::DeserializeOwned;
38
38
  use serde::{Deserialize, Serialize};
39
39
  use sha1_smol::Digest;
@@ -2065,5 +2065,6 @@ pub struct SnapshotsUploadOptions {
2065
2065
  pub struct ObjectstoreUploadOptions {
2066
2066
  pub url: String,
2067
2067
  pub scopes: Vec<(String, String)>,
2068
+ pub auth_token: Option<SecretString>,
2068
2069
  pub expiration_policy: String,
2069
2070
  }
@@ -9,8 +9,9 @@ use anyhow::{Context as _, Result};
9
9
  use clap::{Arg, ArgMatches, Command};
10
10
  use console::style;
11
11
  use itertools::Itertools as _;
12
- use log::{debug, info, warn};
12
+ use log::{debug, 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};
@@ -50,6 +51,32 @@ pub fn make_command(command: Command) -> Command {
50
51
  .help("The application identifier.")
51
52
  .required(true),
52
53
  )
54
+ .arg(
55
+ Arg::new("diff_threshold")
56
+ .long("diff-threshold")
57
+ .value_name("THRESHOLD")
58
+ .value_parser(|s: &str| {
59
+ let v: f64 = s.parse().map_err(|e| format!("invalid float: {e}"))?;
60
+ if !(0.0..=1.0).contains(&v) {
61
+ return Err("value must be between 0.0 and 1.0".to_owned());
62
+ }
63
+ Ok(v)
64
+ })
65
+ .help(
66
+ "If set, Sentry will only report images as changed if their \
67
+ difference % is greater than this value. \
68
+ Example: 0.01 = only report image changes >= 1%.",
69
+ ),
70
+ )
71
+ .arg(
72
+ Arg::new("selective")
73
+ .long("selective")
74
+ .action(clap::ArgAction::SetTrue)
75
+ .help(
76
+ "Indicates this upload contains only a subset of images. \
77
+ Removals and renames cannot be detected on PRs.",
78
+ ),
79
+ )
53
80
  .git_metadata_args()
54
81
  }
55
82
 
@@ -122,9 +149,15 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
122
149
  let manifest_entries = upload_images(images, &org, &project)?;
123
150
 
124
151
  // Build manifest from discovered images
152
+ let diff_threshold = matches.get_one::<f64>("diff_threshold").copied();
153
+
154
+ let selective = matches.get_flag("selective");
155
+
125
156
  let manifest = SnapshotsManifest {
126
157
  app_id: app_id.clone(),
127
158
  images: manifest_entries,
159
+ diff_threshold,
160
+ selective,
128
161
  vcs_info,
129
162
  };
130
163
 
@@ -230,7 +263,7 @@ fn compute_sha256_hash(path: &Path) -> Result<String> {
230
263
  let mut file = std::fs::File::open(path)
231
264
  .with_context(|| format!("Failed to open image for hashing: {}", path.display()))?;
232
265
  let mut hasher = Sha256::new();
233
- let mut buffer = [0u8; 8192];
266
+ let mut buffer = [0u8; 65536];
234
267
  loop {
235
268
  let bytes_read = file
236
269
  .read(&mut buffer)
@@ -282,6 +315,11 @@ fn read_sidecar_metadata(image_path: &Path) -> Result<HashMap<String, Value>> {
282
315
  })
283
316
  }
284
317
 
318
+ struct PreparedImage {
319
+ path: PathBuf,
320
+ key: String,
321
+ }
322
+
285
323
  fn upload_images(
286
324
  images: Vec<ImageInfo>,
287
325
  org: &str,
@@ -294,33 +332,43 @@ fn upload_images(
294
332
  let expiration = ExpirationPolicy::from_str(&options.objectstore.expiration_policy)
295
333
  .context("Failed to parse expiration policy from upload options")?;
296
334
 
297
- let client = ClientBuilder::new(options.objectstore.url)
298
- .token({
299
- // TODO: replace with auth from `ObjectstoreUploadOptions` when appropriate
300
- let auth = match authenticated_api.auth() {
301
- Auth::Token(token) => token.raw().expose_secret().to_owned(),
302
- };
303
- auth
335
+ let mut builder = ClientBuilder::new(options.objectstore.url);
336
+ if let Some(token) = options.objectstore.auth_token {
337
+ builder = builder.token(token.expose_secret().to_owned());
338
+ }
339
+ let builder = builder;
340
+
341
+ let sentry_token = match authenticated_api.auth() {
342
+ Auth::Token(token) => token.raw().expose_secret().to_owned(),
343
+ };
344
+ let sentry_token = format!("Bearer {sentry_token}")
345
+ .parse()
346
+ // Ignore original error to avoid leaking the token (even though it's invalid)
347
+ .map_err(|_| anyhow::anyhow!("Invalid auth token"))?;
348
+ let client = builder
349
+ .configure_reqwest(|r| {
350
+ let mut headers = http::HeaderMap::new();
351
+ headers.insert(http::header::AUTHORIZATION, sentry_token);
352
+ r.connect_timeout(Duration::from_secs(10))
353
+ .default_headers(headers)
304
354
  })
305
- .configure_reqwest(|r| r.connect_timeout(Duration::from_secs(10)))
306
355
  .build()?;
307
356
 
357
+ let scopes = options.objectstore.scopes;
358
+
359
+ let find_scope = |name: &str| {
360
+ scopes
361
+ .iter()
362
+ .find(|(k, _)| k == name)
363
+ .map(|(_, v)| v.clone())
364
+ };
365
+ let org_id = find_scope("org").context("Missing org in UploadOptions scope")?;
366
+ let project_id = find_scope("project").context("Missing project in UploadOptions scope")?;
367
+
308
368
  let mut scope = Usecase::new("preprod").scope();
309
- let (mut org_id, mut project_id): (Option<String>, Option<String>) = (None, None);
310
- for (key, value) in options.objectstore.scopes.into_iter() {
311
- scope = scope.push(&key, value.clone());
312
- if key == "org" {
313
- org_id = Some(value);
314
- } else if key == "project" {
315
- project_id = Some(value);
316
- }
369
+ for (key, value) in scopes {
370
+ scope = scope.push(&key, value);
317
371
  }
318
- let Some(org_id) = org_id else {
319
- anyhow::bail!("Missing org in UploadOptions scope");
320
- };
321
- let Some(project_id) = project_id else {
322
- anyhow::bail!("Missing project in UploadOptions scope");
323
- };
324
372
 
325
373
  let session = scope.session(&client)?;
326
374
 
@@ -329,46 +377,27 @@ fn upload_images(
329
377
  .build()
330
378
  .context("Failed to create tokio runtime")?;
331
379
 
332
- let mut many_builder = session.many();
333
380
  let mut manifest_entries = HashMap::new();
334
- let mut collisions: HashMap<String, Vec<String>> = HashMap::new();
335
- let mut kept_paths: HashMap<String, String> = HashMap::new();
336
- for image in images {
337
- debug!("Processing image: {}", image.path.display());
338
-
339
- let image_file_name = image
340
- .relative_path
341
- .file_name()
342
- .unwrap_or_default()
343
- .to_string_lossy()
344
- .into_owned();
381
+ let mut duplicates: Vec<String> = Vec::new();
382
+ let mut uploads = Vec::with_capacity(images.len());
383
+
384
+ let hashed_images: Vec<_> = images
385
+ .into_par_iter()
386
+ .map(|image| {
387
+ let hash = compute_sha256_hash(&image.path)?;
388
+ Ok((image, hash))
389
+ })
390
+ .collect::<Result<Vec<_>>>()?;
345
391
 
346
- let relative_path = crate::utils::fs::path_as_url(&image.relative_path);
392
+ for (image, hash) in hashed_images {
393
+ let image_key = crate::utils::fs::path_as_url(&image.relative_path);
347
394
 
348
- if manifest_entries.contains_key(&image_file_name) {
349
- collisions
350
- .entry(image_file_name)
351
- .or_default()
352
- .push(relative_path);
395
+ if manifest_entries.contains_key(&image_key) {
396
+ duplicates.push(image_key);
353
397
  continue;
354
398
  }
355
399
 
356
- let hash = compute_sha256_hash(&image.path)?;
357
- let file = runtime
358
- .block_on(tokio::fs::File::open(&image.path))
359
- .with_context(|| {
360
- format!("Failed to open image for upload: {}", image.path.display())
361
- })?;
362
-
363
400
  let key = format!("{org_id}/{project_id}/{hash}");
364
- info!("Queueing {} as {key}", image.relative_path.display());
365
-
366
- many_builder = many_builder.push(
367
- session
368
- .put_file(file)
369
- .key(&key)
370
- .expiration_policy(expiration),
371
- );
372
401
 
373
402
  let mut extra = read_sidecar_metadata(&image.path).unwrap_or_else(|err| {
374
403
  warn!("Error reading sidecar metadata, ignoring it instead: {err:#}");
@@ -376,48 +405,52 @@ fn upload_images(
376
405
  });
377
406
  extra.insert("content_hash".to_owned(), serde_json::Value::String(hash));
378
407
 
379
- kept_paths.insert(image_file_name.clone(), relative_path);
408
+ uploads.push(PreparedImage {
409
+ path: image.path,
410
+ key,
411
+ });
380
412
  manifest_entries.insert(
381
- image_file_name,
413
+ image_key,
382
414
  ImageMetadata::new(image.width, image.height, extra),
383
415
  );
384
416
  }
385
417
 
386
- if !collisions.is_empty() {
387
- let mut details = String::new();
388
- for (name, excluded_paths) in &collisions {
389
- let mut all_paths = vec![kept_paths[name].as_str()];
390
- all_paths.extend(excluded_paths.iter().map(|s| s.as_str()));
391
- details.push_str(&format!("\n {name}: {}", all_paths.join(", ")));
392
- }
393
- warn!("Some images share identical file names. Only the first occurrence of each is included:{details}");
418
+ if !duplicates.is_empty() {
419
+ let paths = duplicates.join(", ");
420
+ warn!("Duplicate paths encountered, skipping: {paths}");
394
421
  }
395
422
 
396
- let result = runtime.block_on(async { many_builder.send().error_for_failures().await });
423
+ let total_count = uploads.len();
397
424
 
398
- let uploaded_count = manifest_entries.len();
425
+ let mut many_builder = session.many();
426
+ for prepared in uploads {
427
+ many_builder = many_builder.push(
428
+ session
429
+ .put_path(prepared.path.clone())
430
+ .key(&prepared.key)
431
+ .expiration_policy(expiration),
432
+ );
433
+ }
399
434
 
400
- match result {
401
- Ok(()) => {
402
- println!(
403
- "{} Uploaded {} image {}",
404
- style(">").dim(),
405
- style(uploaded_count).yellow(),
406
- if uploaded_count == 1 { "file" } else { "files" }
407
- );
408
- Ok(manifest_entries)
409
- }
410
- Err(errors) => {
411
- eprintln!("There were errors uploading images:");
412
- let mut error_count = 0;
413
- for error in errors {
414
- let error = anyhow::Error::new(error);
415
- eprintln!(" {}", style(format!("{error:#}")).red());
416
- error_count += 1;
417
- }
418
- anyhow::bail!("Failed to upload {error_count} out of {uploaded_count} images")
435
+ let result = runtime.block_on(async { many_builder.send().await.error_for_failures().await });
436
+ if let Err(errors) = result {
437
+ let errors: Vec<_> = errors.collect();
438
+ let error_count = errors.len();
439
+ eprintln!("There were errors uploading images:");
440
+ for error in errors {
441
+ let error = anyhow::Error::new(error);
442
+ eprintln!(" {}", style(format!("{error:#}")).red());
419
443
  }
444
+ anyhow::bail!("Failed to upload {error_count} images");
420
445
  }
446
+
447
+ println!(
448
+ "{} Uploaded {} image {}",
449
+ style(">").dim(),
450
+ style(total_count).yellow(),
451
+ if total_count == 1 { "file" } else { "files" }
452
+ );
453
+ Ok(manifest_entries)
421
454
  }
422
455
 
423
456
  #[cfg(test)]