Skip to content

Commit

Permalink
Fix duplicate dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake-Shadle committed Jan 21, 2024
1 parent b2c4864 commit 1a93556
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 1,148 deletions.
24 changes: 23 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,24 @@ impl Builder {
let maybe_real_name = pkg.name();
let strong = features.is_some();

// If there are multiple versions of the same package we use the
// version to disambiguate references to them, but that is extremely
// rare so we only do it in the case there are actually multiple crates
// with the same name. Note that cargo _should_ fail to resolve
// nodes if the same package is referenced with two `^` (compatible)
// semvers, ie, you can't reference both ">= 0.2.12" and "=0.2.7" of
// a package even if they could never point to the same package
// This _may_ mean there could be a situation where a single crate
// _could_ be referenced with 0.0.x versions, but...I'll fix that
// if someone reports an issue
let rdep_version = (rnode
.deps
.iter()
.filter(|d| d.pkg.name() == rdep.pkg.name())
.count()
> 1)
.then(|| rdep.pkg.version().parse().expect("failed to parse semver"));

let edges = rdep.dep_kinds.iter().filter_map(|dk| {
let mask = match dk.kind {
DepKind::Normal => 0x1,
Expand All @@ -1154,7 +1172,11 @@ impl Builder {

// Crates can rename the dependency package themselves
let dep_name = dep.rename.as_deref().unwrap_or(&dep.name);
dep_names_match(dep_name, &rdep.name) || maybe_real_name == dep_name
if !dep_names_match(dep_name, &rdep.name) && maybe_real_name != dep_name {
return false;
}

rdep_version.as_ref().map_or(true, |rdv| dep.req.matches(rdv))
})
.unwrap_or_else(|| panic!("cargo metadata resolved a dependency for a dependency not specified by the crate: {rdep:?}"));

Expand Down
1 change: 0 additions & 1 deletion tests/bug.json

This file was deleted.

28 changes: 16 additions & 12 deletions tests/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,18 +190,6 @@ fn direct_dependencies() {
insta::assert_snapshot!(dd);
}

#[test]
#[cfg(feature = "with-crates-index")]
fn bug_repro() {
let mut kb = krates::Builder::new();
kb.with_crates_io_index(None, krates::index::IndexKind::Sparse)
.unwrap();

let grafs = util::build("bug.json", kb).unwrap();

insta::assert_snapshot!(grafs.dotgraph());
}

/// Validates that there is no difference between the OG "opaque" package id
/// format and the newly stabilized one
#[test]
Expand All @@ -211,3 +199,19 @@ fn opaque_matches_stable() {

similar_asserts::assert_eq!(opaque.dotgraph(), stable.dotgraph());
}

/// Validates we can correctly find package ids for duplicated packages in both
/// the opaque and stable formats
///
/// https://github.com/EmbarkStudios/krates/issues/68
/// https://github.com/EmbarkStudios/krates/issues/69
#[test]
fn finds_duplicates() {
let opaque = util::build("pid-opaque.json", krates::Builder::new()).unwrap();
let stable = util::build("pid-stable.json", krates::Builder::new()).unwrap();

let opaque = opaque.dotgraph();
similar_asserts::assert_eq!(opaque, stable.dotgraph());

insta::assert_snapshot!(opaque);
}
1 change: 1 addition & 0 deletions tests/pid-opaque.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tests/pid-stable.json

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions tests/pid/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "pid"
version = "0.1.0"
edition = "2021"

[dependencies]
# does not have a feature called wasm-bindgen
getrandom = { version = "0.2.7", features = ["js"] }
# does not have a feature called js
getrandom_old = { package = "getrandom", version = "0.1.16", features = [
"wasm-bindgen",
] }
tower_http_4 = { package = "tower-http", version = "0.4.4", features = [] }
tower-http = { package = "tower-http", version = "0.5.0", features = [
"sensitive-headers",
] }
1 change: 1 addition & 0 deletions tests/pid/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1,134 changes: 0 additions & 1,134 deletions tests/snapshots/misc__bug_repro.snap

This file was deleted.

261 changes: 261 additions & 0 deletions tests/snapshots/misc__finds_duplicates.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
---
source: tests/misc.rs
expression: opaque
---
digraph {
0 [ label = "crate bitflags 2.4.2" ]
1 [ label = "crate bumpalo 3.14.0" ]
2 [ label = "crate bytes 1.5.0" ]
3 [ label = "crate cfg-if 1.0.0" ]
4 [ label = "crate fnv 1.0.7" ]
5 [ label = "crate futures-core 0.3.30" ]
6 [ label = "crate futures-task 0.3.30" ]
7 [ label = "crate futures-util 0.3.30" ]
8 [ label = "crate getrandom 0.1.16" ]
9 [ label = "crate getrandom 0.2.12" ]
10 [ label = "crate http 0.2.11" ]
11 [ label = "crate http 1.0.0" ]
12 [ label = "crate http-body 0.4.6" ]
13 [ label = "crate http-body 1.0.0" ]
14 [ label = "crate http-body-util 0.1.0" ]
15 [ label = "crate http-range-header 0.3.1" ]
16 [ label = "crate itoa 1.0.10" ]
17 [ label = "crate js-sys 0.3.67" ]
18 [ label = "crate libc 0.2.152" ]
19 [ label = "crate log 0.4.20" ]
20 [ label = "crate once_cell 1.19.0" ]
21 [ label = "crate pid 0.1.0 path+file:///krates/tests/pid" ]
22 [ label = "crate pin-project-lite 0.2.13" ]
23 [ label = "crate pin-utils 0.1.0" ]
24 [ label = "crate proc-macro2 1.0.78" ]
25 [ label = "crate quote 1.0.35" ]
26 [ label = "crate syn 2.0.48" ]
27 [ label = "crate tower-http 0.4.4" ]
28 [ label = "crate tower-http 0.5.1" ]
29 [ label = "crate tower-layer 0.3.2" ]
30 [ label = "crate tower-service 0.3.2" ]
31 [ label = "crate unicode-ident 1.0.12" ]
32 [ label = "crate wasi 0.11.0+wasi-snapshot-preview1" ]
33 [ label = "crate wasi 0.9.0+wasi-snapshot-preview1" ]
34 [ label = "crate wasm-bindgen 0.2.90" ]
35 [ label = "crate wasm-bindgen-backend 0.2.90" ]
36 [ label = "crate wasm-bindgen-macro 0.2.90" ]
37 [ label = "crate wasm-bindgen-macro-support 0.2.90" ]
38 [ label = "crate wasm-bindgen-shared 0.2.90" ]
39 [ label = "feature alloc" ]
40 [ label = "feature alloc" ]
41 [ label = "feature default" ]
42 [ label = "feature default" ]
43 [ label = "feature default" ]
44 [ label = "feature default" ]
45 [ label = "feature default" ]
46 [ label = "feature alloc" ]
47 [ label = "feature wasm-bindgen" ]
48 [ label = "feature js" ]
49 [ label = "feature default" ]
50 [ label = "feature sensitive-headers" ]
51 [ label = "feature default" ]
52 [ label = "feature proc-macro" ]
53 [ label = "feature proc-macro" ]
54 [ label = "feature default" ]
55 [ label = "feature spans" ]
56 [ label = "feature default" ]
57 [ label = "feature default" ]
58 [ label = "feature default" ]
59 [ label = "feature default" ]
60 [ label = "feature full" ]
61 [ label = "feature default" ]
62 [ label = "feature spans" ]
63 [ label = "feature visit" ]
64 [ label = "feature spans" ]
65 [ label = "feature std" ]
66 [ label = "feature std" ]
67 [ label = "feature std" ]
68 [ label = "feature bindgen" ]
69 [ label = "feature js-sys" ]
70 [ label = "feature bindgen" ]
71 [ label = "feature wasm-bindgen" ]
72 [ label = "feature js-sys" ]
73 [ label = "feature std" ]
74 [ label = "feature std" ]
75 [ label = "feature alloc" ]
76 [ label = "feature race" ]
77 [ label = "feature quote" ]
78 [ label = "feature proc-macro" ]
79 [ label = "feature printing" ]
80 [ label = "feature parsing" ]
81 [ label = "feature derive" ]
82 [ label = "feature clone-impls" ]
83 [ label = "feature std" ]
84 [ label = "feature std" ]
85 [ label = "feature spans" ]
7 -> 5 [ label = "" ]
7 -> 39 [ label = "" ]
7 -> 6 [ label = "" ]
7 -> 40 [ label = "" ]
7 -> 22 [ label = "" ]
7 -> 23 [ label = "" ]
8 -> 3 [ label = "" ]
8 -> 17 [ label = " 'wasm32-unknown-unknown'" ]
8 -> 18 [ label = " 'cfg(unix)'" ]
8 -> 41 [ label = " 'cfg(target_os = \"wasi\")'" ]
8 -> 42 [ label = " 'wasm32-unknown-unknown'" ]
9 -> 3 [ label = "" ]
9 -> 17 [ label = " 'cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))'" ]
9 -> 18 [ label = " 'cfg(unix)'" ]
9 -> 32 [ label = " 'cfg(target_os = \"wasi\")'" ]
9 -> 34 [ label = " 'cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))'" ]
10 -> 43 [ label = "" ]
10 -> 44 [ label = "" ]
10 -> 16 [ label = "" ]
11 -> 43 [ label = "" ]
11 -> 44 [ label = "" ]
11 -> 16 [ label = "" ]
12 -> 43 [ label = "" ]
12 -> 10 [ label = "" ]
12 -> 22 [ label = "" ]
13 -> 43 [ label = "" ]
13 -> 45 [ label = "" ]
14 -> 43 [ label = "" ]
14 -> 46 [ label = "" ]
14 -> 45 [ label = "" ]
14 -> 13 [ label = "" ]
14 -> 22 [ label = "" ]
17 -> 42 [ label = "" ]
21 -> 47 [ label = "" ]
21 -> 48 [ label = "" ]
21 -> 49 [ label = "" ]
21 -> 50 [ label = "" ]
21 -> 51 [ label = "" ]
24 -> 31 [ label = "" ]
25 -> 24 [ label = "" ]
25 -> 52 [ label = "" ]
26 -> 24 [ label = "" ]
26 -> 52 [ label = "" ]
26 -> 25 [ label = "" ]
26 -> 53 [ label = "" ]
26 -> 31 [ label = "" ]
27 -> 0 [ label = "" ]
27 -> 43 [ label = "" ]
27 -> 54 [ label = "" ]
27 -> 7 [ label = "" ]
27 -> 10 [ label = "" ]
27 -> 12 [ label = "" ]
27 -> 15 [ label = "" ]
27 -> 22 [ label = "" ]
27 -> 29 [ label = "" ]
27 -> 30 [ label = "" ]
28 -> 0 [ label = "" ]
28 -> 43 [ label = "" ]
28 -> 45 [ label = "" ]
28 -> 13 [ label = "" ]
28 -> 14 [ label = "" ]
28 -> 22 [ label = "" ]
28 -> 29 [ label = "" ]
28 -> 30 [ label = "" ]
34 -> 3 [ label = "" ]
34 -> 36 [ label = "" ]
34 -> 55 [ label = "" ]
35 -> 56 [ label = "" ]
35 -> 19 [ label = "" ]
35 -> 57 [ label = "" ]
35 -> 58 [ label = "" ]
35 -> 59 [ label = "" ]
35 -> 60 [ label = "" ]
35 -> 61 [ label = "" ]
35 -> 38 [ label = "" ]
36 -> 59 [ label = "" ]
36 -> 37 [ label = "" ]
36 -> 62 [ label = "" ]
37 -> 58 [ label = "" ]
37 -> 59 [ label = "" ]
37 -> 63 [ label = "" ]
37 -> 60 [ label = "" ]
37 -> 61 [ label = "" ]
37 -> 35 [ label = "" ]
37 -> 64 [ label = "" ]
37 -> 38 [ label = "" ]
56 -> 1 [ label = "" ]
65 -> 2 [ label = "" ]
43 -> 2 [ label = "" ]
43 -> 65 [ label = "" ]
66 -> 4 [ label = "" ]
44 -> 4 [ label = "" ]
44 -> 66 [ label = "" ]
67 -> 5 [ label = "" ]
67 -> 39 [ label = "" ]
54 -> 5 [ label = "" ]
54 -> 67 [ label = "" ]
39 -> 5 [ label = "" ]
40 -> 6 [ label = "" ]
46 -> 7 [ label = "" ]
46 -> 39 [ label = "" ]
46 -> 40 [ label = "" ]
47 -> 8 [ label = "" ]
47 -> 68 [ label = "" ]
47 -> 69 [ label = "" ]
69 -> 8 [ label = "" ]
69 -> 17 [ label = "" ]
68 -> 8 [ label = "" ]
68 -> 70 [ label = "" ]
71 -> 9 [ label = "" ]
71 -> 34 [ label = "" ]
72 -> 9 [ label = "" ]
72 -> 17 [ label = "" ]
48 -> 9 [ label = "" ]
48 -> 71 [ label = "" ]
48 -> 72 [ label = "" ]
73 -> 11 [ label = "" ]
45 -> 11 [ label = "" ]
45 -> 73 [ label = "" ]
74 -> 20 [ label = "" ]
74 -> 75 [ label = "" ]
76 -> 20 [ label = "" ]
57 -> 20 [ label = "" ]
57 -> 74 [ label = "" ]
75 -> 20 [ label = "" ]
75 -> 76 [ label = "" ]
52 -> 24 [ label = "" ]
58 -> 24 [ label = "" ]
58 -> 52 [ label = "" ]
53 -> 25 [ label = "" ]
53 -> 52 [ label = "" ]
59 -> 25 [ label = "" ]
59 -> 53 [ label = "" ]
63 -> 26 [ label = "" ]
77 -> 26 [ label = "" ]
77 -> 25 [ label = "" ]
78 -> 26 [ label = "" ]
78 -> 52 [ label = "" ]
78 -> 53 [ label = "" ]
79 -> 26 [ label = "" ]
79 -> 77 [ label = "" ]
80 -> 26 [ label = "" ]
60 -> 26 [ label = "" ]
81 -> 26 [ label = "" ]
61 -> 26 [ label = "" ]
61 -> 81 [ label = "" ]
61 -> 80 [ label = "" ]
61 -> 79 [ label = "" ]
61 -> 82 [ label = "" ]
61 -> 78 [ label = "" ]
82 -> 26 [ label = "" ]
49 -> 27 [ label = "" ]
50 -> 28 [ label = "" ]
51 -> 28 [ label = "" ]
83 -> 33 [ label = "" ]
41 -> 33 [ label = "" ]
41 -> 83 [ label = "" ]
84 -> 34 [ label = "" ]
85 -> 34 [ label = "" ]
85 -> 55 [ label = "" ]
42 -> 34 [ label = "" ]
42 -> 85 [ label = "" ]
42 -> 84 [ label = "" ]
64 -> 35 [ label = "" ]
55 -> 36 [ label = "" ]
55 -> 62 [ label = "" ]
62 -> 37 [ label = "" ]
62 -> 64 [ label = "" ]
}

0 comments on commit 1a93556

Please sign in to comment.