@@ -12,7 +12,6 @@ use std::mem::transmute;
12
12
use std:: ops:: Deref ;
13
13
use std:: path:: { Component , Path , PathBuf } ;
14
14
use std:: process:: Command ;
15
- use std:: slice:: { Chunks , Iter } ;
16
15
use std:: str;
17
16
use std:: thread;
18
17
use std:: time:: { Duration , Instant } ;
@@ -39,10 +38,11 @@ use crate::api::{
39
38
use crate :: config:: Config ;
40
39
use crate :: constants:: { DEFAULT_MAX_DIF_SIZE , DEFAULT_MAX_WAIT } ;
41
40
use crate :: utils:: chunks:: {
42
- upload_chunks, BatchedSliceExt , Chunk , ItemSize , ASSEMBLE_POLL_INTERVAL ,
41
+ upload_chunks, BatchedSliceExt , Chunk , Chunked , ItemSize , MissingObjectsInfo ,
42
+ ASSEMBLE_POLL_INTERVAL ,
43
43
} ;
44
44
use crate :: utils:: dif:: ObjectDifFeatures ;
45
- use crate :: utils:: fs:: { get_sha1_checksum, get_sha1_checksums , TempDir , TempFile } ;
45
+ use crate :: utils:: fs:: { get_sha1_checksum, TempDir , TempFile } ;
46
46
use crate :: utils:: progress:: { ProgressBar , ProgressStyle } ;
47
47
use crate :: utils:: ui:: { copy_with_progress, make_byte_progress_bar} ;
48
48
@@ -52,25 +52,6 @@ pub use crate::api::DebugInfoFile;
52
52
/// Fallback maximum number of chunks in a batch for the legacy upload.
53
53
static MAX_CHUNKS : u64 = 64 ;
54
54
55
- /// An iterator over chunks of data in a `ChunkedDifMatch` object.
56
- ///
57
- /// This struct is returned by `ChunkedDifMatch::chunks`.
58
- struct DifChunks < ' a > {
59
- checksums : Iter < ' a , Digest > ,
60
- iter : Chunks < ' a , u8 > ,
61
- }
62
-
63
- impl < ' a > Iterator for DifChunks < ' a > {
64
- type Item = Chunk < ' a > ;
65
-
66
- fn next ( & mut self ) -> Option < Self :: Item > {
67
- match ( self . checksums . next ( ) , self . iter . next ( ) ) {
68
- ( Some ( checksum) , Some ( data) ) => Some ( Chunk ( ( * checksum, data) ) ) ,
69
- ( _, _) => None ,
70
- }
71
- }
72
- }
73
-
74
55
/// A Debug Information File.
75
56
///
76
57
/// This is primarily used to store inside the [`DifMatch`] so does not contain any
@@ -286,6 +267,40 @@ impl fmt::Debug for DifMatch<'_> {
286
267
}
287
268
}
288
269
270
+ impl AsRef < [ u8 ] > for DifMatch < ' _ > {
271
+ fn as_ref ( & self ) -> & [ u8 ] {
272
+ self . data ( )
273
+ }
274
+ }
275
+
276
+ trait ToAssemble {
277
+ fn to_assemble ( & self , with_debug_id : bool ) -> ( Digest , ChunkedDifRequest < ' _ > ) ;
278
+ }
279
+
280
+ impl ToAssemble for Chunked < DifMatch < ' _ > > {
281
+ /// Creates a tuple which can be collected into a `ChunkedDifRequest`.
282
+ // Some(...) for debug_id can only be done if the ChunkedUploadCapability::Pdbs is
283
+ // present, which is kind of a protocol bug. Not supplying it means more recent
284
+ // sentry-cli versions keep working with ancient versions of sentry by not
285
+ // triggering this protocol bug in most common situations.
286
+ // See: https://github.com/getsentry/sentry-cli/issues/980
287
+ // See: https://github.com/getsentry/sentry-cli/issues/1056
288
+ fn to_assemble ( & self , with_debug_id : bool ) -> ( Digest , ChunkedDifRequest < ' _ > ) {
289
+ (
290
+ self . checksum ( ) ,
291
+ ChunkedDifRequest {
292
+ name : self . object ( ) . file_name ( ) ,
293
+ debug_id : if with_debug_id {
294
+ self . object ( ) . debug_id
295
+ } else {
296
+ None
297
+ } ,
298
+ chunks : self . chunk_hashes ( ) ,
299
+ } ,
300
+ )
301
+ }
302
+ }
303
+
289
304
/// A `DifMatch` with computed SHA1 checksum.
290
305
#[ derive( Debug ) ]
291
306
struct HashedDifMatch < ' data > {
@@ -320,72 +335,6 @@ impl ItemSize for HashedDifMatch<'_> {
320
335
}
321
336
}
322
337
323
- /// A chunked `DifMatch` with computed SHA1 checksums.
324
- #[ derive( Debug ) ]
325
- struct ChunkedDifMatch < ' data > {
326
- inner : HashedDifMatch < ' data > ,
327
- chunks : Vec < Digest > ,
328
- chunk_size : u64 ,
329
- }
330
-
331
- impl < ' data > ChunkedDifMatch < ' data > {
332
- /// Slices the DIF into chunks of `chunk_size` bytes each, and computes SHA1
333
- /// checksums for every chunk as well as the entire DIF.
334
- pub fn from ( inner : DifMatch < ' data > , chunk_size : u64 ) -> Result < Self > {
335
- let ( checksum, chunks) = get_sha1_checksums ( inner. data ( ) , chunk_size as usize ) ?;
336
- Ok ( ChunkedDifMatch {
337
- inner : HashedDifMatch { inner, checksum } ,
338
- chunks,
339
- chunk_size,
340
- } )
341
- }
342
-
343
- /// Returns an iterator over all chunk checksums.
344
- pub fn checksums ( & self ) -> Iter < ' _ , Digest > {
345
- self . chunks . iter ( )
346
- }
347
-
348
- /// Returns an iterator over all `DifChunk`s.
349
- pub fn chunks ( & self ) -> DifChunks < ' _ > {
350
- DifChunks {
351
- checksums : self . checksums ( ) ,
352
- iter : self . data ( ) . chunks ( self . chunk_size as usize ) ,
353
- }
354
- }
355
-
356
- /// Creates a tuple which can be collected into a `ChunkedDifRequest`.
357
- // Some(...) for debug_id can only be done if the ChunkedUploadCapability::Pdbs is
358
- // present, which is kind of a protocol bug. Not supplying it means more recent
359
- // sentry-cli versions keep working with ancient versions of sentry by not
360
- // triggering this protocol bug in most common situations.
361
- // See: https://github.com/getsentry/sentry-cli/issues/980
362
- // See: https://github.com/getsentry/sentry-cli/issues/1056
363
- pub fn to_assemble ( & self , with_debug_id : bool ) -> ( Digest , ChunkedDifRequest < ' _ > ) {
364
- (
365
- self . checksum ( ) ,
366
- ChunkedDifRequest {
367
- name : self . file_name ( ) ,
368
- debug_id : if with_debug_id { self . debug_id } else { None } ,
369
- chunks : & self . chunks ,
370
- } ,
371
- )
372
- }
373
- }
374
-
375
- impl < ' data > Deref for ChunkedDifMatch < ' data > {
376
- type Target = HashedDifMatch < ' data > ;
377
-
378
- fn deref ( & self ) -> & Self :: Target {
379
- & self . inner
380
- }
381
- }
382
-
383
- impl ItemSize for ChunkedDifMatch < ' _ > {
384
- fn size ( & self ) -> u64 {
385
- self . deref ( ) . size ( )
386
- }
387
- }
388
-
389
338
type ZipFileArchive = ZipArchive < BufReader < File > > ;
390
339
391
340
/// A handle to the source of a potential `DifMatch` used inside `search_difs`.
@@ -469,10 +418,6 @@ impl DifSource<'_> {
469
418
}
470
419
}
471
420
472
- /// Information returned by `assemble_difs` containing flat lists of incomplete
473
- /// DIFs and their missing chunks.
474
- type MissingDifsInfo < ' data , ' m > = ( Vec < & ' m ChunkedDifMatch < ' data > > , Vec < Chunk < ' m > > ) ;
475
-
476
421
/// Verifies that the given path contains a ZIP file and opens it.
477
422
fn try_open_zip < P > ( path : P ) -> Result < Option < ZipFileArchive > >
478
423
where
@@ -1268,9 +1213,9 @@ fn create_il2cpp_mappings<'a>(difs: &[DifMatch<'a>]) -> Result<Vec<DifMatch<'a>>
1268
1213
/// The returned value contains separate vectors for incomplete DIFs and
1269
1214
/// missing chunks for convenience.
1270
1215
fn try_assemble_difs < ' data , ' m > (
1271
- difs : & ' m [ ChunkedDifMatch < ' data > ] ,
1216
+ difs : & ' m [ Chunked < DifMatch < ' data > > ] ,
1272
1217
options : & DifUpload ,
1273
- ) -> Result < MissingDifsInfo < ' data , ' m > > {
1218
+ ) -> Result < MissingObjectsInfo < ' m , DifMatch < ' data > > > {
1274
1219
let api = Api :: current ( ) ;
1275
1220
let request = difs
1276
1221
. iter ( )
@@ -1288,7 +1233,7 @@ fn try_assemble_difs<'data, 'm>(
1288
1233
// nicer.
1289
1234
let difs_by_checksum = difs
1290
1235
. iter ( )
1291
- . map ( |m| ( m. checksum , m) )
1236
+ . map ( |m| ( m. checksum ( ) , m) )
1292
1237
. collect :: < BTreeMap < _ , _ > > ( ) ;
1293
1238
1294
1239
let mut difs = Vec :: new ( ) ;
@@ -1317,7 +1262,7 @@ fn try_assemble_difs<'data, 'm>(
1317
1262
// will have to call `try_assemble_difs` again after uploading
1318
1263
// them.
1319
1264
let mut missing_chunks = chunked_match
1320
- . chunks ( )
1265
+ . iter_chunks ( )
1321
1266
. filter ( |& Chunk ( ( c, _) ) | file_response. missing_chunks . contains ( & c) )
1322
1267
. peekable ( ) ;
1323
1268
@@ -1346,11 +1291,11 @@ fn try_assemble_difs<'data, 'm>(
1346
1291
/// `chunk_options`.
1347
1292
///
1348
1293
/// This function blocks until all chunks have been uploaded.
1349
- fn upload_missing_chunks (
1350
- missing_info : & MissingDifsInfo < ' _ , ' _ > ,
1294
+ fn upload_missing_chunks < T > (
1295
+ missing_info : & MissingObjectsInfo < ' _ , T > ,
1351
1296
chunk_options : & ChunkUploadOptions ,
1352
1297
) -> Result < ( ) > {
1353
- let ( difs , chunks) = missing_info;
1298
+ let ( objects , chunks) = missing_info;
1354
1299
1355
1300
// Chunks might be empty if errors occurred in a previous upload. We do
1356
1301
// not need to render a progress bar or perform an upload in this case.
@@ -1362,17 +1307,17 @@ fn upload_missing_chunks(
1362
1307
"{} Uploading {} missing debug information file{}...\
1363
1308
\n {{wide_bar}} {{bytes}}/{{total_bytes}} ({{eta}})",
1364
1309
style( ">" ) . dim( ) ,
1365
- style( difs . len( ) . to_string( ) ) . yellow( ) ,
1366
- if difs . len( ) == 1 { "" } else { "s" }
1310
+ style( objects . len( ) . to_string( ) ) . yellow( ) ,
1311
+ if objects . len( ) == 1 { "" } else { "s" }
1367
1312
) ) ;
1368
1313
1369
1314
upload_chunks ( chunks, chunk_options, progress_style) ?;
1370
1315
1371
1316
println ! (
1372
1317
"{} Uploaded {} missing debug information {}" ,
1373
1318
style( ">" ) . dim( ) ,
1374
- style( difs . len( ) . to_string( ) ) . yellow( ) ,
1375
- match difs . len( ) {
1319
+ style( objects . len( ) . to_string( ) ) . yellow( ) ,
1320
+ match objects . len( ) {
1376
1321
1 => "file" ,
1377
1322
_ => "files" ,
1378
1323
}
@@ -1408,7 +1353,7 @@ fn render_detail(detail: &Option<String>, fallback: Option<&str>) {
1408
1353
/// This function assumes that all chunks have been uploaded successfully. If there are still
1409
1354
/// missing chunks in the assemble response, this likely indicates a bug in the server.
1410
1355
fn poll_dif_assemble (
1411
- difs : & [ & ChunkedDifMatch < ' _ > ] ,
1356
+ difs : & [ & Chunked < DifMatch < ' _ > > ] ,
1412
1357
options : & DifUpload ,
1413
1358
) -> Result < ( Vec < DebugInfoFile > , bool ) > {
1414
1359
let progress_style = ProgressStyle :: default_bar ( ) . template (
@@ -1490,7 +1435,7 @@ fn poll_dif_assemble(
1490
1435
. to_owned ( )
1491
1436
} ) ;
1492
1437
1493
- let difs_by_checksum: BTreeMap < _ , _ > = difs. iter ( ) . map ( |m| ( m. checksum , m) ) . collect ( ) ;
1438
+ let difs_by_checksum: BTreeMap < _ , _ > = difs. iter ( ) . map ( |m| ( m. checksum ( ) , m) ) . collect ( ) ;
1494
1439
1495
1440
for & ( checksum, ref success) in & successes {
1496
1441
// Silently skip all OK entries without a "dif" record since the server
@@ -1512,6 +1457,7 @@ fn poll_dif_assemble(
1512
1457
// If we skip waiting for the server to finish processing, there
1513
1458
// are pending entries. We only expect results that have been
1514
1459
// uploaded in the first place, so we can skip everything else.
1460
+ let dif = dif. object ( ) ;
1515
1461
let kind = match dif. dif . get ( ) {
1516
1462
ParsedDif :: Object ( ref object) => match object. kind ( ) {
1517
1463
symbolic:: debuginfo:: ObjectKind :: None => String :: new ( ) ,
@@ -1550,7 +1496,7 @@ fn poll_dif_assemble(
1550
1496
. ok_or_else ( || format_err ! ( "Server returned unexpected checksum" ) ) ?;
1551
1497
errored. push ( ( dif, error) ) ;
1552
1498
}
1553
- errored. sort_by_key ( |x| x. 0 . file_name ( ) ) ;
1499
+ errored. sort_by_key ( |x| x. 0 . object ( ) . file_name ( ) ) ;
1554
1500
1555
1501
let has_errors = !errored. is_empty ( ) ;
1556
1502
for ( dif, error) in errored {
@@ -1560,7 +1506,7 @@ fn poll_dif_assemble(
1560
1506
_ => Some ( "An unknown error occurred" ) ,
1561
1507
} ;
1562
1508
1563
- println ! ( " {:>7} {}" , style( "ERROR" ) . red( ) , dif. file_name( ) ) ;
1509
+ println ! ( " {:>7} {}" , style( "ERROR" ) . red( ) , dif. object ( ) . file_name( ) ) ;
1564
1510
render_detail ( & error. detail , fallback) ;
1565
1511
}
1566
1512
@@ -1600,7 +1546,7 @@ fn upload_difs_chunked(
1600
1546
1601
1547
// Calculate checksums and chunks
1602
1548
let chunked = prepare_difs ( processed, |m| {
1603
- ChunkedDifMatch :: from ( m, chunk_options. chunk_size )
1549
+ Chunked :: from ( m, chunk_options. chunk_size as usize )
1604
1550
} ) ?;
1605
1551
1606
1552
// Upload missing chunks to the server and remember incomplete difs
0 commit comments