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();
1020 repository
= "https://github.com/rust-lang/cargo"
1023 dep
= {version="1.0", optional=true}
1031 .file("src
/lib
.rs
", "")
1034 p.cargo("tree
--format
<<<{p}
>>>")
1035 .with_stdout("<<<foo v0
.1
.0 ([..]/foo
)>>>")
1038 p.cargo("tree
--format {}
")
1041 [ERROR
] tree format `{}` not valid
1044 unsupported pattern ``
1050 p.cargo("tree
--format {p}
-{{hello}
}")
1051 .with_stdout("foo v0
.1
.0 ([..]/foo
)-{hello}
")
1054 p.cargo("tree
--format
")
1056 .with_stdout("foo v0
.1
.0 ([..]/foo
) MIT https
://github.com/rust-lang/cargo")
1059 p
.cargo("tree --format")
1061 .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo")
1064 p
.cargo("tree --all-features --format")
1068 foo v0.1.0 ([..]/foo) [bar,default,dep,foo]
1076 fn dev_dep_feature() {
1077 // New feature resolver with optional dep
1078 Package
::new("optdep", "1.0.0").publish();
1079 Package
::new("bar", "1.0.0")
1080 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1091 bar = { version = "1.0", features = ["optdep"] }
1097 .file("src/lib.rs", "")
1104 foo v0.1.0 ([..]/foo)
1113 p
.cargo("tree -e normal")
1116 foo v0.1.0 ([..]/foo)
1124 switch_to_resolver_2(&p
);
1129 foo v0.1.0 ([..]/foo)
1138 p
.cargo("tree -e normal")
1141 foo v0.1.0 ([..]/foo)
1149 fn host_dep_feature() {
1150 // New feature resolver with optional build dep
1151 Package
::new("optdep", "1.0.0").publish();
1152 Package
::new("bar", "1.0.0")
1153 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1163 [build-dependencies]
1164 bar = { version = "1.0", features = ["optdep"] }
1170 .file("src/lib.rs", "")
1171 .file("build.rs", "fn main() {}")
1178 foo v0.1.0 ([..]/foo)
1181 [build-dependencies]
1188 p
.cargo("tree -p bar")
1198 p
.cargo("tree -i optdep")
1203 └── foo v0.1.0 ([..]/foo)
1204 [build-dependencies]
1205 └── foo v0.1.0 ([..]/foo)
1211 switch_to_resolver_2(&p
);
1216 foo v0.1.0 ([..]/foo)
1218 [build-dependencies]
1225 p
.cargo("tree -p bar")
1236 p
.cargo("tree -i optdep")
1241 [build-dependencies]
1242 └── foo v0.1.0 ([..]/foo)
1247 // Check that -d handles duplicates with features.
1252 └── foo v0.1.0 ([..]/foo)
1255 [build-dependencies]
1256 └── foo v0.1.0 ([..]/foo)
1263 fn proc_macro_features() {
1264 // New feature resolver with a proc-macro
1265 Package
::new("optdep", "1.0.0").publish();
1266 Package
::new("somedep", "1.0.0")
1267 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1269 Package
::new("pm", "1.0.0")
1271 .feature_dep("somedep", "1.0", &["optdep"])
1286 .file("src/lib.rs", "")
1293 foo v0.1.0 ([..]/foo)
1294 ├── pm v1.0.0 (proc-macro)
1295 │ └── somedep v1.0.0
1297 └── somedep v1.0.0 (*)
1302 // Old behavior + no-proc-macro
1303 p
.cargo("tree -e no-proc-macro")
1306 foo v0.1.0 ([..]/foo)
1314 p
.cargo("tree -p somedep")
1323 // -p -e no-proc-macro
1324 p
.cargo("tree -p somedep -e no-proc-macro")
1334 p
.cargo("tree -i somedep")
1338 ├── foo v0.1.0 ([..]/foo)
1339 └── pm v1.0.0 (proc-macro)
1340 └── foo v0.1.0 ([..]/foo)
1345 // invert + no-proc-macro
1346 p
.cargo("tree -i somedep -e no-proc-macro")
1350 └── foo v0.1.0 ([..]/foo)
1356 switch_to_resolver_2(&p
);
1358 // Note the missing (*)
1362 foo v0.1.0 ([..]/foo)
1363 ├── pm v1.0.0 (proc-macro)
1364 │ └── somedep v1.0.0
1371 p
.cargo("tree -e no-proc-macro")
1374 foo v0.1.0 ([..]/foo)
1380 p
.cargo("tree -p somedep")
1391 p
.cargo("tree -i somedep")
1395 └── foo v0.1.0 ([..]/foo)
1398 └── pm v1.0.0 (proc-macro)
1399 └── foo v0.1.0 ([..]/foo)
1404 p
.cargo("tree -i somedep -e no-proc-macro")
1408 └── foo v0.1.0 ([..]/foo)
1417 fn itarget_opt_dep() {
1418 // New feature resolver with optional target dep
1419 Package
::new("optdep", "1.0.0").publish();
1420 Package
::new("common", "1.0.0")
1421 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1435 [target.'cfg(whatever)'.dependencies]
1436 common = { version = "1.0", features = ["optdep"] }
1440 .file("src/lib.rs", "")
1447 foo v1.0.0 ([..]/foo)
1455 switch_to_resolver_2(&p
);
1460 foo v1.0.0 ([..]/foo)
1468 fn ambiguous_name() {
1469 // -p that is ambiguous.
1470 Package
::new("dep", "1.0.0").publish();
1471 Package
::new("dep", "2.0.0").publish();
1472 Package
::new("bar", "1.0.0").dep("dep", "2.0").publish();
1486 .file("src/lib.rs", "")
1489 p
.cargo("tree -p dep")
1490 .with_stderr_contains(
1492 error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
1493 Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
1503 fn workspace_features_are_local() {
1504 // The features for workspace packages should be the same as `cargo build`
1505 // (i.e., the features selected depend on the "current" package).
1506 Package
::new("optdep", "1.0.0").publish();
1507 Package
::new("somedep", "1.0.0")
1508 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1515 members = ["a", "b"]
1526 somedep = {version="1.0", features=["optdep"]}
1529 .file("a/src/lib.rs", "")
1541 .file("b/src/lib.rs", "")
1547 a v0.1.0 ([..]/foo/a)
1551 b v0.1.0 ([..]/foo/b)
1552 └── somedep v1.0.0 (*)
1557 p
.cargo("tree -p a")
1560 a v0.1.0 ([..]/foo/a)
1567 p
.cargo("tree -p b")
1570 b v0.1.0 ([..]/foo/b)
1578 fn unknown_edge_kind() {
1580 .file("Cargo.toml", "")
1581 .file("src/lib.rs", "")
1584 p
.cargo("tree -e unknown")
1587 [ERROR] unknown edge kind `unknown`, valid values are \
1588 \"normal\", \"build\", \"dev\", \
1589 \"no-normal\", \"no-build\", \"no-dev\", \"no-proc-macro\", \
1590 \"features\", or \"all\"
1598 fn mixed_no_edge_kinds() {
1608 .file("src/lib.rs", "")
1611 p
.cargo("tree -e no-build,normal")
1614 [ERROR] `normal` dependency kind cannot be mixed with \
1615 \"no-normal\", \"no-build\", or \"no-dev\" dependency kinds
1621 // `no-proc-macro` can be mixed with others
1622 p
.cargo("tree -e no-proc-macro,normal")
1625 foo v0.1.0 ([..]/foo)
1633 let p
= make_simple_proj();
1635 p
.cargo("tree --depth 0")
1638 foo v0.1.0 ([..]/foo)
1639 [build-dependencies]
1645 p
.cargo("tree --depth 1")
1648 foo v0.1.0 ([..]/foo)
1651 [build-dependencies]
1659 p
.cargo("tree --depth 2")
1662 foo v0.1.0 ([..]/foo)
1666 [build-dependencies]
1676 // specify a package
1677 p
.cargo("tree -p bdep --depth 1")
1687 p
.cargo("tree --depth 1 --prefix depth")
1690 0foo v0.1.0 ([..]/foo)
1700 p
.cargo("tree --depth 1 -e no-dev")
1703 foo v0.1.0 ([..]/foo)
1706 [build-dependencies]
1713 p
.cargo("tree --depth 1 --invert c")
1718 └── foo v0.1.0 ([..]/foo)
1726 let p
= make_simple_proj();
1728 p
.cargo("tree --prune c")
1731 foo v0.1.0 ([..]/foo)
1734 [build-dependencies]
1745 p
.cargo("tree --prune c --prune bdep")
1748 foo v0.1.0 ([..]/foo)
1751 [build-dependencies]
1760 p
.cargo("tree --prune c -e normal")
1763 foo v0.1.0 ([..]/foo)
1770 // pruning self does not works
1771 p
.cargo("tree --prune foo")
1774 foo v0.1.0 ([..]/foo)
1779 [build-dependencies]
1790 p
.cargo("tree --prune no-dep")
1793 [ERROR] package ID specification `no-dep` did not match any packages
1795 <tab>Did you mean `bdep`?