@@ -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