1 //! Tests for the `cargo tree` command.
3 use super::features2
::switch_to_resolver_2
;
4 use cargo_test_support
::cross_compile
::{self, alternate}
;
5 use cargo_test_support
::registry
::{Dependency, Package}
;
6 use cargo_test_support
::{basic_manifest, git, project, rustc_host, Project}
;
8 fn make_simple_proj() -> Project
{
9 Package
::new("c", "1.0.0").publish();
10 Package
::new("b", "1.0.0").dep("c", "1.0").publish();
11 Package
::new("a", "1.0.0").dep("b", "1.0").publish();
12 Package
::new("bdep", "1.0.0").dep("b", "1.0").publish();
13 Package
::new("devdep", "1.0.0").dep("b", "1.0.0").publish();
34 .file("src/lib.rs", "")
35 .file("build.rs", "fn main() {}")
41 // A simple test with a few different dependencies.
42 let p
= make_simple_proj();
62 p
.cargo("tree -p bdep")
74 fn virtual_workspace() {
75 // Multiple packages in a virtual workspace.
76 Package
::new("somedep", "1.0.0").publish();
82 members = ["a", "baz", "c"]
85 .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
86 .file("a/src/lib.rs", "")
99 .file("baz/src/lib.rs", "")
100 .file("c/Cargo.toml", &basic_manifest("c", "1.0.0"))
101 .file("c/src/lib.rs", "")
107 a v1.0.0 ([..]/foo/a)
109 baz v0.1.0 ([..]/foo/baz)
110 ├── c v1.0.0 ([..]/foo/c)
113 c v1.0.0 ([..]/foo/c)
118 p
.cargo("tree -p a").with_stdout("a v1.0.0 [..]").run();
124 baz v0.1.0 ([..]/foo/baz)
125 ├── c v1.0.0 ([..]/foo/c)
132 p
.cargo("tree --workspace --exclude baz")
135 a v1.0.0 ([..]/foo/a)
137 c v1.0.0 ([..]/foo/c)
143 p
.cargo("tree --workspace --exclude '*z'")
146 a v1.0.0 ([..]/foo/a)
148 c v1.0.0 ([..]/foo/c)
154 p
.cargo("tree -p '*z'")
157 baz v0.1.0 ([..]/foo/baz)
158 ├── c v1.0.0 ([..]/foo/c)
167 // Works around https://github.com/rust-lang/cargo/issues/7985
168 Package
::new("bitflags", "1.0.0").publish();
169 Package
::new("manyfeat", "1.0.0")
173 .dep("bitflags", "1.0")
175 Package
::new("a", "1.0.0")
176 .feature_dep("manyfeat", "1.0", &["f1"])
178 Package
::new("b", "1.0.0")
179 .feature_dep("manyfeat", "1.0", &["f2"])
181 Package
::new("c", "1.0.0")
182 .feature_dep("manyfeat", "1.0", &["f3"])
199 .file("src/lib.rs", "")
205 foo v0.1.0 ([..]/foo)
207 │ └── manyfeat v1.0.0
208 │ └── bitflags v1.0.0
210 │ └── manyfeat v1.0.0 (*)
212 └── manyfeat v1.0.0 (*)
220 // Handles renamed dependencies.
221 Package
::new("one", "1.0.0").publish();
222 Package
::new("two", "1.0.0").publish();
223 Package
::new("bar", "1.0.0").dep("one", "1.0").publish();
224 Package
::new("bar", "2.0.0").dep("two", "1.0").publish();
234 bar1 = {version = "1.0", package="bar"}
235 bar2 = {version = "2.0", package="bar"}
238 .file("src/lib.rs", "")
244 foo v1.0.0 ([..]/foo)
256 // Handles git and path sources.
257 Package
::new("regdep", "1.0.0").publish();
258 let git_project
= git
::new("gitdep", |p
| {
259 p
.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0"))
260 .file("src/lib.rs", "")
273 pathdep = {{ path = "pathdep" }}
274 gitdep = {{ git = "{}" }}
279 .file("src
/lib
.rs
", "")
280 .file("pathdep
/Cargo
.toml
", &basic_manifest("pathdep
", "1.0.0"))
281 .file("pathdep
/src
/lib
.rs
", "")
287 foo v0
.1
.0 ([..]/foo
)
288 ├── gitdep v1
.0
.0 (file
://[..]/gitdep#[..])
289 ├── pathdep v1
.0
.0 ([..]/foo
/pathdep
)
298 // Exercises a variety of feature behaviors.
299 Package::new("optdep_default
", "1.0.0").publish();
300 Package::new("optdep
", "1.0.0").publish();
310 optdep_default
= { version = "1.0", optional = true }
311 optdep
= { version = "1.0", optional = true }
314 default = ["optdep_default"]
317 .file("src
/lib
.rs
", "")
324 └── optdep_default v1
.0
.0
329 p.cargo("tree
--no
-default-features
")
337 p.cargo("tree
--all
-features
")
342 └── optdep_default v1
.0
.0
347 p.cargo("tree
--features optdep
")
352 └── optdep_default v1
.0
.0
359 fn filters_target() {
361 if cross_compile::disabled() {
364 Package::new("targetdep
", "1.0.0").publish();
365 Package::new("hostdep
", "1.0.0").publish();
366 Package::new("devdep
", "1.0.0").publish();
367 Package::new("build_target_dep
", "1.0.0").publish();
368 Package::new("build_host_dep
", "1.0.0")
369 .target_dep("targetdep
", "1.0", alternate())
370 .target_dep("hostdep
", "1.0", rustc_host())
372 Package::new("pm_target
", "1.0.0")
375 Package::new("pm_host
", "1.0.0").proc_macro(true).publish();
386 [target
.'{alt}'
.dependencies
]
390 [target
.'{host}'
.dependencies
]
394 [target
.'{alt}'
.dev
-dependencies
]
397 [target
.'{alt}'
.build
-dependencies
]
398 build_target_dep
= "1.0"
400 [target
.'{host}'
.build
-dependencies
]
401 build_host_dep
= "1.0"
407 .file("src
/lib
.rs
", "")
408 .file("build
.rs
", "fn main() {}
")
414 foo v0
.1
.0 ([..]/foo
)
416 └── pm_host v1
.0
.0 (proc
-macro)
418 └── build_host_dep v1
.0
.0
424 p.cargo("tree
--target
")
428 foo v0
.1
.0 ([..]/foo
)
429 ├── pm_target v1
.0
.0 (proc
-macro)
432 └── build_host_dep v1
.0
.0
440 p.cargo("tree
--target
")
444 foo v0
.1
.0 ([..]/foo
)
446 └── pm_host v1
.0
.0 (proc
-macro)
448 └── build_host_dep v1
.0
.0
454 p.cargo("tree
--target
=all
")
457 foo v0
.1
.0 ([..]/foo
)
459 ├── pm_host v1
.0
.0 (proc
-macro)
460 ├── pm_target v1
.0
.0 (proc
-macro)
463 ├── build_host_dep v1
.0
.0
465 │ └── targetdep v1
.0
.0
466 └── build_target_dep v1
.0
.0
474 p.cargo("tree
--target
=all
-e no
-proc
-macro")
477 foo v0
.1
.0 ([..]/foo
)
481 ├── build_host_dep v1
.0
.0
483 │ └── targetdep v1
.0
.0
484 └── build_target_dep v1
.0
.0
494 Package::new("inner
-devdep
", "1.0.0").publish();
495 Package::new("inner
-builddep
", "1.0.0").publish();
496 Package::new("inner
-normal
", "1.0.0").publish();
497 Package::new("inner
-pm
", "1.0.0").proc_macro(true).publish();
498 Package::new("inner
-buildpm
", "1.0.0")
501 Package::new("normaldep
", "1.0.0")
502 .dep("inner
-normal
", "1.0")
503 .dev_dep("inner
-devdep
", "1.0")
504 .build_dep("inner
-builddep
", "1.0")
506 Package::new("devdep
", "1.0.0")
507 .dep("inner
-normal
", "1.0")
508 .dep("inner
-pm
", "1.0")
509 .dev_dep("inner
-devdep
", "1.0")
510 .build_dep("inner
-builddep
", "1.0")
511 .build_dep("inner
-buildpm
", "1.0")
513 Package::new("builddep
", "1.0.0")
514 .dep("inner
-normal
", "1.0")
515 .dev_dep("inner
-devdep
", "1.0")
516 .build_dep("inner
-builddep
", "1.0")
536 .file("src
/lib
.rs
", "")
542 foo v0
.1
.0 ([..]/foo
)
544 └── inner
-normal v1
.0
.0
546 └── inner
-builddep v1
.0
.0
549 └── inner
-normal v1
.0
.0
551 └── inner
-builddep v1
.0
.0
554 ├── inner
-normal v1
.0
.0
555 └── inner
-pm v1
.0
.0 (proc
-macro)
557 ├── inner
-builddep v1
.0
.0
558 └── inner
-buildpm v1
.0
.0 (proc
-macro)
563 p.cargo("tree
-e no
-dev
")
566 foo v0
.1
.0 ([..]/foo
)
568 └── inner
-normal v1
.0
.0
570 └── inner
-builddep v1
.0
.0
573 └── inner
-normal v1
.0
.0
575 └── inner
-builddep v1
.0
.0
580 p.cargo("tree
-e normal
")
583 foo v0
.1
.0 ([..]/foo
)
585 └── inner
-normal v1
.0
.0
590 p.cargo("tree
-e dev
,build
")
593 foo v0
.1
.0 ([..]/foo
)
597 └── inner
-builddep v1
.0
.0
601 ├── inner
-builddep v1
.0
.0
602 └── inner
-buildpm v1
.0
.0 (proc
-macro)
607 p.cargo("tree
-e dev
,build
,no
-proc
-macro")
610 foo v0
.1
.0 ([..]/foo
)
614 └── inner
-builddep v1
.0
.0
618 └── inner
-builddep v1
.0
.0
625 fn cyclic_dev_dep() {
626 // Cyclical dev-dependency and inverse flag.
636 dev
-dep
= { path = "dev-dep" }
639 .file("src
/lib
.rs
", "")
641 "dev
-dep
/Cargo
.toml
",
651 .file("dev
-dep
/src
/lib
.rs
", "")
657 foo v0
.1
.0 ([..]/foo
)
659 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
660 └── foo v0
.1
.0 ([..]/foo
) (*)
665 p.cargo("tree
--invert foo
")
668 foo v0
.1
.0 ([..]/foo
)
669 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
671 └── foo v0
.1
.0 ([..]/foo
) (*)
679 Package::new("b1
", "1.0.0").dep("c
", "1.0").publish();
680 Package::new("b2
", "1.0.0").dep("d
", "1.0").publish();
681 Package::new("c
", "1.0.0").publish();
682 Package::new("d
", "1.0.0").publish();
697 .file("src
/lib
.rs
", "")
703 foo v0
.1
.0 ([..]/foo
)
713 p.cargo("tree
--invert c
")
718 │ └── foo v0
.1
.0 ([..]/foo
)
719 └── foo v0
.1
.0 ([..]/foo
)
726 fn invert_with_build_dep() {
727 // -i for a common dependency between normal and build deps.
728 Package::new("common
", "1.0.0").publish();
729 Package::new("bdep
", "1.0.0").dep("common
", "1.0").publish();
745 .file("src
/lib
.rs
", "")
751 foo v0
.1
.0 ([..]/foo
)
760 p.cargo("tree
-i common
")
765 │
[build
-dependencies
]
766 │ └── foo v0
.1
.0 ([..]/foo
)
767 └── foo v0
.1
.0 ([..]/foo
)
775 let p = make_simple_proj();
777 p.cargo("tree
--prefix
=none
")
780 foo v0
.1
.0 ([..]/foo
)
796 let p = make_simple_proj();
798 p.cargo("tree
--prefix
=depth
")
801 0foo v0
.1
.0 ([..]/foo
)
817 let p = make_simple_proj();
819 p.cargo("tree
--no
-dedupe
")
822 foo v0
.1
.0 ([..]/foo
)
841 fn no_dedupe_cycle() {
842 // --no-dedupe with a dependency cycle
855 .file("src
/lib
.rs
", "")
867 .file("bar
/src
/lib
.rs
", "")
873 foo v0
.1
.0 ([..]/foo
)
875 └── bar v0
.1
.0 ([..]/foo
/bar
)
876 └── foo v0
.1
.0 ([..]/foo
) (*)
881 p.cargo("tree
--no
-dedupe
")
884 foo v0
.1
.0 ([..]/foo
)
886 └── bar v0
.1
.0 ([..]/foo
/bar
)
887 └── foo v0
.1
.0 ([..]/foo
) (*)
895 Package::new("dog
", "1.0.0").publish();
896 Package::new("dog
", "2.0.0").publish();
897 Package::new("cat
", "1.0.0").publish();
898 Package::new("cat
", "2.0.0").publish();
899 Package::new("dep
", "1.0.0")
919 dog1
= { version = "1.0", package = "dog" }
920 dog2
= { version = "2.0", package = "dog" }
923 .file("a
/src
/lib
.rs
", "")
936 .file("b
/src
/lib
.rs
", "")
942 a v0
.1
.0 ([..]/foo
/a
)
952 b v0
.1
.0 ([..]/foo
/b
)
961 p.cargo("tree
-p a
-d
")
965 └── a v0
.1
.0 ([..]/foo
/a
)
968 └── a v0
.1
.0 ([..]/foo
/a
)
973 p.cargo("tree
-p b
-d
")
978 └── b v0
.1
.0 ([..]/foo
/b
)
981 └── b v0
.1
.0 ([..]/foo
/b
)
989 let p = make_simple_proj();
990 p.cargo("tree
--charset ascii
")
993 foo v0
.1
.0 ([..]/foo
)
1011 Package::new("dep
", "1.0.0").publish();
1012 Package::new("other
-dep
", "1.0.0").publish();
1014 Package::new("dep_that_is_awesome
", "1.0.0")
1019 name
= "dep_that_is_awesome"
1023 name
= "awesome_dep"
1026 .file("src
/lib
.rs
", "pub struct Straw
;")
1037 repository
= "https://github.com/rust-lang/cargo"
1040 dep
= {version="1.0", optional=true}
1041 other
-dep
= {version="1.0", optional=true}
1042 dep_that_is_awesome
= {version="1.0", optional=true}
1051 .file("src
/main
.rs
", "")
1054 p.cargo("tree
--format
<<<{p}
>>>")
1055 .with_stdout("<<<foo v0
.1
.0 ([..]/foo
)>>>")
1058 p.cargo("tree
--format {}
")
1061 [ERROR
] tree format `{}` not valid
1064 unsupported pattern ``
1070 p.cargo("tree
--format {p}
-{{hello}
}")
1071 .with_stdout("foo v0
.1
.0 ([..]/foo
)-{hello}
")
1074 p.cargo("tree
--format
")
1076 .with_stdout("foo v0
.1
.0 ([..]/foo
) MIT https
://github.com/rust-lang/cargo")
1079 p
.cargo("tree --format")
1081 .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo")
1084 p
.cargo("tree --all-features --format")
1088 foo v0.1.0 ([..]/foo) [bar,default,dep,dep_that_is_awesome,foo,other-dep]
1090 ├── dep_that_is_awesome v1.0.0 []
1091 └── other-dep v1.0.0 []
1097 .arg("--features=other-dep,dep_that_is_awesome")
1098 .arg("--format={lib}")
1109 fn dev_dep_feature() {
1110 // New feature resolver with optional dep
1111 Package
::new("optdep", "1.0.0").publish();
1112 Package
::new("bar", "1.0.0")
1113 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1124 bar = { version = "1.0", features = ["optdep"] }
1130 .file("src/lib.rs", "")
1137 foo v0.1.0 ([..]/foo)
1146 p
.cargo("tree -e normal")
1149 foo v0.1.0 ([..]/foo)
1157 switch_to_resolver_2(&p
);
1162 foo v0.1.0 ([..]/foo)
1171 p
.cargo("tree -e normal")
1174 foo v0.1.0 ([..]/foo)
1182 fn host_dep_feature() {
1183 // New feature resolver with optional build dep
1184 Package
::new("optdep", "1.0.0").publish();
1185 Package
::new("bar", "1.0.0")
1186 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1196 [build-dependencies]
1197 bar = { version = "1.0", features = ["optdep"] }
1203 .file("src/lib.rs", "")
1204 .file("build.rs", "fn main() {}")
1211 foo v0.1.0 ([..]/foo)
1214 [build-dependencies]
1221 p
.cargo("tree -p bar")
1231 p
.cargo("tree -i optdep")
1236 └── foo v0.1.0 ([..]/foo)
1237 [build-dependencies]
1238 └── foo v0.1.0 ([..]/foo)
1244 switch_to_resolver_2(&p
);
1249 foo v0.1.0 ([..]/foo)
1251 [build-dependencies]
1258 p
.cargo("tree -p bar")
1269 p
.cargo("tree -i optdep")
1274 [build-dependencies]
1275 └── foo v0.1.0 ([..]/foo)
1280 // Check that -d handles duplicates with features.
1285 └── foo v0.1.0 ([..]/foo)
1288 [build-dependencies]
1289 └── foo v0.1.0 ([..]/foo)
1296 fn proc_macro_features() {
1297 // New feature resolver with a proc-macro
1298 Package
::new("optdep", "1.0.0").publish();
1299 Package
::new("somedep", "1.0.0")
1300 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1302 Package
::new("pm", "1.0.0")
1304 .feature_dep("somedep", "1.0", &["optdep"])
1319 .file("src/lib.rs", "")
1326 foo v0.1.0 ([..]/foo)
1327 ├── pm v1.0.0 (proc-macro)
1328 │ └── somedep v1.0.0
1330 └── somedep v1.0.0 (*)
1335 // Old behavior + no-proc-macro
1336 p
.cargo("tree -e no-proc-macro")
1339 foo v0.1.0 ([..]/foo)
1347 p
.cargo("tree -p somedep")
1356 // -p -e no-proc-macro
1357 p
.cargo("tree -p somedep -e no-proc-macro")
1367 p
.cargo("tree -i somedep")
1371 ├── foo v0.1.0 ([..]/foo)
1372 └── pm v1.0.0 (proc-macro)
1373 └── foo v0.1.0 ([..]/foo)
1378 // invert + no-proc-macro
1379 p
.cargo("tree -i somedep -e no-proc-macro")
1383 └── foo v0.1.0 ([..]/foo)
1389 switch_to_resolver_2(&p
);
1391 // Note the missing (*)
1395 foo v0.1.0 ([..]/foo)
1396 ├── pm v1.0.0 (proc-macro)
1397 │ └── somedep v1.0.0
1404 p
.cargo("tree -e no-proc-macro")
1407 foo v0.1.0 ([..]/foo)
1413 p
.cargo("tree -p somedep")
1424 p
.cargo("tree -i somedep")
1428 └── foo v0.1.0 ([..]/foo)
1431 └── pm v1.0.0 (proc-macro)
1432 └── foo v0.1.0 ([..]/foo)
1437 p
.cargo("tree -i somedep -e no-proc-macro")
1441 └── foo v0.1.0 ([..]/foo)
1450 fn itarget_opt_dep() {
1451 // New feature resolver with optional target dep
1452 Package
::new("optdep", "1.0.0").publish();
1453 Package
::new("common", "1.0.0")
1454 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1468 [target.'cfg(whatever)'.dependencies]
1469 common = { version = "1.0", features = ["optdep"] }
1473 .file("src/lib.rs", "")
1480 foo v1.0.0 ([..]/foo)
1488 switch_to_resolver_2(&p
);
1493 foo v1.0.0 ([..]/foo)
1501 fn ambiguous_name() {
1502 // -p that is ambiguous.
1503 Package
::new("dep", "1.0.0").publish();
1504 Package
::new("dep", "2.0.0").publish();
1505 Package
::new("bar", "1.0.0").dep("dep", "2.0").publish();
1519 .file("src/lib.rs", "")
1522 p
.cargo("tree -p dep")
1523 .with_stderr_contains(
1525 error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
1526 Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
1536 fn workspace_features_are_local() {
1537 // The features for workspace packages should be the same as `cargo build`
1538 // (i.e., the features selected depend on the "current" package).
1539 Package
::new("optdep", "1.0.0").publish();
1540 Package
::new("somedep", "1.0.0")
1541 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1548 members = ["a", "b"]
1559 somedep = {version="1.0", features=["optdep"]}
1562 .file("a/src/lib.rs", "")
1574 .file("b/src/lib.rs", "")
1580 a v0.1.0 ([..]/foo/a)
1584 b v0.1.0 ([..]/foo/b)
1585 └── somedep v1.0.0 (*)
1590 p
.cargo("tree -p a")
1593 a v0.1.0 ([..]/foo/a)
1600 p
.cargo("tree -p b")
1603 b v0.1.0 ([..]/foo/b)
1611 fn unknown_edge_kind() {
1613 .file("Cargo.toml", "")
1614 .file("src/lib.rs", "")
1617 p
.cargo("tree -e unknown")
1620 [ERROR] unknown edge kind `unknown`, valid values are \
1621 \"normal\", \"build\", \"dev\", \
1622 \"no-normal\", \"no-build\", \"no-dev\", \"no-proc-macro\", \
1623 \"features\", or \"all\"
1631 fn mixed_no_edge_kinds() {
1641 .file("src/lib.rs", "")
1644 p
.cargo("tree -e no-build,normal")
1647 [ERROR] `normal` dependency kind cannot be mixed with \
1648 \"no-normal\", \"no-build\", or \"no-dev\" dependency kinds
1654 // `no-proc-macro` can be mixed with others
1655 p
.cargo("tree -e no-proc-macro,normal")
1658 foo v0.1.0 ([..]/foo)
1666 let p
= make_simple_proj();
1668 p
.cargo("tree --depth 0")
1671 foo v0.1.0 ([..]/foo)
1672 [build-dependencies]
1678 p
.cargo("tree --depth 1")
1681 foo v0.1.0 ([..]/foo)
1684 [build-dependencies]
1692 p
.cargo("tree --depth 2")
1695 foo v0.1.0 ([..]/foo)
1699 [build-dependencies]
1709 // specify a package
1710 p
.cargo("tree -p bdep --depth 1")
1720 p
.cargo("tree --depth 1 --prefix depth")
1723 0foo v0.1.0 ([..]/foo)
1733 p
.cargo("tree --depth 1 -e no-dev")
1736 foo v0.1.0 ([..]/foo)
1739 [build-dependencies]
1746 p
.cargo("tree --depth 1 --invert c")
1751 └── foo v0.1.0 ([..]/foo)
1759 let p
= make_simple_proj();
1761 p
.cargo("tree --prune c")
1764 foo v0.1.0 ([..]/foo)
1767 [build-dependencies]
1778 p
.cargo("tree --prune c --prune bdep")
1781 foo v0.1.0 ([..]/foo)
1784 [build-dependencies]
1793 p
.cargo("tree --prune c -e normal")
1796 foo v0.1.0 ([..]/foo)
1803 // pruning self does not works
1804 p
.cargo("tree --prune foo")
1807 foo v0.1.0 ([..]/foo)
1812 [build-dependencies]
1823 p
.cargo("tree --prune no-dep")
1826 [ERROR] package ID specification `no-dep` did not match any packages
1828 <tab>Did you mean `bdep`?