Skip to content

Commit

Permalink
feat(sourcebundle): Add callback to handle skipped files (#864)
Browse files Browse the repository at this point in the history
* feat(sourcebundle): Add callback to handle skipped files

Add a callback to SourceBundleWriter that is called every time we skip adding a file to the bundle due to a ReadFailed error.

Closes #863

* fix(sourcebundle): Skip all invalid sources

#861 missed another spot where the ReadFailed error can cause the write function to fail; this commit fixes that.

Fixes #860

* meta: Update changelog

* apply suggestions from code review

Co-authored-by: Jan Michael Auer <jan.auer@sentry.io>

---------

Co-authored-by: Jan Michael Auer <jan.auer@sentry.io>
  • Loading branch information
szokeasaurusrex and jan-auer authored Sep 4, 2024
1 parent fa5edd1 commit a66bcd1
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Add callback to `symbolic::debuginfo::sourcebundle::SourceBundleWriter` which handles files skipped while writing to the source bundle. ([#864](https://github.com/getsentry/symbolic/pull/864))

## 12.10.1

- Skip invalid sources ([#861](https://github.com/getsentry/symbolic/pull/861))
Expand Down
77 changes: 70 additions & 7 deletions symbolic-debuginfo/src/sourcebundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ use std::borrow::Cow;
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::error::Error;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::fs::{File, OpenOptions};
use std::io::{BufReader, BufWriter, Read, Seek, Write};
use std::path::Path;
Expand Down Expand Up @@ -1035,6 +1036,35 @@ fn sanitize_bundle_path(path: &str) -> String {
sanitized
}

/// Contains information about a file skipped in the SourceBundleWriter
#[derive(Debug)]
pub struct SkippedFileInfo<'a> {
path: &'a str,
reason: &'a str,
}

impl<'a> SkippedFileInfo<'a> {
fn new(path: &'a str, reason: &'a str) -> Self {
Self { path, reason }
}

/// Returns the path of the skipped file.
pub fn path(&self) -> &str {
self.path
}

/// Get the human-readable reason why the file was skipped
pub fn reason(&self) -> &str {
self.reason
}
}

impl Display for SkippedFileInfo<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "Skipped file {} due to: {}", self.path, self.reason)
}
}

/// Writer to create [`SourceBundles`].
///
/// Writers can either [create a new file] or be created from an [existing file]. Then, use
Expand Down Expand Up @@ -1070,6 +1100,7 @@ where
manifest: SourceBundleManifest,
writer: ZipWriter<W>,
collect_il2cpp: bool,
skipped_file_callback: Box<dyn FnMut(SkippedFileInfo)>,
}

fn default_file_options() -> SimpleFileOptions {
Expand Down Expand Up @@ -1097,6 +1128,7 @@ where
manifest: SourceBundleManifest::new(),
writer: ZipWriter::new(writer),
collect_il2cpp: false,
skipped_file_callback: Box::new(|_| ()),
})
}

Expand Down Expand Up @@ -1212,6 +1244,42 @@ where
Ok(())
}

/// Calls add_file, and handles any ReadFailed errors by calling the skipped_file_callback.
fn add_file_skip_read_failed<S, R>(
&mut self,
path: S,
file: R,
info: SourceFileInfo,
) -> Result<(), SourceBundleError>
where
S: AsRef<str>,
R: Read,
{
let result = self.add_file(&path, file, info);

if let Err(e) = &result {
if e.kind == SourceBundleErrorKind::ReadFailed {
let reason = e.to_string();
let skipped_info = SkippedFileInfo::new(path.as_ref(), &reason);
(self.skipped_file_callback)(skipped_info);

return Ok(());
}
}

result
}

/// Set a callback, which is called for every file that is skipped from being included in the
/// source bundle. The callback receives information about the file being skipped.
pub fn with_skipped_file_callback(
mut self,
callback: impl FnMut(SkippedFileInfo) + 'static,
) -> Self {
self.skipped_file_callback = Box::new(callback);
self
}

/// Writes a single object into the bundle.
///
/// Returns `Ok(true)` if any source files were added to the bundle, or `Ok(false)` if no
Expand Down Expand Up @@ -1297,7 +1365,7 @@ where
collect_il2cpp_sources(&source, &mut referenced_files);
}

self.add_file(bundle_path, source.as_slice(), info)?;
self.add_file_skip_read_failed(bundle_path, source.as_slice(), info)?;
}

files_handled.insert(filename);
Expand All @@ -1314,12 +1382,7 @@ where
info.set_ty(SourceFileType::Source);
info.set_path(filename.clone());

if let Err(e) = self.add_file(bundle_path, source, info) {
// Skip sources that are not UTF-8
if e.kind != SourceBundleErrorKind::ReadFailed {
return Err(e);
};
}
self.add_file_skip_read_failed(bundle_path, source, info)?
}
}

Expand Down

0 comments on commit a66bcd1

Please sign in to comment.