From ab5487828edec3d8e3bb7f18a1a7dd193075c6b2 Mon Sep 17 00:00:00 2001 From: Jake Shadle Date: Sat, 20 Jan 2024 07:27:38 +0100 Subject: [PATCH] Ignore features that reference unresolved crates (#67) * Ignore features that referenced unresolved crates * Update CHANGELOG --- CHANGELOG.md | 3 + src/builder.rs | 7 +- tests/features.rs | 17 + tests/features/Cargo.lock | 259 +++++++++++++- tests/features/Cargo.toml | 3 + .../features__handles_dev_only_features.snap | 322 ++++++++++++++++++ 6 files changed, 596 insertions(+), 15 deletions(-) create mode 100644 tests/snapshots/features__handles_dev_only_features.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 69e857d..7fe12f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - ReleaseDate +### Fixed +- [PR#67](https://github.com/EmbarkStudios/krates/pull/67) resolved [#66](https://github.com/EmbarkStudios/krates/issues/66) by ignore features that reference crates that aren't resolved, instead of panicing, as there should only be one case where that occurs. + ## [0.16.0] - 2024-01-19 ### Fixed - [PR#65](https://github.com/EmbarkStudios/krates/pull/65) resolved [#64](https://github.com/EmbarkStudios/krates/issues/64) by adding support for the newly stabilized (currently nightly only) package id format. diff --git a/src/builder.rs b/src/builder.rs index 758082a..f447b5e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1070,10 +1070,9 @@ impl Builder { let Some(ndep) = rnode.deps.iter().find(|rdep| { dep_names_match(krate_name, &rdep.name) || krate_name == rdep.pkg.name() }) else { - unreachable!( - "unable to find dependency {krate_name} for {pid} {:#?}", - rnode.deps - ); + // We can have a feature that points to a crate that isn't resolved by cargo due to it being + // a dev-only dependency + continue; }; let rdep_node = get_rnode(&ndep.pkg); diff --git a/tests/features.rs b/tests/features.rs index 6da862b..ea8283b 100644 --- a/tests/features.rs +++ b/tests/features.rs @@ -234,6 +234,23 @@ fn handles_cyclic_features() { assert_features!(md, "features-galore", ["cycle", "midi", "subfeatcycle"]); } +/// Ensures we handle features that enable dev only dependencies +/// +#[test] +fn handles_dev_only_features() { + let mut cmd = krates::Cmd::new(); + cmd.manifest_path("tests/features/Cargo.toml") + .no_default_features(); + + let mut builder = krates::Builder::new(); + builder.include_targets([("x86_64-pc-windows-msvc", vec![])]); + builder.ignore_kind(krates::DepKind::Dev, krates::Scope::All); + + let md: krates::Krates = builder.build(cmd, krates::NoneFilter).unwrap(); + + insta::assert_snapshot!(krates::petgraph::dot::Dot::new(md.graph()).to_string()); +} + /// Ensures that features only brought in by eg dev-dependencies are not used if /// dev-dependencies are ignored /// diff --git a/tests/features/Cargo.lock b/tests/features/Cargo.lock index 3fc501f..f963469 100644 --- a/tests/features/Cargo.lock +++ b/tests/features/Cargo.lock @@ -43,6 +43,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base-x" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" + [[package]] name = "base64" version = "0.13.0" @@ -119,6 +125,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "cbor4ii" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544cf8c89359205f4f990d0e6f3828db42df85b5dac95d09157a250eb0749c4" +dependencies = [ + "serde", +] + [[package]] name = "cc" version = "1.0.73" @@ -143,6 +158,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cid" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd94671561e36e4e7de75f753f577edafb0e7c05d6e4547229fdf7938fbcd2c3" +dependencies = [ + "core2", + "multibase", + "multihash", + "serde", + "serde_bytes", + "unsigned-varint", +] + [[package]] name = "clang-sys" version = "1.4.0" @@ -196,6 +225,15 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +[[package]] +name = "core2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" +dependencies = [ + "memchr", +] + [[package]] name = "coreaudio-rs" version = "0.11.1" @@ -225,6 +263,32 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "data-encoding" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" + +[[package]] +name = "data-encoding-macro" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c01c06f5f429efdf2bae21eb67c28b3df3cf85b7dd2d8ef09c0838dac5d33e" +dependencies = [ + "data-encoding", + "data-encoding-macro-internal", +] + +[[package]] +name = "data-encoding-macro-internal" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0047d07f2c89b17dd631c80450d69841a6b5d7fb17278cbc43d7e4cfcf2576f3" +dependencies = [ + "data-encoding", + "syn 1.0.98", +] + [[package]] name = "encoding_rs" version = "0.8.31" @@ -244,6 +308,7 @@ dependencies = [ "rgb", "rustls", "serde", + "serde_ipld_dagcbor", ] [[package]] @@ -633,6 +698,44 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "multibase" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3539ec3c1f04ac9748a260728e855f261b4977f5c3406612c884564f329404" +dependencies = [ + "base-x", + "data-encoding", + "data-encoding-macro", +] + +[[package]] +name = "multihash" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd8a792c1694c6da4f68db0a9d707c72bd260994da179e6030a5dcee00bb815" +dependencies = [ + "core2", + "multihash-derive", + "serde", + "serde-big-array", + "unsigned-varint", +] + +[[package]] +name = "multihash-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db" +dependencies = [ + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.98", + "synstructure", +] + [[package]] name = "nom" version = "7.1.1" @@ -711,6 +814,40 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.98", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -719,9 +856,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -746,9 +883,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -871,6 +1008,12 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "sct" version = "0.7.0" @@ -883,22 +1026,52 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.138" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd31f59f6fe2b0c055371bb2f16d7f0aa7d8881676c04a55b1596d1a17cd10a4" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", +] + +[[package]] +name = "serde_ipld_dagcbor" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e880e0b1f9c7a8db874642c1217f7e19b29e325f24ab9f0fcb11818adec7f01" +dependencies = [ + "cbor4ii", + "cid", + "scopeguard", + "serde", ] [[package]] @@ -963,6 +1136,49 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.98", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "time" version = "0.3.11" @@ -1038,6 +1254,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.2" @@ -1100,6 +1325,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "unsigned-varint" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105" + [[package]] name = "untrusted" version = "0.7.1" @@ -1167,7 +1404,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 1.0.98", "wasm-bindgen-shared", ] @@ -1201,7 +1438,7 @@ checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.98", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/tests/features/Cargo.toml b/tests/features/Cargo.toml index 9696367..3175034 100644 --- a/tests/features/Cargo.toml +++ b/tests/features/Cargo.toml @@ -11,6 +11,9 @@ rgb = { version = "0.8.25", optional = true } serde = { version = "1.0.133", optional = true } rustls = { version = "0.20", optional = true } +[target.'cfg(windows)'.dependencies] +serde_ipld_dagcbor = "0.4.2" + [target.'cfg(target_os = "linux")'.dependencies] git = { package = "git2", version = "0.14", default-features = false } diff --git a/tests/snapshots/features__handles_dev_only_features.snap b/tests/snapshots/features__handles_dev_only_features.snap new file mode 100644 index 0000000..69db67b --- /dev/null +++ b/tests/snapshots/features__handles_dev_only_features.snap @@ -0,0 +1,322 @@ +--- +source: tests/features.rs +expression: "krates::petgraph::dot::Dot::new(md.graph()).to_string()" +--- +digraph { + 0 [ label = "crate base-x 0.2.11" ] + 1 [ label = "crate cbor4ii 0.2.14" ] + 2 [ label = "crate cid 0.10.1" ] + 3 [ label = "crate core2 0.4.0" ] + 4 [ label = "crate data-encoding 2.5.0" ] + 5 [ label = "crate data-encoding-macro 0.1.14" ] + 6 [ label = "crate data-encoding-macro-internal 0.1.12" ] + 7 [ label = "crate features-galore 0.1.0 path+file:///krates/tests/features" ] + 8 [ label = "crate memchr 2.5.0" ] + 9 [ label = "crate multibase 0.9.1" ] + 10 [ label = "crate multihash 0.18.1" ] + 11 [ label = "crate multihash-derive 0.8.1" ] + 12 [ label = "crate proc-macro-crate 1.1.3" ] + 13 [ label = "crate proc-macro-error 1.0.4" ] + 14 [ label = "crate proc-macro-error-attr 1.0.4" ] + 15 [ label = "crate proc-macro2 1.0.76" ] + 16 [ label = "crate quote 1.0.35" ] + 17 [ label = "crate scopeguard 1.2.0" ] + 18 [ label = "crate serde 1.0.195" ] + 19 [ label = "crate serde-big-array 0.3.3" ] + 20 [ label = "crate serde_bytes 0.11.14" ] + 21 [ label = "crate serde_derive 1.0.195" ] + 22 [ label = "crate serde_ipld_dagcbor 0.4.2" ] + 23 [ label = "crate syn 1.0.98" ] + 24 [ label = "crate syn 2.0.48" ] + 25 [ label = "crate synstructure 0.12.6" ] + 26 [ label = "crate thiserror 1.0.56" ] + 27 [ label = "crate thiserror-impl 1.0.56" ] + 28 [ label = "crate toml 0.5.11" ] + 29 [ label = "crate unicode-ident 1.0.1" ] + 30 [ label = "crate unicode-xid 0.2.4" ] + 31 [ label = "crate unsigned-varint 0.7.2" ] + 32 [ label = "crate version_check 0.9.4" ] + 33 [ label = "feature std" ] + 34 [ label = "feature alloc" ] + 35 [ label = "feature std" ] + 36 [ label = "feature alloc" ] + 37 [ label = "feature serde-codec" ] + 38 [ label = "feature std" ] + 39 [ label = "feature alloc" ] + 40 [ label = "feature default" ] + 41 [ label = "feature std" ] + 42 [ label = "feature alloc" ] + 43 [ label = "feature parsing" ] + 44 [ label = "feature proc-macro" ] + 45 [ label = "feature default" ] + 46 [ label = "feature std" ] + 47 [ label = "feature std" ] + 48 [ label = "feature derive" ] + 49 [ label = "feature const-generics" ] + 50 [ label = "feature default" ] + 51 [ label = "feature span-locations" ] + 52 [ label = "feature default" ] + 53 [ label = "feature default" ] + 54 [ label = "feature default" ] + 55 [ label = "feature default" ] + 56 [ label = "feature default" ] + 57 [ label = "feature proc-macro" ] + 58 [ label = "feature default" ] + 59 [ label = "feature default" ] + 60 [ label = "feature use_alloc" ] + 61 [ label = "feature use_std" ] + 62 [ label = "feature serde-codec" ] + 63 [ label = "feature std" ] + 64 [ label = "feature default" ] + 65 [ label = "feature proc-macro" ] + 66 [ label = "feature derive" ] + 67 [ label = "feature printing" ] + 68 [ label = "feature clone-impls" ] + 69 [ label = "feature visit" ] + 70 [ label = "feature extra-traits" ] + 71 [ label = "feature default" ] + 72 [ label = "feature default" ] + 73 [ label = "feature alloc" ] + 74 [ label = "feature serde_bytes" ] + 75 [ label = "feature serde" ] + 76 [ label = "feature multibase" ] + 77 [ label = "feature serde" ] + 78 [ label = "feature serde-big-array" ] + 79 [ label = "feature syn-error" ] + 80 [ label = "feature syn" ] + 81 [ label = "feature use_std" ] + 82 [ label = "feature serde_derive" ] + 83 [ label = "feature std" ] + 84 [ label = "feature std" ] + 85 [ label = "feature quote" ] + 86 [ label = "feature quote" ] + 87 [ label = "feature proc-macro" ] + 88 [ label = "feature printing" ] + 89 [ label = "feature parsing" ] + 90 [ label = "feature derive" ] + 91 [ label = "feature clone-impls" ] + 92 [ label = "feature proc-macro" ] + 1 -> 18 [ label = "" ] + 1 -> 33 [ label = "" ] + 2 -> 3 [ label = "" ] + 2 -> 34 [ label = "" ] + 2 -> 9 [ label = "" ] + 2 -> 35 [ label = "" ] + 2 -> 10 [ label = "" ] + 2 -> 36 [ label = "" ] + 2 -> 37 [ label = "" ] + 2 -> 38 [ label = "" ] + 2 -> 18 [ label = "" ] + 2 -> 39 [ label = "" ] + 2 -> 33 [ label = "" ] + 2 -> 40 [ label = "" ] + 2 -> 31 [ label = "" ] + 2 -> 41 [ label = "" ] + 3 -> 8 [ label = "" ] + 5 -> 4 [ label = "" ] + 5 -> 6 [ label = "" ] + 6 -> 42 [ label = "" ] + 6 -> 43 [ label = "" ] + 6 -> 44 [ label = "" ] + 7 -> 45 [ label = " 'cfg(windows)'" ] + 9 -> 0 [ label = "" ] + 9 -> 42 [ label = "" ] + 9 -> 46 [ label = "" ] + 9 -> 5 [ label = "" ] + 10 -> 3 [ label = "" ] + 10 -> 34 [ label = "" ] + 10 -> 11 [ label = "" ] + 10 -> 47 [ label = "" ] + 10 -> 48 [ label = "" ] + 10 -> 49 [ label = "" ] + 10 -> 31 [ label = "" ] + 10 -> 41 [ label = "" ] + 11 -> 12 [ label = "" ] + 11 -> 50 [ label = "" ] + 11 -> 51 [ label = "" ] + 11 -> 52 [ label = "" ] + 11 -> 53 [ label = "" ] + 11 -> 54 [ label = "" ] + 11 -> 55 [ label = "" ] + 12 -> 26 [ label = "" ] + 12 -> 56 [ label = "" ] + 13 -> 14 [ label = "" ] + 13 -> 52 [ label = "" ] + 13 -> 53 [ label = "" ] + 13 -> 23 [ label = "" ] + 13 -> 32 [ label = "(build)" ] + 14 -> 52 [ label = "" ] + 14 -> 53 [ label = "" ] + 14 -> 32 [ label = "(build)" ] + 15 -> 29 [ label = "" ] + 16 -> 15 [ label = "" ] + 16 -> 57 [ label = "" ] + 18 -> 58 [ label = "" ] + 19 -> 18 [ label = "" ] + 20 -> 18 [ label = "" ] + 20 -> 33 [ label = "" ] + 21 -> 52 [ label = "" ] + 21 -> 53 [ label = "" ] + 21 -> 59 [ label = "" ] + 22 -> 60 [ label = "" ] + 22 -> 61 [ label = "" ] + 22 -> 62 [ label = "" ] + 22 -> 63 [ label = "" ] + 22 -> 64 [ label = "" ] + 22 -> 39 [ label = "" ] + 22 -> 33 [ label = "" ] + 23 -> 15 [ label = "" ] + 23 -> 57 [ label = "" ] + 23 -> 16 [ label = "" ] + 23 -> 65 [ label = "" ] + 23 -> 29 [ label = "" ] + 24 -> 15 [ label = "" ] + 24 -> 57 [ label = "" ] + 24 -> 16 [ label = "" ] + 24 -> 65 [ label = "" ] + 24 -> 29 [ label = "" ] + 25 -> 15 [ label = "" ] + 25 -> 57 [ label = "" ] + 25 -> 16 [ label = "" ] + 25 -> 65 [ label = "" ] + 25 -> 66 [ label = "" ] + 25 -> 43 [ label = "" ] + 25 -> 67 [ label = "" ] + 25 -> 68 [ label = "" ] + 25 -> 69 [ label = "" ] + 25 -> 70 [ label = "" ] + 25 -> 44 [ label = "" ] + 25 -> 71 [ label = "" ] + 26 -> 27 [ label = "" ] + 27 -> 52 [ label = "" ] + 27 -> 53 [ label = "" ] + 27 -> 59 [ label = "" ] + 28 -> 72 [ label = "" ] + 61 -> 1 [ label = "" ] + 61 -> 33 [ label = "" ] + 61 -> 60 [ label = "" ] + 60 -> 1 [ label = "" ] + 63 -> 2 [ label = "" ] + 63 -> 38 [ label = "" ] + 63 -> 41 [ label = "" ] + 63 -> 73 [ label = "" ] + 63 -> 35 [ label = "" ] + 63 -> 33 [ label = "" ] + 74 -> 2 [ label = "" ] + 74 -> 20 [ label = "" ] + 62 -> 2 [ label = "" ] + 62 -> 73 [ label = "" ] + 62 -> 75 [ label = "" ] + 62 -> 37 [ label = "" ] + 62 -> 74 [ label = "" ] + 75 -> 2 [ label = "" ] + 75 -> 18 [ label = "" ] + 76 -> 2 [ label = "" ] + 76 -> 9 [ label = "" ] + 73 -> 2 [ label = "" ] + 73 -> 76 [ label = "" ] + 73 -> 36 [ label = "" ] + 73 -> 34 [ label = "" ] + 73 -> 39 [ label = "" ] + 34 -> 3 [ label = "" ] + 46 -> 4 [ label = "" ] + 46 -> 42 [ label = "" ] + 42 -> 4 [ label = "" ] + 35 -> 9 [ label = "" ] + 35 -> 46 [ label = "" ] + 38 -> 10 [ label = "" ] + 38 -> 41 [ label = "" ] + 38 -> 47 [ label = "" ] + 38 -> 36 [ label = "" ] + 37 -> 10 [ label = "" ] + 37 -> 77 [ label = "" ] + 37 -> 78 [ label = "" ] + 78 -> 10 [ label = "" ] + 78 -> 19 [ label = "" ] + 77 -> 10 [ label = "" ] + 77 -> 18 [ label = "" ] + 36 -> 10 [ label = "" ] + 36 -> 34 [ label = "" ] + 47 -> 11 [ label = "" ] + 79 -> 13 [ label = "" ] + 79 -> 80 [ label = "" ] + 80 -> 13 [ label = "" ] + 80 -> 23 [ label = "" ] + 50 -> 13 [ label = "" ] + 50 -> 79 [ label = "" ] + 51 -> 15 [ label = "" ] + 57 -> 15 [ label = "" ] + 52 -> 15 [ label = "" ] + 52 -> 57 [ label = "" ] + 65 -> 16 [ label = "" ] + 65 -> 57 [ label = "" ] + 53 -> 16 [ label = "" ] + 53 -> 65 [ label = "" ] + 81 -> 17 [ label = "" ] + 64 -> 17 [ label = "" ] + 64 -> 81 [ label = "" ] + 33 -> 18 [ label = "" ] + 82 -> 18 [ label = "" ] + 82 -> 21 [ label = "" ] + 48 -> 18 [ label = "" ] + 48 -> 82 [ label = "" ] + 72 -> 18 [ label = "" ] + 72 -> 33 [ label = "" ] + 39 -> 18 [ label = "" ] + 49 -> 19 [ label = "" ] + 83 -> 20 [ label = "" ] + 83 -> 33 [ label = "" ] + 40 -> 20 [ label = "" ] + 40 -> 83 [ label = "" ] + 58 -> 21 [ label = "" ] + 84 -> 22 [ label = "" ] + 84 -> 61 [ label = "" ] + 84 -> 63 [ label = "" ] + 84 -> 33 [ label = "" ] + 45 -> 22 [ label = "" ] + 45 -> 84 [ label = "" ] + 69 -> 23 [ label = "" ] + 85 -> 23 [ label = "" ] + 85 -> 16 [ label = "" ] + 44 -> 23 [ label = "" ] + 44 -> 57 [ label = "" ] + 44 -> 65 [ label = "" ] + 67 -> 23 [ label = "" ] + 67 -> 85 [ label = "" ] + 43 -> 23 [ label = "" ] + 70 -> 23 [ label = "" ] + 66 -> 23 [ label = "" ] + 54 -> 23 [ label = "" ] + 54 -> 66 [ label = "" ] + 54 -> 43 [ label = "" ] + 54 -> 67 [ label = "" ] + 54 -> 68 [ label = "" ] + 54 -> 44 [ label = "" ] + 68 -> 23 [ label = "" ] + 86 -> 24 [ label = "" ] + 86 -> 16 [ label = "" ] + 87 -> 24 [ label = "" ] + 87 -> 57 [ label = "" ] + 87 -> 65 [ label = "" ] + 88 -> 24 [ label = "" ] + 88 -> 86 [ label = "" ] + 89 -> 24 [ label = "" ] + 90 -> 24 [ label = "" ] + 59 -> 24 [ label = "" ] + 59 -> 90 [ label = "" ] + 59 -> 89 [ label = "" ] + 59 -> 88 [ label = "" ] + 59 -> 91 [ label = "" ] + 59 -> 87 [ label = "" ] + 91 -> 24 [ label = "" ] + 92 -> 25 [ label = "" ] + 92 -> 57 [ label = "" ] + 92 -> 44 [ label = "" ] + 92 -> 65 [ label = "" ] + 55 -> 25 [ label = "" ] + 55 -> 92 [ label = "" ] + 56 -> 28 [ label = "" ] + 71 -> 30 [ label = "" ] + 41 -> 31 [ label = "" ] +} +