1 //! Tests for the `cargo tree` command.
3 use cargo_test_support
::cross_compile
::alternate
;
4 use cargo_test_support
::registry
::{Dependency, Package}
;
5 use cargo_test_support
::{basic_manifest, git, project, rustc_host, Project}
;
7 fn make_simple_proj() -> Project
{
8 Package
::new("c", "1.0.0").publish();
9 Package
::new("b", "1.0.0").dep("c", "1.0").publish();
10 Package
::new("a", "1.0.0").dep("b", "1.0").publish();
11 Package
::new("bdep", "1.0.0").dep("b", "1.0").publish();
12 Package
::new("devdep", "1.0.0").dep("b", "1.0.0").publish();
33 .file("src/lib.rs", "")
34 .file("build.rs", "fn main() {}")
40 // A simple test with a few different dependencies.
41 let p
= make_simple_proj();
61 p
.cargo("tree -p bdep")
73 fn virtual_workspace() {
74 // Multiple packages in a virtual workspace.
75 Package
::new("somedep", "1.0.0").publish();
81 members = ["a", "b", "c"]
84 .file("a/Cargo.toml", &basic_manifest("a", "1.0.0"))
85 .file("a/src/lib.rs", "")
98 .file("b/src/lib.rs", "")
99 .file("c/Cargo.toml", &basic_manifest("c", "1.0.0"))
100 .file("c/src/lib.rs", "")
106 a v1.0.0 ([..]/foo/a)
108 b v0.1.0 ([..]/foo/b)
109 ├── c v1.0.0 ([..]/foo/c)
112 c v1.0.0 ([..]/foo/c)
117 p
.cargo("tree -p a").with_stdout("a v1.0.0 [..]").run();
123 b v0.1.0 ([..]/foo/b)
124 ├── c v1.0.0 ([..]/foo/c)
133 // Works around https://github.com/rust-lang/cargo/issues/7985
134 Package
::new("bitflags", "1.0.0").publish();
135 Package
::new("manyfeat", "1.0.0")
139 .dep("bitflags", "1.0")
141 Package
::new("a", "1.0.0")
142 .feature_dep("manyfeat", "1.0", &["f1"])
144 Package
::new("b", "1.0.0")
145 .feature_dep("manyfeat", "1.0", &["f2"])
147 Package
::new("c", "1.0.0")
148 .feature_dep("manyfeat", "1.0", &["f3"])
165 .file("src/lib.rs", "")
171 foo v0.1.0 ([..]/foo)
173 │ └── manyfeat v1.0.0
174 │ └── bitflags v1.0.0
176 │ └── manyfeat v1.0.0 (*)
178 └── manyfeat v1.0.0 (*)
186 // Handles renamed dependencies.
187 Package
::new("one", "1.0.0").publish();
188 Package
::new("two", "1.0.0").publish();
189 Package
::new("bar", "1.0.0").dep("one", "1.0").publish();
190 Package
::new("bar", "2.0.0").dep("two", "1.0").publish();
200 bar1 = {version = "1.0", package="bar"}
201 bar2 = {version = "2.0", package="bar"}
204 .file("src/lib.rs", "")
210 foo v1.0.0 ([..]/foo)
222 // Handles git and path sources.
223 Package
::new("regdep", "1.0.0").publish();
224 let git_project
= git
::new("gitdep", |p
| {
225 p
.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0"))
226 .file("src/lib.rs", "")
239 pathdep = {{ path = "pathdep" }}
240 gitdep = {{ git = "{}" }}
245 .file("src
/lib
.rs
", "")
246 .file("pathdep
/Cargo
.toml
", &basic_manifest("pathdep
", "1.0.0"))
247 .file("pathdep
/src
/lib
.rs
", "")
253 foo v0
.1
.0 ([..]/foo
)
254 ├── gitdep v1
.0
.0 (file
://[..]/gitdep#[..])
255 ├── pathdep v1
.0
.0 ([..]/foo
/pathdep
)
264 // Exercises a variety of feature behaviors.
265 Package::new("optdep_default
", "1.0.0").publish();
266 Package::new("optdep
", "1.0.0").publish();
276 optdep_default
= { version = "1.0", optional = true }
277 optdep
= { version = "1.0", optional = true }
280 default = ["optdep_default"]
283 .file("src
/lib
.rs
", "")
290 └── optdep_default v1
.0
.0
295 p.cargo("tree
--no
-default-features
")
303 p.cargo("tree
--all
-features
")
308 └── optdep_default v1
.0
.0
313 p.cargo("tree
--features optdep
")
318 └── optdep_default v1
.0
.0
325 fn filters_target() {
327 Package::new("targetdep
", "1.0.0").publish();
328 Package::new("hostdep
", "1.0.0").publish();
329 Package::new("devdep
", "1.0.0").publish();
330 Package::new("build_target_dep
", "1.0.0").publish();
331 Package::new("build_host_dep
", "1.0.0")
332 .target_dep("targetdep
", "1.0", alternate())
333 .target_dep("hostdep
", "1.0", &rustc_host())
335 Package::new("pm_target
", "1.0.0")
338 Package::new("pm_host
", "1.0.0").proc_macro(true).publish();
349 [target
.'{alt}'
.dependencies
]
353 [target
.'{host}'
.dependencies
]
357 [target
.'{alt}'
.dev
-dependencies
]
360 [target
.'{alt}'
.build
-dependencies
]
361 build_target_dep
= "1.0"
363 [target
.'{host}'
.build
-dependencies
]
364 build_host_dep
= "1.0"
370 .file("src
/lib
.rs
", "")
371 .file("build
.rs
", "fn main() {}
")
377 foo v0
.1
.0 ([..]/foo
)
381 └── build_host_dep v1
.0
.0
382 └── hostdep v1
.0
.0 (*)
387 p.cargo("tree
--target
")
391 foo v0
.1
.0 ([..]/foo
)
395 └── build_host_dep v1
.0
.0
403 p.cargo("tree
--target
")
407 foo v0
.1
.0 ([..]/foo
)
411 └── build_host_dep v1
.0
.0
417 p.cargo("tree
--no
-filter
-targets
--target
")
420 .with_stderr("[ERROR
] cannot specify both `
--target` and `
--no
-filter
-targets`
")
423 p.cargo("tree
--no
-filter
-targets
")
426 foo v0
.1
.0 ([..]/foo
)
432 ├── build_host_dep v1
.0
.0
433 │ ├── hostdep v1
.0
.0 (*)
434 │ └── targetdep v1
.0
.0 (*)
435 └── build_target_dep v1
.0
.0
444 fn no_dev_dependencies() {
445 Package::new("devdep
", "1.0.0").publish();
458 .file("src
/lib
.rs
", "")
471 p.cargo("tree
--no
-dev
-dependencies
")
481 fn cyclic_dev_dep() {
482 // Cyclical dev-dependency and inverse flag.
492 dev
-dep
= { path = "dev-dep" }
495 .file("src
/lib
.rs
", "")
497 "dev
-dep
/Cargo
.toml
",
507 .file("dev
-dep
/src
/lib
.rs
", "")
513 foo v0
.1
.0 ([..]/foo
)
515 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
516 └── foo v0
.1
.0 ([..]/foo
) (*)
521 p.cargo("tree
--invert
")
524 foo v0
.1
.0 ([..]/foo
)
525 └── dev
-dep v0
.1
.0 ([..]/foo
/dev
-dep
)
527 └── foo v0
.1
.0 ([..]/foo
) (*)
535 Package::new("b1
", "1.0.0").dep("c
", "1.0").publish();
536 Package::new("b2
", "1.0.0").dep("d
", "1.0").publish();
537 Package::new("c
", "1.0.0").publish();
538 Package::new("d
", "1.0.0").publish();
553 .file("src
/lib
.rs
", "")
559 foo v0
.1
.0 ([..]/foo
)
569 p.cargo("tree
--invert
-p c
")
574 │ └── foo v0
.1
.0 ([..]/foo
)
575 └── foo v0
.1
.0 ([..]/foo
) (*)
582 fn invert_with_build_dep() {
583 // -i with -p for a common dependency between normal and build deps.
584 Package::new("common
", "1.0.0").publish();
585 Package::new("bdep
", "1.0.0").dep("common
", "1.0").publish();
601 .file("src
/lib
.rs
", "")
607 foo v0
.1
.0 ([..]/foo
)
611 └── common v1
.0
.0 (*)
616 p.cargo("tree
-i
-p common
")
621 │
[build
-dependencies
]
622 │ └── foo v0
.1
.0 ([..]/foo
)
623 └── foo v0
.1
.0 ([..]/foo
) (*)
631 let p = make_simple_proj();
633 p.cargo("tree
--no
-indent
")
636 foo v0
.1
.0 ([..]/foo
)
652 let p = make_simple_proj();
654 p.cargo("tree
--prefix
-depth
")
657 0foo v0
.1
.0 ([..]/foo
)
673 let p = make_simple_proj();
675 p.cargo("tree
--no
-dedupe
")
678 foo v0
.1
.0 ([..]/foo
)
697 fn no_dedupe_cycle() {
698 // --no-dedupe with a dependency cycle
711 .file("src
/lib
.rs
", "")
723 .file("bar
/src
/lib
.rs
", "")
729 foo v0
.1
.0 ([..]/foo
)
731 └── bar v0
.1
.0 ([..]/foo
/bar
)
732 └── foo v0
.1
.0 ([..]/foo
) (*)
737 p.cargo("tree
--no
-dedupe
")
740 foo v0
.1
.0 ([..]/foo
)
742 └── bar v0
.1
.0 ([..]/foo
/bar
)
743 └── foo v0
.1
.0 ([..]/foo
) (*)
751 Package::new("dog
", "1.0.0").publish();
752 Package::new("dog
", "2.0.0").publish();
753 Package::new("cat
", "1.0.0").publish();
754 Package::new("cat
", "2.0.0").publish();
755 Package::new("dep
", "1.0.0")
775 dog1
= { version = "1.0", package = "dog" }
776 dog2
= { version = "2.0", package = "dog" }
779 .file("a
/src
/lib
.rs
", "")
792 .file("b
/src
/lib
.rs
", "")
798 a v0
.1
.0 ([..]/foo
/a
)
808 b v0
.1
.0 ([..]/foo
/b
)
817 p.cargo("tree
-p a
-d
")
821 └── a v0
.1
.0 ([..]/foo
/a
)
824 └── a v0
.1
.0 ([..]/foo
/a
)
829 p.cargo("tree
-p b
-d
")
834 └── b v0
.1
.0 ([..]/foo
/b
)
837 └── b v0
.1
.0 ([..]/foo
/b
)
845 let p = make_simple_proj();
846 p.cargo("tree
--charset ascii
")
849 foo v0
.1
.0 ([..]/foo
)
867 Package::new("dep
", "1.0.0").publish();
876 repository
= "https://github.com/rust-lang/cargo"
879 dep
= {version="1.0", optional=true}
887 .file("src
/lib
.rs
", "")
890 p.cargo("tree
--format
<<<{p}
>>>")
891 .with_stdout("<<<foo v0
.1
.0 ([..]/foo
)>>>")
894 p.cargo("tree
--format {}
")
897 [ERROR
] tree format `{}` not valid
900 unsupported pattern ``
906 p.cargo("tree
--format
")
908 .with_stdout("foo v0
.1
.0 ([..]/foo
) MIT https
://github.com/rust-lang/cargo")
911 p
.cargo("tree --format")
913 .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo")
916 p
.cargo("tree --all-features --format")
920 foo v0.1.0 ([..]/foo) [bar,default,dep,foo]
928 fn dev_dep_feature() {
929 // -Zfeatures=dev_dep with optional dep
930 Package
::new("optdep", "1.0.0").publish();
931 Package
::new("bar", "1.0.0")
932 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
943 bar = { version = "1.0", features = ["optdep"] }
949 .file("src/lib.rs", "")
955 foo v0.1.0 ([..]/foo)
964 p
.cargo("tree --no-dev-dependencies")
967 foo v0.1.0 ([..]/foo)
974 p
.cargo("tree -Zfeatures=dev_dep")
975 .masquerade_as_nightly_cargo()
978 foo v0.1.0 ([..]/foo)
987 p
.cargo("tree --no-dev-dependencies -Zfeatures=dev_dep")
988 .masquerade_as_nightly_cargo()
991 foo v0.1.0 ([..]/foo)
999 fn host_dep_feature() {
1000 // -Zfeatures=host_dep with optional dep
1001 Package
::new("optdep", "1.0.0").publish();
1002 Package
::new("bar", "1.0.0")
1003 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1013 [build-dependencies]
1014 bar = { version = "1.0", features = ["optdep"] }
1020 .file("src/lib.rs", "")
1021 .file("build.rs", "fn main() {}")
1027 foo v0.1.0 ([..]/foo)
1030 [build-dependencies]
1036 p
.cargo("tree -Zfeatures=host_dep")
1037 .masquerade_as_nightly_cargo()
1040 foo v0.1.0 ([..]/foo)
1042 [build-dependencies]
1050 p
.cargo("tree -p bar")
1059 p
.cargo("tree -p bar -Zfeatures=host_dep")
1060 .masquerade_as_nightly_cargo()
1072 p
.cargo("tree -i -p optdep")
1077 └── foo v0.1.0 ([..]/foo)
1078 [build-dependencies]
1079 └── foo v0.1.0 ([..]/foo) (*)
1084 p
.cargo("tree -i -p optdep -Zfeatures=host_dep")
1085 .masquerade_as_nightly_cargo()
1090 [build-dependencies]
1091 └── foo v0.1.0 ([..]/foo)
1096 // Check that -d handles duplicates with features.
1097 p
.cargo("tree -d -Zfeatures=host_dep")
1098 .masquerade_as_nightly_cargo()
1102 └── foo v0.1.0 ([..]/foo)
1105 [build-dependencies]
1106 └── foo v0.1.0 ([..]/foo)
1113 fn proc_macro_features() {
1114 // -Zfeatures=host_dep with a proc-macro
1115 Package
::new("optdep", "1.0.0").publish();
1116 Package
::new("somedep", "1.0.0")
1117 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1119 Package
::new("pm", "1.0.0")
1121 .feature_dep("somedep", "1.0", &["optdep"])
1136 .file("src/lib.rs", "")
1142 foo v0.1.0 ([..]/foo)
1144 │ └── somedep v1.0.0
1146 └── somedep v1.0.0 (*)
1151 // Note the missing (*)
1152 p
.cargo("tree -Zfeatures=host_dep")
1153 .masquerade_as_nightly_cargo()
1156 foo v0.1.0 ([..]/foo)
1158 │ └── somedep v1.0.0
1166 p
.cargo("tree -p somedep")
1175 p
.cargo("tree -p somedep -Zfeatures=host_dep")
1176 .masquerade_as_nightly_cargo()
1188 p
.cargo("tree -i -p somedep")
1192 ├── foo v0.1.0 ([..]/foo)
1194 └── foo v0.1.0 ([..]/foo) (*)
1199 p
.cargo("tree -i -p somedep -Zfeatures=host_dep")
1200 .masquerade_as_nightly_cargo()
1204 └── foo v0.1.0 ([..]/foo)
1208 └── foo v0.1.0 ([..]/foo)
1215 fn itarget_opt_dep() {
1216 // -Zfeatures=itarget with optional dep
1217 Package
::new("optdep", "1.0.0").publish();
1218 Package
::new("common", "1.0.0")
1219 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1233 [target.'cfg(whatever)'.dependencies]
1234 common = { version = "1.0", features = ["optdep"] }
1238 .file("src/lib.rs", "")
1244 foo v1.0.0 ([..]/foo)
1251 p
.cargo("tree -Zfeatures=itarget")
1254 foo v1.0.0 ([..]/foo)
1258 .masquerade_as_nightly_cargo()
1263 fn ambiguous_name() {
1264 // -p that is ambiguous.
1265 Package
::new("dep", "1.0.0").publish();
1266 Package
::new("dep", "2.0.0").publish();
1267 Package
::new("bar", "1.0.0").dep("dep", "2.0").publish();
1281 .file("src/lib.rs", "")
1284 p
.cargo("tree -p dep")
1285 .with_stderr_contains(
1287 error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous.
1288 Please re-run this command with `-p <spec>` where `<spec>` is one of the following:
1298 fn workspace_features_are_local() {
1299 // The features for workspace packages should be the same as `cargo build`
1300 // (i.e., the features selected depend on the "current" package).
1301 Package
::new("optdep", "1.0.0").publish();
1302 Package
::new("somedep", "1.0.0")
1303 .add_dep(Dependency
::new("optdep", "1.0").optional(true))
1310 members = ["a", "b"]
1321 somedep = {version="1.0", features=["optdep"]}
1324 .file("a/src/lib.rs", "")
1336 .file("b/src/lib.rs", "")
1342 a v0.1.0 ([..]/foo/a)
1346 b v0.1.0 ([..]/foo/b)
1353 p
.cargo("tree -p a")
1356 a v0.1.0 ([..]/foo/a)
1363 p
.cargo("tree -p b")
1366 b v0.1.0 ([..]/foo/b)