@@ -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 {
10411069mod 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}
0 commit comments