Skip to content

Commit

Permalink
Merge 89a4053 into 760f7c4
Browse files Browse the repository at this point in the history
  • Loading branch information
loewenheim committed Jul 14, 2023
2 parents 760f7c4 + 89a4053 commit eba0142
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
**Features**

- Add sourcelink functionality to `symbolic-common` ([#803](https://github.com/getsentry/symbolic/pull/803))
- Add sourcelink support to sourcebundles ([#804](https://github.com/getsentry/symbolic/pull/804))

## 12.2.0

Expand Down
87 changes: 79 additions & 8 deletions symbolic-debuginfo/src/sourcebundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ use serde::{Deserialize, Deserializer, Serialize};
use thiserror::Error;
use zip::{write::FileOptions, ZipWriter};

use symbolic_common::{Arch, AsSelf, CodeId, DebugId};
use symbolic_common::{Arch, AsSelf, CodeId, DebugId, SourceLinkMappings};

use crate::base::*;
use crate::js::{
Expand Down Expand Up @@ -517,6 +517,9 @@ struct SourceBundleManifest {
#[serde(default)]
pub files: BTreeMap<String, SourceFileInfo>,

#[serde(default)]
pub source_links: BTreeMap<String, String>,

/// Arbitrary attributes to include in the bundle.
#[serde(flatten)]
pub attributes: BTreeMap<String, String>,
Expand Down Expand Up @@ -734,9 +737,17 @@ impl<'data> SourceBundle<'data> {
// `SourceBundle`, which might be shared by multiple threads.
// The only thing here that really needs to be `mut` is the `Cursor` / `Seek` position.
let archive = Mutex::new(self.archive.clone());
let source_links = SourceLinkMappings::new(
self.index
.manifest
.source_links
.iter()
.map(|(k, v)| (&k[..], &v[..])),
);
Ok(SourceBundleDebugSession {
index: Arc::clone(&self.index),
archive,
source_links,
})
}

Expand Down Expand Up @@ -862,6 +873,7 @@ enum FileKey<'a> {
pub struct SourceBundleDebugSession<'data> {
archive: Mutex<zip::read::ZipArchive<std::io::Cursor<&'data [u8]>>>,
index: Arc<SourceBundleIndex<'data>>,
source_links: SourceLinkMappings,
}

impl<'data> SourceBundleDebugSession<'data> {
Expand Down Expand Up @@ -891,18 +903,27 @@ impl<'data> SourceBundleDebugSession<'data> {
}

/// Looks up a source file descriptor.
///
/// The file is looked up in both the embedded files and
/// in the included source link mappings, in that order.
fn get_source_file_descriptor(
&self,
key: FileKey,
) -> Result<Option<SourceFileDescriptor<'_>>, SourceBundleError> {
let zip_path = match self.index.indexed_files.get(&key) {
Some(zip_path) => zip_path.as_str(),
None => return Ok(None),
};
if let Some(zip_path) = self.index.indexed_files.get(&key) {
let zip_path = zip_path.as_str();
let content = self.source_by_zip_path(zip_path)?;
let info = self.index.manifest.files.get(zip_path);
return Ok(content.map(|opt| SourceFileDescriptor::new_embedded(Cow::Owned(opt), info)));
}

let content = self.source_by_zip_path(zip_path)?;
let info = self.index.manifest.files.get(zip_path);
Ok(content.map(|opt| SourceFileDescriptor::new_embedded(Cow::Owned(opt), info)))
let FileKey::Path(path) = key else {
return Ok(None);
};
Ok(self
.source_links
.resolve(&path)
.map(|s| SourceFileDescriptor::new_remote(s.into())))
}

/// See [DebugSession::source_by_path] for more information.
Expand Down Expand Up @@ -1632,4 +1653,54 @@ mod tests {
assert_eq!(sanitize_bundle_path("\\foo\\bar"), "foo/bar");
assert_eq!(sanitize_bundle_path("\\\\UNC\\foo\\bar"), "UNC/foo/bar");
}

#[test]
fn test_source_links() -> Result<(), SourceBundleError> {
let mut writer = Cursor::new(Vec::new());
let mut bundle = SourceBundleWriter::start(&mut writer)?;

let mut info = SourceFileInfo::default();
info.set_url("https://example.com/bar/index.min.js".into());
info.set_path("/files/bar/index.min.js".into());
info.set_ty(SourceFileType::MinifiedSource);
bundle.add_file("bar/index.js", &b"filecontents"[..], info)?;
assert!(bundle.has_file("bar/index.js"));

bundle
.manifest
.source_links
.insert("/files/bar/*".to_string(), "https://nope.com/*".into());
bundle
.manifest
.source_links
.insert("/files/foo/*".to_string(), "https://example.com/*".into());

bundle.finish()?;
let bundle_bytes = writer.into_inner();
let bundle = SourceBundle::parse(&bundle_bytes)?;

let sess = bundle.debug_session().unwrap();

// This should be resolved by source link
let foo = sess
.source_by_path("/files/foo/index.min.js")
.unwrap()
.expect("should exist");
assert_eq!(foo.contents(), None);
assert_eq!(foo.ty(), SourceFileType::Source);
assert_eq!(foo.url(), Some("https://example.com/index.min.js"));
assert_eq!(foo.path(), None);

// This should be resolved by embedded file, even though the link also exists
let bar = sess
.source_by_path("/files/bar/index.min.js")
.unwrap()
.expect("should exist");
assert_eq!(bar.contents(), Some("filecontents"));
assert_eq!(bar.ty(), SourceFileType::MinifiedSource);
assert_eq!(bar.url(), Some("https://example.com/bar/index.min.js"));
assert_eq!(bar.path(), Some("/files/bar/index.min.js"));

Ok(())
}
}

0 comments on commit eba0142

Please sign in to comment.