diff --git a/CHANGELOG.md b/CHANGELOG.md index 1774705249..cc17783e73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### Fixes - (snapshots) Chunk image uploads to avoid file descriptor exhaustion and 413 errors when uploading hundreds of images ([#3249](https://github.com/getsentry/sentry-cli/pull/3249)) +- (snapshots) Preserve subdirectory structure in snapshot manifest keys instead of flattening to bare filenames ([#3269](https://github.com/getsentry/sentry-cli/pull/3269)) - Replace `eprintln!` with `log::info!` for progress bar completion messages when the progress bar is disabled (e.g. in CI). This avoids spurious stderr output that some CI systems treat as errors ([#3223](https://github.com/getsentry/sentry-cli/pull/3223)). ## 3.3.5 diff --git a/src/commands/build/snapshots.rs b/src/commands/build/snapshots.rs index daf49772ee..8f6b9bb1a2 100644 --- a/src/commands/build/snapshots.rs +++ b/src/commands/build/snapshots.rs @@ -354,8 +354,7 @@ fn upload_images( .context("Failed to create tokio runtime")?; let mut manifest_entries = HashMap::new(); - let mut collisions: HashMap> = HashMap::new(); - let mut kept_paths = HashMap::new(); + let mut duplicates: Vec = Vec::new(); let mut uploads = Vec::with_capacity(images.len()); let hashed_images: Vec<_> = images @@ -367,20 +366,10 @@ fn upload_images( .collect::>>()?; for (image, hash) in hashed_images { - let image_file_name = image - .relative_path - .file_name() - .unwrap_or_default() - .to_string_lossy() - .into_owned(); - - let relative_path = crate::utils::fs::path_as_url(&image.relative_path); + let image_key = crate::utils::fs::path_as_url(&image.relative_path); - if manifest_entries.contains_key(&image_file_name) { - collisions - .entry(image_file_name) - .or_default() - .push(relative_path); + if manifest_entries.contains_key(&image_key) { + duplicates.push(image_key); continue; } @@ -392,29 +381,19 @@ fn upload_images( }); extra.insert("content_hash".to_owned(), serde_json::Value::String(hash)); - kept_paths.insert(image_file_name.clone(), relative_path); uploads.push(PreparedImage { path: image.path, key, }); manifest_entries.insert( - image_file_name, + image_key, ImageMetadata::new(image.width, image.height, extra), ); } - if !collisions.is_empty() { - let details: String = collisions - .iter() - .map(|(name, excluded)| { - let kept = &kept_paths[name]; - let all = std::iter::once(kept.as_str()) - .chain(excluded.iter().map(|s| s.as_str())) - .join(", "); - format!("\n {name}: {all}") - }) - .collect(); - warn!("Some images share identical file names. Only the first occurrence of each is included:{details}"); + if !duplicates.is_empty() { + let paths = duplicates.join(", "); + warn!("Duplicate paths encountered, skipping: {paths}"); } let total_count = uploads.len();