Skip to content

Commit 0acdceb

Browse files
committed
feat: use source as vcs url
Signed-off-by: Johannes Özkan Preisinger <[email protected]>
1 parent ab5d4d7 commit 0acdceb

File tree

2 files changed

+99
-1
lines changed

2 files changed

+99
-1
lines changed

cargo-cyclonedx/src/generator.rs

+98
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,34 @@ impl SbomGenerator {
399399
e
400400
),
401401
}
402+
} else {
403+
if let Some(source) = &package.source {
404+
if !source.is_crates_io() {
405+
match source.repr.split_once('+') {
406+
Some(("git", git_path)) => {
407+
let repo_url = git_path
408+
.split_once('#')
409+
.map_or(git_path, |(first, _)| first);
410+
match Uri::try_from(repo_url.to_string()) {
411+
Ok(uri) => references
412+
.push(ExternalReference::new(ExternalReferenceType::Vcs, uri)),
413+
Err(e) => log::warn!(
414+
"Package {} has an invalid repository URI ({}): {} ",
415+
package.name,
416+
source,
417+
e
418+
),
419+
}
420+
}
421+
Some((source, _path)) => log::warn!("Unknown source kind {}", source),
422+
None => {
423+
log::warn!(
424+
"No '+' separator found in source field from `cargo metadata`"
425+
)
426+
}
427+
}
428+
}
429+
}
402430
}
403431

404432
if !references.is_empty() {
@@ -1041,6 +1069,8 @@ impl From<std::io::Error> for SbomWriterError {
10411069
mod test {
10421070
use super::*;
10431071

1072+
const GIT_PACKAGE_JSON: &str = include_str!("../tests/fixtures/git_package.json");
1073+
10441074
#[test]
10451075
fn it_should_parse_author_and_email() {
10461076
let actual = SbomGenerator::parse_author("First Last <[email protected]>")
@@ -1079,4 +1109,72 @@ mod test {
10791109

10801110
assert_eq!(actual, expected);
10811111
}
1112+
1113+
#[test]
1114+
fn it_should_get_external_references_from_source() {
1115+
let mut git_package: Package = serde_json::from_str(GIT_PACKAGE_JSON).unwrap();
1116+
git_package.repository = None;
1117+
1118+
let actual = SbomGenerator::get_external_references(&git_package)
1119+
.expect("Failed to parse external reference");
1120+
1121+
let mut expected = Vec::new();
1122+
expected.push(ExternalReference::new(
1123+
ExternalReferenceType::Vcs,
1124+
Uri::new("https://github.com/rust-secure-code/cargo-auditable.git"),
1125+
));
1126+
1127+
assert_eq!(actual, ExternalReferences(expected));
1128+
}
1129+
1130+
#[test]
1131+
fn it_should_get_external_references_from_source_without_digest() {
1132+
let mut git_package: Package = serde_json::from_str(GIT_PACKAGE_JSON).unwrap();
1133+
git_package.repository = None;
1134+
git_package.source = Some(cargo_metadata::Source {
1135+
repr: "git+https://github.com/rust-secure-code/cargo-auditable.git".to_string(),
1136+
});
1137+
1138+
let actual = SbomGenerator::get_external_references(&git_package)
1139+
.expect("Failed to parse external reference");
1140+
1141+
let mut expected = Vec::new();
1142+
expected.push(ExternalReference::new(
1143+
ExternalReferenceType::Vcs,
1144+
Uri::new("https://github.com/rust-secure-code/cargo-auditable.git"),
1145+
));
1146+
1147+
assert_eq!(actual, ExternalReferences(expected));
1148+
}
1149+
1150+
#[test]
1151+
fn it_should_not_get_external_references_from_unidentifiable_source() {
1152+
let mut git_package: Package = serde_json::from_str(GIT_PACKAGE_JSON).unwrap();
1153+
git_package.repository = None;
1154+
git_package.source = Some(cargo_metadata::Source {
1155+
repr: "https://github.com/rust-secure-code/cargo-auditable.git".to_string(),
1156+
});
1157+
1158+
assert_eq!(SbomGenerator::get_external_references(&git_package), None);
1159+
}
1160+
1161+
#[test]
1162+
fn it_should_not_get_external_references_from_non_uri_source() {
1163+
let mut git_package: Package = serde_json::from_str(GIT_PACKAGE_JSON).unwrap();
1164+
git_package.repository = None;
1165+
git_package.source = Some(cargo_metadata::Source {
1166+
repr: "not a uri".to_string(),
1167+
});
1168+
1169+
assert_eq!(SbomGenerator::get_external_references(&git_package), None);
1170+
}
1171+
1172+
#[test]
1173+
fn it_should_not_get_external_reference_from_invalid_source_uri() {
1174+
let mut git_package: Package = serde_json::from_str(GIT_PACKAGE_JSON).unwrap();
1175+
git_package.repository = None;
1176+
git_package.source = None;
1177+
1178+
assert_eq!(SbomGenerator::get_external_references(&git_package), None);
1179+
}
10821180
}

cargo-cyclonedx/src/purl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub fn get_purl(
6666

6767
/// Converts the `cargo metadata`'s `source` field to a valid PURL `vcs_url`.
6868
/// Assumes that the source kind is `git`, panics if it isn't.
69-
fn source_to_vcs_url(source: &cargo_metadata::Source) -> String {
69+
pub fn source_to_vcs_url(source: &cargo_metadata::Source) -> String {
7070
assert!(source.repr.starts_with("git+"));
7171
source.repr.replace('#', "@")
7272
}

0 commit comments

Comments
 (0)