@@ -388,10 +388,15 @@ impl TryFrom<&cargo_metadata::Metadata> for VersionInfo {
388
388
// dev-dependencies are not included
389
389
let package: & mut Package = & mut packages[ id_to_index[ package_id] ] ;
390
390
// Dependencies
391
- for dep in node. dependencies . iter ( ) {
392
- // omit package if it is a development-only dependency
393
- let dep_id = dep. repr . as_str ( ) ;
394
- if id_to_dep_kind[ dep_id] != PrivateDepKind :: Development {
391
+ for dep in node. deps . iter ( ) {
392
+ // Omit the graph edge if this is a development dependency
393
+ // to fix https://github.com/rustsec/rustsec/issues/1043
394
+ // It is possible that something that we depend on normally
395
+ // is also a dev-dependency for something,
396
+ // and dev-dependencies are allowed to have cycles,
397
+ // so we may end up encoding cyclic graph if we don't handle that.
398
+ let dep_id = dep. pkg . repr . as_str ( ) ;
399
+ if strongest_dep_kind ( & dep. dep_kinds ) != PrivateDepKind :: Development {
395
400
package. dependencies . push ( id_to_index[ dep_id] ) ;
396
401
}
397
402
}
@@ -490,23 +495,36 @@ mod tests {
490
495
#![ allow( unused_imports) ] // otherwise conditional compilation emits warnings
491
496
use super :: * ;
492
497
use std:: fs;
493
- use std:: { convert:: TryInto , path:: PathBuf } ;
498
+ use std:: {
499
+ convert:: TryInto ,
500
+ path:: { Path , PathBuf } ,
501
+ } ;
494
502
495
- #[ cfg( feature = "toml" ) ]
496
503
#[ cfg( feature = "from_metadata" ) ]
497
- fn load_own_metadata ( ) -> cargo_metadata:: Metadata {
504
+ fn load_metadata ( cargo_toml_path : & Path ) -> cargo_metadata:: Metadata {
498
505
let mut cmd = cargo_metadata:: MetadataCommand :: new ( ) ;
499
- let cargo_toml_path =
500
- PathBuf :: from ( std:: env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ) . join ( "Cargo.toml" ) ;
501
506
cmd. manifest_path ( cargo_toml_path) ;
502
507
cmd. exec ( ) . unwrap ( )
503
508
}
504
509
510
+ #[ test]
511
+ #[ cfg( feature = "from_metadata" ) ]
512
+ fn dependency_cycle ( ) {
513
+ let cargo_toml_path = PathBuf :: from ( std:: env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) )
514
+ . join ( "tests/fixtures/cargo-audit-dep-cycle/Cargo.toml" ) ;
515
+ let metadata = load_metadata ( & cargo_toml_path) ;
516
+ let version_info_struct: VersionInfo = ( & metadata) . try_into ( ) . unwrap ( ) ;
517
+ let json = serde_json:: to_string ( & version_info_struct) . unwrap ( ) ;
518
+ VersionInfo :: from_str ( & json) . unwrap ( ) ; // <- the part we care about succeeding
519
+ }
520
+
505
521
#[ test]
506
522
#[ cfg( feature = "toml" ) ]
507
523
#[ cfg( feature = "from_metadata" ) ]
508
524
fn to_toml ( ) {
509
- let metadata = load_own_metadata ( ) ;
525
+ let cargo_toml_path =
526
+ PathBuf :: from ( std:: env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ) . join ( "Cargo.toml" ) ;
527
+ let metadata = load_metadata ( & cargo_toml_path) ;
510
528
let version_info_struct: VersionInfo = ( & metadata) . try_into ( ) . unwrap ( ) ;
511
529
let _lockfile_struct: cargo_lock:: Lockfile = ( & version_info_struct) . try_into ( ) . unwrap ( ) ;
512
530
}
0 commit comments