| //! Tests for the `cargo tree` command. |
| |
| use super::features2::switch_to_resolver_2; |
| use cargo_test_support::cross_compile::{self, alternate}; |
| use cargo_test_support::registry::{Dependency, Package}; |
| use cargo_test_support::{basic_manifest, git, project, rustc_host, Project}; |
| |
| fn make_simple_proj() -> Project { |
| Package::new("c", "1.0.0").publish(); |
| Package::new("b", "1.0.0").dep("c", "1.0").publish(); |
| Package::new("a", "1.0.0").dep("b", "1.0").publish(); |
| Package::new("bdep", "1.0.0").dep("b", "1.0").publish(); |
| Package::new("devdep", "1.0.0").dep("b", "1.0.0").publish(); |
| |
| project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| a = "1.0" |
| c = "1.0" |
| |
| [build-dependencies] |
| bdep = "1.0" |
| |
| [dev-dependencies] |
| devdep = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("build.rs", "fn main() {}") |
| .build() |
| } |
| |
| #[cargo_test] |
| fn simple() { |
| // A simple test with a few different dependencies. |
| let p = make_simple_proj(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| │ └── b v1.0.0 |
| │ └── c v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── b v1.0.0 (*) |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p bdep") |
| .with_stdout( |
| "\ |
| bdep v1.0.0 |
| └── b v1.0.0 |
| └── c v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn virtual_workspace() { |
| // Multiple packages in a virtual workspace. |
| Package::new("somedep", "1.0.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["a", "baz", "c"] |
| "#, |
| ) |
| .file("a/Cargo.toml", &basic_manifest("a", "1.0.0")) |
| .file("a/src/lib.rs", "") |
| .file( |
| "baz/Cargo.toml", |
| r#" |
| [package] |
| name = "baz" |
| version = "0.1.0" |
| |
| [dependencies] |
| c = { path = "../c" } |
| somedep = "1.0" |
| "#, |
| ) |
| .file("baz/src/lib.rs", "") |
| .file("c/Cargo.toml", &basic_manifest("c", "1.0.0")) |
| .file("c/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| a v1.0.0 ([..]/foo/a) |
| |
| baz v0.1.0 ([..]/foo/baz) |
| ├── c v1.0.0 ([..]/foo/c) |
| └── somedep v1.0.0 |
| |
| c v1.0.0 ([..]/foo/c) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p a").with_stdout("a v1.0.0 [..]").run(); |
| |
| p.cargo("tree") |
| .cwd("baz") |
| .with_stdout( |
| "\ |
| baz v0.1.0 ([..]/foo/baz) |
| ├── c v1.0.0 ([..]/foo/c) |
| └── somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // exclude baz |
| p.cargo("tree --workspace --exclude baz") |
| .with_stdout( |
| "\ |
| a v1.0.0 ([..]/foo/a) |
| |
| c v1.0.0 ([..]/foo/c) |
| ", |
| ) |
| .run(); |
| |
| // exclude glob '*z' |
| p.cargo("tree --workspace --exclude '*z'") |
| .with_stdout( |
| "\ |
| a v1.0.0 ([..]/foo/a) |
| |
| c v1.0.0 ([..]/foo/c) |
| ", |
| ) |
| .run(); |
| |
| // include glob '*z' |
| p.cargo("tree -p '*z'") |
| .with_stdout( |
| "\ |
| baz v0.1.0 ([..]/foo/baz) |
| ├── c v1.0.0 ([..]/foo/c) |
| └── somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dedupe_edges() { |
| // Works around https://github.com/rust-lang/cargo/issues/7985 |
| Package::new("bitflags", "1.0.0").publish(); |
| Package::new("manyfeat", "1.0.0") |
| .feature("f1", &[]) |
| .feature("f2", &[]) |
| .feature("f3", &[]) |
| .dep("bitflags", "1.0") |
| .publish(); |
| Package::new("a", "1.0.0") |
| .feature_dep("manyfeat", "1.0", &["f1"]) |
| .publish(); |
| Package::new("b", "1.0.0") |
| .feature_dep("manyfeat", "1.0", &["f2"]) |
| .publish(); |
| Package::new("c", "1.0.0") |
| .feature_dep("manyfeat", "1.0", &["f3"]) |
| .publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| a = "1.0" |
| b = "1.0" |
| c = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| │ └── manyfeat v1.0.0 |
| │ └── bitflags v1.0.0 |
| ├── b v1.0.0 |
| │ └── manyfeat v1.0.0 (*) |
| └── c v1.0.0 |
| └── manyfeat v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn renamed_deps() { |
| // Handles renamed dependencies. |
| Package::new("one", "1.0.0").publish(); |
| Package::new("two", "1.0.0").publish(); |
| Package::new("bar", "1.0.0").dep("one", "1.0").publish(); |
| Package::new("bar", "2.0.0").dep("two", "1.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "1.0.0" |
| |
| [dependencies] |
| bar1 = {version = "1.0", package="bar"} |
| bar2 = {version = "2.0", package="bar"} |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([..]/foo) |
| ├── bar v1.0.0 |
| │ └── one v1.0.0 |
| └── bar v2.0.0 |
| └── two v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn source_kinds() { |
| // Handles git and path sources. |
| Package::new("regdep", "1.0.0").publish(); |
| let git_project = git::new("gitdep", |p| { |
| p.file("Cargo.toml", &basic_manifest("gitdep", "1.0.0")) |
| .file("src/lib.rs", "") |
| }); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| regdep = "1.0" |
| pathdep = {{ path = "pathdep" }} |
| gitdep = {{ git = "{}" }} |
| "#, |
| git_project.url() |
| ), |
| ) |
| .file("src/lib.rs", "") |
| .file("pathdep/Cargo.toml", &basic_manifest("pathdep", "1.0.0")) |
| .file("pathdep/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── gitdep v1.0.0 (file://[..]/gitdep#[..]) |
| ├── pathdep v1.0.0 ([..]/foo/pathdep) |
| └── regdep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn features() { |
| // Exercises a variety of feature behaviors. |
| Package::new("optdep_default", "1.0.0").publish(); |
| Package::new("optdep", "1.0.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "a" |
| version = "0.1.0" |
| |
| [dependencies] |
| optdep_default = { version = "1.0", optional = true } |
| optdep = { version = "1.0", optional = true } |
| |
| [features] |
| default = ["optdep_default"] |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo) |
| └── optdep_default v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --no-default-features") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --all-features") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo) |
| ├── optdep v1.0.0 |
| └── optdep_default v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --features optdep") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo) |
| ├── optdep v1.0.0 |
| └── optdep_default v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn filters_target() { |
| // --target flag |
| if cross_compile::disabled() { |
| return; |
| } |
| Package::new("targetdep", "1.0.0").publish(); |
| Package::new("hostdep", "1.0.0").publish(); |
| Package::new("devdep", "1.0.0").publish(); |
| Package::new("build_target_dep", "1.0.0").publish(); |
| Package::new("build_host_dep", "1.0.0") |
| .target_dep("targetdep", "1.0", alternate()) |
| .target_dep("hostdep", "1.0", rustc_host()) |
| .publish(); |
| Package::new("pm_target", "1.0.0") |
| .proc_macro(true) |
| .publish(); |
| Package::new("pm_host", "1.0.0").proc_macro(true).publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [target.'{alt}'.dependencies] |
| targetdep = "1.0" |
| pm_target = "1.0" |
| |
| [target.'{host}'.dependencies] |
| hostdep = "1.0" |
| pm_host = "1.0" |
| |
| [target.'{alt}'.dev-dependencies] |
| devdep = "1.0" |
| |
| [target.'{alt}'.build-dependencies] |
| build_target_dep = "1.0" |
| |
| [target.'{host}'.build-dependencies] |
| build_host_dep = "1.0" |
| "#, |
| alt = alternate(), |
| host = rustc_host() |
| ), |
| ) |
| .file("src/lib.rs", "") |
| .file("build.rs", "fn main() {}") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── hostdep v1.0.0 |
| └── pm_host v1.0.0 (proc-macro) |
| [build-dependencies] |
| └── build_host_dep v1.0.0 |
| └── hostdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --target") |
| .arg(alternate()) |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── pm_target v1.0.0 (proc-macro) |
| └── targetdep v1.0.0 |
| [build-dependencies] |
| └── build_host_dep v1.0.0 |
| └── hostdep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --target") |
| .arg(rustc_host()) |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── hostdep v1.0.0 |
| └── pm_host v1.0.0 (proc-macro) |
| [build-dependencies] |
| └── build_host_dep v1.0.0 |
| └── hostdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --target=all") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── hostdep v1.0.0 |
| ├── pm_host v1.0.0 (proc-macro) |
| ├── pm_target v1.0.0 (proc-macro) |
| └── targetdep v1.0.0 |
| [build-dependencies] |
| ├── build_host_dep v1.0.0 |
| │ ├── hostdep v1.0.0 |
| │ └── targetdep v1.0.0 |
| └── build_target_dep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // no-proc-macro |
| p.cargo("tree --target=all -e no-proc-macro") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── hostdep v1.0.0 |
| └── targetdep v1.0.0 |
| [build-dependencies] |
| ├── build_host_dep v1.0.0 |
| │ ├── hostdep v1.0.0 |
| │ └── targetdep v1.0.0 |
| └── build_target_dep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_selected_target_dependency() { |
| // --target flag |
| if cross_compile::disabled() { |
| return; |
| } |
| Package::new("targetdep", "1.0.0").publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| &format!( |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [target.'{alt}'.dependencies] |
| targetdep = "1.0" |
| |
| "#, |
| alt = alternate(), |
| ), |
| ) |
| .file("src/lib.rs", "") |
| .file("build.rs", "fn main() {}") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -i targetdep") |
| .with_stderr( |
| "\ |
| [WARNING] nothing to print. |
| |
| To find dependencies that require specific target platforms, \ |
| try to use option `--target all` first, and then narrow your search scope accordingly. |
| ", |
| ) |
| .run(); |
| p.cargo("tree -i targetdep --target all") |
| .with_stdout( |
| "\ |
| targetdep v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dep_kinds() { |
| Package::new("inner-devdep", "1.0.0").publish(); |
| Package::new("inner-builddep", "1.0.0").publish(); |
| Package::new("inner-normal", "1.0.0").publish(); |
| Package::new("inner-pm", "1.0.0").proc_macro(true).publish(); |
| Package::new("inner-buildpm", "1.0.0") |
| .proc_macro(true) |
| .publish(); |
| Package::new("normaldep", "1.0.0") |
| .dep("inner-normal", "1.0") |
| .dev_dep("inner-devdep", "1.0") |
| .build_dep("inner-builddep", "1.0") |
| .publish(); |
| Package::new("devdep", "1.0.0") |
| .dep("inner-normal", "1.0") |
| .dep("inner-pm", "1.0") |
| .dev_dep("inner-devdep", "1.0") |
| .build_dep("inner-builddep", "1.0") |
| .build_dep("inner-buildpm", "1.0") |
| .publish(); |
| Package::new("builddep", "1.0.0") |
| .dep("inner-normal", "1.0") |
| .dev_dep("inner-devdep", "1.0") |
| .build_dep("inner-builddep", "1.0") |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| normaldep = "1.0" |
| |
| [dev-dependencies] |
| devdep = "1.0" |
| |
| [build-dependencies] |
| builddep = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── normaldep v1.0.0 |
| └── inner-normal v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| [build-dependencies] |
| └── builddep v1.0.0 |
| └── inner-normal v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| ├── inner-normal v1.0.0 |
| └── inner-pm v1.0.0 (proc-macro) |
| [build-dependencies] |
| ├── inner-builddep v1.0.0 |
| └── inner-buildpm v1.0.0 (proc-macro) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e no-dev") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── normaldep v1.0.0 |
| └── inner-normal v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| [build-dependencies] |
| └── builddep v1.0.0 |
| └── inner-normal v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e normal") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── normaldep v1.0.0 |
| └── inner-normal v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e dev,build") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [build-dependencies] |
| └── builddep v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| [build-dependencies] |
| ├── inner-builddep v1.0.0 |
| └── inner-buildpm v1.0.0 (proc-macro) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e dev,build,no-proc-macro") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [build-dependencies] |
| └── builddep v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| [build-dependencies] |
| └── inner-builddep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn cyclic_dev_dep() { |
| // Cyclical dev-dependency and inverse flag. |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dev-dependencies] |
| dev-dep = { path = "dev-dep" } |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "dev-dep/Cargo.toml", |
| r#" |
| [package] |
| name = "dev-dep" |
| version = "0.1.0" |
| |
| [dependencies] |
| foo = { path=".." } |
| "#, |
| ) |
| .file("dev-dep/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [dev-dependencies] |
| └── dev-dep v0.1.0 ([..]/foo/dev-dep) |
| └── foo v0.1.0 ([..]/foo) (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --invert foo") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── dev-dep v0.1.0 ([..]/foo/dev-dep) |
| [dev-dependencies] |
| └── foo v0.1.0 ([..]/foo) (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn invert() { |
| Package::new("b1", "1.0.0").dep("c", "1.0").publish(); |
| Package::new("b2", "1.0.0").dep("d", "1.0").publish(); |
| Package::new("c", "1.0.0").publish(); |
| Package::new("d", "1.0.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| b1 = "1.0" |
| b2 = "1.0" |
| c = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── b1 v1.0.0 |
| │ └── c v1.0.0 |
| ├── b2 v1.0.0 |
| │ └── d v1.0.0 |
| └── c v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --invert c") |
| .with_stdout( |
| "\ |
| c v1.0.0 |
| ├── b1 v1.0.0 |
| │ └── foo v0.1.0 ([..]/foo) |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn invert_with_build_dep() { |
| // -i for a common dependency between normal and build deps. |
| Package::new("common", "1.0.0").publish(); |
| Package::new("bdep", "1.0.0").dep("common", "1.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| common = "1.0" |
| |
| [build-dependencies] |
| bdep = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── common v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── common v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -i common") |
| .with_stdout( |
| "\ |
| common v1.0.0 |
| ├── bdep v1.0.0 |
| │ [build-dependencies] |
| │ └── foo v0.1.0 ([..]/foo) |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_indent() { |
| let p = make_simple_proj(); |
| |
| p.cargo("tree --prefix=none") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| a v1.0.0 |
| b v1.0.0 |
| c v1.0.0 |
| c v1.0.0 |
| bdep v1.0.0 |
| b v1.0.0 (*) |
| devdep v1.0.0 |
| b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn prefix_depth() { |
| let p = make_simple_proj(); |
| |
| p.cargo("tree --prefix=depth") |
| .with_stdout( |
| "\ |
| 0foo v0.1.0 ([..]/foo) |
| 1a v1.0.0 |
| 2b v1.0.0 |
| 3c v1.0.0 |
| 1c v1.0.0 |
| 1bdep v1.0.0 |
| 2b v1.0.0 (*) |
| 1devdep v1.0.0 |
| 2b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_dedupe() { |
| let p = make_simple_proj(); |
| |
| p.cargo("tree --no-dedupe") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| │ └── b v1.0.0 |
| │ └── c v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── b v1.0.0 |
| └── c v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 |
| └── c v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn no_dedupe_cycle() { |
| // --no-dedupe with a dependency cycle |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dev-dependencies] |
| bar = {path = "bar"} |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "bar/Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "0.1.0" |
| |
| [dependencies] |
| foo = {path=".."} |
| "#, |
| ) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [dev-dependencies] |
| └── bar v0.1.0 ([..]/foo/bar) |
| └── foo v0.1.0 ([..]/foo) (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --no-dedupe") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [dev-dependencies] |
| └── bar v0.1.0 ([..]/foo/bar) |
| └── foo v0.1.0 ([..]/foo) (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn duplicates() { |
| Package::new("dog", "1.0.0").publish(); |
| Package::new("dog", "2.0.0").publish(); |
| Package::new("cat", "1.0.0").publish(); |
| Package::new("cat", "2.0.0").publish(); |
| Package::new("dep", "1.0.0") |
| .dep("dog", "1.0") |
| .dep("cat", "1.0") |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["a", "b"] |
| "#, |
| ) |
| .file( |
| "a/Cargo.toml", |
| r#" |
| [package] |
| name = "a" |
| version = "0.1.0" |
| |
| [dependencies] |
| dog1 = { version = "1.0", package = "dog" } |
| dog2 = { version = "2.0", package = "dog" } |
| "#, |
| ) |
| .file("a/src/lib.rs", "") |
| .file( |
| "b/Cargo.toml", |
| r#" |
| [package] |
| name = "b" |
| version = "0.1.0" |
| |
| [dependencies] |
| dep = "1.0" |
| cat = "2.0" |
| "#, |
| ) |
| .file("b/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -p a") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo/a) |
| ├── dog v1.0.0 |
| └── dog v2.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p b") |
| .with_stdout( |
| "\ |
| b v0.1.0 ([..]/foo/b) |
| ├── cat v2.0.0 |
| └── dep v1.0.0 |
| ├── cat v1.0.0 |
| └── dog v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p a -d") |
| .with_stdout( |
| "\ |
| dog v1.0.0 |
| └── a v0.1.0 ([..]/foo/a) |
| |
| dog v2.0.0 |
| └── a v0.1.0 ([..]/foo/a) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p b -d") |
| .with_stdout( |
| "\ |
| cat v1.0.0 |
| └── dep v1.0.0 |
| └── b v0.1.0 ([..]/foo/b) |
| |
| cat v2.0.0 |
| └── b v0.1.0 ([..]/foo/b) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn duplicates_with_target() { |
| // --target flag |
| if cross_compile::disabled() { |
| return; |
| } |
| Package::new("a", "1.0.0").publish(); |
| Package::new("dog", "1.0.0").publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| a = "1.0" |
| dog = "1.0" |
| |
| [build-dependencies] |
| a = "1.0" |
| dog = "1.0" |
| |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("build.rs", "fn main() {}") |
| .build(); |
| p.cargo("tree -d").with_stdout("").run(); |
| |
| p.cargo("tree -d --target") |
| .arg(alternate()) |
| .with_stdout("") |
| .run(); |
| |
| p.cargo("tree -d --target") |
| .arg(rustc_host()) |
| .with_stdout("") |
| .run(); |
| |
| p.cargo("tree -d --target=all").with_stdout("").run(); |
| } |
| |
| #[cargo_test] |
| fn charset() { |
| let p = make_simple_proj(); |
| p.cargo("tree --charset ascii") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| |-- a v1.0.0 |
| | `-- b v1.0.0 |
| | `-- c v1.0.0 |
| `-- c v1.0.0 |
| [build-dependencies] |
| `-- bdep v1.0.0 |
| `-- b v1.0.0 (*) |
| [dev-dependencies] |
| `-- devdep v1.0.0 |
| `-- b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn format() { |
| Package::new("dep", "1.0.0").publish(); |
| Package::new("other-dep", "1.0.0").publish(); |
| |
| Package::new("dep_that_is_awesome", "1.0.0") |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "dep_that_is_awesome" |
| version = "1.0.0" |
| |
| [lib] |
| name = "awesome_dep" |
| "#, |
| ) |
| .file("src/lib.rs", "pub struct Straw;") |
| .publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| license = "MIT" |
| repository = "https://github.com/rust-lang/cargo" |
| |
| [dependencies] |
| dep = {version="1.0", optional=true} |
| other-dep = {version="1.0", optional=true} |
| dep_that_is_awesome = {version="1.0", optional=true} |
| |
| |
| [features] |
| default = ["foo"] |
| foo = ["bar"] |
| bar = [] |
| "#, |
| ) |
| .file("src/main.rs", "") |
| .build(); |
| |
| p.cargo("tree --format <<<{p}>>>") |
| .with_stdout("<<<foo v0.1.0 ([..]/foo)>>>") |
| .run(); |
| |
| p.cargo("tree --format {}") |
| .with_stderr( |
| "\ |
| [ERROR] tree format `{}` not valid |
| |
| Caused by: |
| unsupported pattern `` |
| ", |
| ) |
| .with_status(101) |
| .run(); |
| |
| p.cargo("tree --format {p}-{{hello}}") |
| .with_stdout("foo v0.1.0 ([..]/foo)-{hello}") |
| .run(); |
| |
| p.cargo("tree --format") |
| .arg("{p} {l} {r}") |
| .with_stdout("foo v0.1.0 ([..]/foo) MIT https://github.com/rust-lang/cargo") |
| .run(); |
| |
| p.cargo("tree --format") |
| .arg("{p} {f}") |
| .with_stdout("foo v0.1.0 ([..]/foo) bar,default,foo") |
| .run(); |
| |
| p.cargo("tree --all-features --format") |
| .arg("{p} [{f}]") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) [bar,default,dep,dep_that_is_awesome,foo,other-dep] |
| ├── dep v1.0.0 [] |
| ├── dep_that_is_awesome v1.0.0 [] |
| └── other-dep v1.0.0 [] |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree") |
| .arg("--features=other-dep,dep_that_is_awesome") |
| .arg("--format={lib}") |
| .with_stdout( |
| " |
| ├── awesome_dep |
| └── other_dep |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dev_dep_feature() { |
| // New feature resolver with optional dep |
| Package::new("optdep", "1.0.0").publish(); |
| Package::new("bar", "1.0.0") |
| .add_dep(Dependency::new("optdep", "1.0").optional(true)) |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dev-dependencies] |
| bar = { version = "1.0", features = ["optdep"] } |
| |
| [dependencies] |
| bar = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| // Old behavior. |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| └── optdep v1.0.0 |
| [dev-dependencies] |
| └── bar v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e normal") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // New behavior. |
| switch_to_resolver_2(&p); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| └── optdep v1.0.0 |
| [dev-dependencies] |
| └── bar v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e normal") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn host_dep_feature() { |
| // New feature resolver with optional build dep |
| Package::new("optdep", "1.0.0").publish(); |
| Package::new("bar", "1.0.0") |
| .add_dep(Dependency::new("optdep", "1.0").optional(true)) |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [build-dependencies] |
| bar = { version = "1.0", features = ["optdep"] } |
| |
| [dependencies] |
| bar = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file("build.rs", "fn main() {}") |
| .build(); |
| |
| // Old behavior |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| └── optdep v1.0.0 |
| [build-dependencies] |
| └── bar v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // -p |
| p.cargo("tree -p bar") |
| .with_stdout( |
| "\ |
| bar v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // invert |
| p.cargo("tree -i optdep") |
| .with_stdout( |
| "\ |
| optdep v1.0.0 |
| └── bar v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| [build-dependencies] |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| // New behavior. |
| switch_to_resolver_2(&p); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── bar v1.0.0 |
| [build-dependencies] |
| └── bar v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p bar") |
| .with_stdout( |
| "\ |
| bar v1.0.0 |
| |
| bar v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -i optdep") |
| .with_stdout( |
| "\ |
| optdep v1.0.0 |
| └── bar v1.0.0 |
| [build-dependencies] |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| // Check that -d handles duplicates with features. |
| p.cargo("tree -d") |
| .with_stdout( |
| "\ |
| bar v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| |
| bar v1.0.0 |
| [build-dependencies] |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn proc_macro_features() { |
| // New feature resolver with a proc-macro |
| Package::new("optdep", "1.0.0").publish(); |
| Package::new("somedep", "1.0.0") |
| .add_dep(Dependency::new("optdep", "1.0").optional(true)) |
| .publish(); |
| Package::new("pm", "1.0.0") |
| .proc_macro(true) |
| .feature_dep("somedep", "1.0", &["optdep"]) |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| pm = "1.0" |
| somedep = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| // Old behavior |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── pm v1.0.0 (proc-macro) |
| │ └── somedep v1.0.0 |
| │ └── optdep v1.0.0 |
| └── somedep v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // Old behavior + no-proc-macro |
| p.cargo("tree -e no-proc-macro") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── somedep v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // -p |
| p.cargo("tree -p somedep") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // -p -e no-proc-macro |
| p.cargo("tree -p somedep -e no-proc-macro") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // invert |
| p.cargo("tree -i somedep") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| ├── foo v0.1.0 ([..]/foo) |
| └── pm v1.0.0 (proc-macro) |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| // invert + no-proc-macro |
| p.cargo("tree -i somedep -e no-proc-macro") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| // New behavior. |
| switch_to_resolver_2(&p); |
| |
| // Note the missing (*) |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── pm v1.0.0 (proc-macro) |
| │ └── somedep v1.0.0 |
| │ └── optdep v1.0.0 |
| └── somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e no-proc-macro") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p somedep") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| |
| somedep v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -i somedep") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| |
| somedep v1.0.0 |
| └── pm v1.0.0 (proc-macro) |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -i somedep -e no-proc-macro") |
| .with_stdout( |
| "\ |
| somedep v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| |
| somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn itarget_opt_dep() { |
| // New feature resolver with optional target dep |
| Package::new("optdep", "1.0.0").publish(); |
| Package::new("common", "1.0.0") |
| .add_dep(Dependency::new("optdep", "1.0").optional(true)) |
| .publish(); |
| |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "1.0.0" |
| |
| [dependencies] |
| common = "1.0" |
| |
| [target.'cfg(whatever)'.dependencies] |
| common = { version = "1.0", features = ["optdep"] } |
| |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| // Old behavior |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([..]/foo) |
| └── common v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // New behavior. |
| switch_to_resolver_2(&p); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([..]/foo) |
| └── common v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn ambiguous_name() { |
| // -p that is ambiguous. |
| Package::new("dep", "1.0.0").publish(); |
| Package::new("dep", "2.0.0").publish(); |
| Package::new("bar", "1.0.0").dep("dep", "2.0").publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| |
| [dependencies] |
| dep = "1.0" |
| bar = "1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -p dep") |
| .with_stderr_contains( |
| "\ |
| error: There are multiple `dep` packages in your project, and the specification `dep` is ambiguous. |
| Please re-run this command with `-p <spec>` where `<spec>` is one of the following: |
| dep@1.0.0 |
| dep@2.0.0 |
| ", |
| ) |
| .with_status(101) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn workspace_features_are_local() { |
| // The features for workspace packages should be the same as `cargo build` |
| // (i.e., the features selected depend on the "current" package). |
| Package::new("optdep", "1.0.0").publish(); |
| Package::new("somedep", "1.0.0") |
| .add_dep(Dependency::new("optdep", "1.0").optional(true)) |
| .publish(); |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [workspace] |
| members = ["a", "b"] |
| "#, |
| ) |
| .file( |
| "a/Cargo.toml", |
| r#" |
| [package] |
| name = "a" |
| version = "0.1.0" |
| |
| [dependencies] |
| somedep = {version="1.0", features=["optdep"]} |
| "#, |
| ) |
| .file("a/src/lib.rs", "") |
| .file( |
| "b/Cargo.toml", |
| r#" |
| [package] |
| name = "b" |
| version = "0.1.0" |
| |
| [dependencies] |
| somedep = "1.0" |
| "#, |
| ) |
| .file("b/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo/a) |
| └── somedep v1.0.0 |
| └── optdep v1.0.0 |
| |
| b v0.1.0 ([..]/foo/b) |
| └── somedep v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p a") |
| .with_stdout( |
| "\ |
| a v0.1.0 ([..]/foo/a) |
| └── somedep v1.0.0 |
| └── optdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -p b") |
| .with_stdout( |
| "\ |
| b v0.1.0 ([..]/foo/b) |
| └── somedep v1.0.0 |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn unknown_edge_kind() { |
| let p = project() |
| .file("Cargo.toml", "") |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -e unknown") |
| .with_stderr( |
| "\ |
| [ERROR] unknown edge kind `unknown`, valid values are \ |
| \"normal\", \"build\", \"dev\", \ |
| \"no-normal\", \"no-build\", \"no-dev\", \"no-proc-macro\", \ |
| \"features\", or \"all\" |
| ", |
| ) |
| .with_status(101) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn mixed_no_edge_kinds() { |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "0.1.0" |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -e no-build,normal") |
| .with_stderr( |
| "\ |
| [ERROR] `normal` dependency kind cannot be mixed with \ |
| \"no-normal\", \"no-build\", or \"no-dev\" dependency kinds |
| ", |
| ) |
| .with_status(101) |
| .run(); |
| |
| // `no-proc-macro` can be mixed with others |
| p.cargo("tree -e no-proc-macro,normal") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn depth_limit() { |
| let p = make_simple_proj(); |
| |
| p.cargo("tree --depth 0") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| [build-dependencies] |
| [dev-dependencies] |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --depth 1") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree --depth 2") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| │ └── b v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── b v1.0.0 (*) |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // specify a package |
| p.cargo("tree -p bdep --depth 1") |
| .with_stdout( |
| "\ |
| bdep v1.0.0 |
| └── b v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // different prefix |
| p.cargo("tree --depth 1 --prefix depth") |
| .with_stdout( |
| "\ |
| 0foo v0.1.0 ([..]/foo) |
| 1a v1.0.0 |
| 1c v1.0.0 |
| 1bdep v1.0.0 |
| 1devdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // with edge-kinds |
| p.cargo("tree --depth 1 -e no-dev") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // invert |
| p.cargo("tree --depth 1 --invert c") |
| .with_stdout( |
| "\ |
| c v1.0.0 |
| ├── b v1.0.0 |
| └── foo v0.1.0 ([..]/foo) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn prune() { |
| let p = make_simple_proj(); |
| |
| p.cargo("tree --prune c") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── a v1.0.0 |
| └── b v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── b v1.0.0 (*) |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // multiple prune |
| p.cargo("tree --prune c --prune bdep") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── a v1.0.0 |
| └── b v1.0.0 |
| [build-dependencies] |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // with edge-kinds |
| p.cargo("tree --prune c -e normal") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| └── a v1.0.0 |
| └── b v1.0.0 |
| ", |
| ) |
| .run(); |
| |
| // pruning self does not works |
| p.cargo("tree --prune foo") |
| .with_stdout( |
| "\ |
| foo v0.1.0 ([..]/foo) |
| ├── a v1.0.0 |
| │ └── b v1.0.0 |
| │ └── c v1.0.0 |
| └── c v1.0.0 |
| [build-dependencies] |
| └── bdep v1.0.0 |
| └── b v1.0.0 (*) |
| [dev-dependencies] |
| └── devdep v1.0.0 |
| └── b v1.0.0 (*) |
| ", |
| ) |
| .run(); |
| |
| // dep not exist |
| p.cargo("tree --prune no-dep") |
| .with_stderr( |
| "\ |
| [ERROR] package ID specification `no-dep` did not match any packages |
| |
| <tab>Did you mean `bdep`? |
| ", |
| ) |
| .with_status(101) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn cyclic_features() { |
| // Check for stack overflow with cyclic features (oops!). |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "1.0.0" |
| |
| [features] |
| a = ["b"] |
| b = ["a"] |
| default = ["a"] |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -e features") |
| .with_stdout("foo v1.0.0 ([ROOT]/foo)") |
| .run(); |
| |
| p.cargo("tree -e features -i foo") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| ├── foo feature \"a\" |
| │ ├── foo feature \"b\" |
| │ │ └── foo feature \"a\" (*) |
| │ └── foo feature \"default\" (command-line) |
| ├── foo feature \"b\" (*) |
| └── foo feature \"default\" (command-line) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dev_dep_cycle_with_feature() { |
| // Cycle with features and a dev-dependency. |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "1.0.0" |
| |
| [dev-dependencies] |
| bar = { path = "bar" } |
| |
| [features] |
| a = ["bar/feat1"] |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "bar/Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "1.0.0" |
| |
| [dependencies] |
| foo = { path = ".." } |
| |
| [features] |
| feat1 = ["foo/a"] |
| "#, |
| ) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -e features --features a") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| [dev-dependencies] |
| └── bar feature \"default\" |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| └── foo feature \"default\" (command-line) |
| └── foo v1.0.0 ([ROOT]/foo) (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e features --features a -i foo") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| ├── foo feature \"a\" (command-line) |
| │ └── bar feature \"feat1\" |
| │ └── foo feature \"a\" (command-line) (*) |
| └── foo feature \"default\" (command-line) |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| ├── bar feature \"default\" |
| │ [dev-dependencies] |
| │ └── foo v1.0.0 ([ROOT]/foo) (*) |
| └── bar feature \"feat1\" (*) |
| ", |
| ) |
| .run(); |
| } |
| |
| #[cargo_test] |
| fn dev_dep_cycle_with_feature_nested() { |
| // Checks for an issue where a cyclic dev dependency tries to activate a |
| // feature on its parent that tries to activate the feature back on the |
| // dev-dependency. |
| let p = project() |
| .file( |
| "Cargo.toml", |
| r#" |
| [package] |
| name = "foo" |
| version = "1.0.0" |
| |
| [dev-dependencies] |
| bar = { path = "bar" } |
| |
| [features] |
| a = ["bar/feat1"] |
| b = ["a"] |
| "#, |
| ) |
| .file("src/lib.rs", "") |
| .file( |
| "bar/Cargo.toml", |
| r#" |
| [package] |
| name = "bar" |
| version = "1.0.0" |
| |
| [dependencies] |
| foo = { path = ".." } |
| |
| [features] |
| feat1 = ["foo/b"] |
| "#, |
| ) |
| .file("bar/src/lib.rs", "") |
| .build(); |
| |
| p.cargo("tree -e features") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| [dev-dependencies] |
| └── bar feature \"default\" |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| └── foo feature \"default\" (command-line) |
| └── foo v1.0.0 ([ROOT]/foo) (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e features --features a -i foo") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| ├── foo feature \"a\" (command-line) |
| │ └── foo feature \"b\" |
| │ └── bar feature \"feat1\" |
| │ └── foo feature \"a\" (command-line) (*) |
| ├── foo feature \"b\" (*) |
| └── foo feature \"default\" (command-line) |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| ├── bar feature \"default\" |
| │ [dev-dependencies] |
| │ └── foo v1.0.0 ([ROOT]/foo) (*) |
| └── bar feature \"feat1\" (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e features --features b -i foo") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| ├── foo feature \"a\" |
| │ └── foo feature \"b\" (command-line) |
| │ └── bar feature \"feat1\" |
| │ └── foo feature \"a\" (*) |
| ├── foo feature \"b\" (command-line) (*) |
| └── foo feature \"default\" (command-line) |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| ├── bar feature \"default\" |
| │ [dev-dependencies] |
| │ └── foo v1.0.0 ([ROOT]/foo) (*) |
| └── bar feature \"feat1\" (*) |
| ", |
| ) |
| .run(); |
| |
| p.cargo("tree -e features --features bar/feat1 -i foo") |
| .with_stdout( |
| "\ |
| foo v1.0.0 ([ROOT]/foo) |
| ├── foo feature \"a\" |
| │ └── foo feature \"b\" |
| │ └── bar feature \"feat1\" (command-line) |
| │ └── foo feature \"a\" (*) |
| ├── foo feature \"b\" (*) |
| └── foo feature \"default\" (command-line) |
| └── bar v1.0.0 ([ROOT]/foo/bar) |
| ├── bar feature \"default\" |
| │ [dev-dependencies] |
| │ └── foo v1.0.0 ([ROOT]/foo) (*) |
| └── bar feature \"feat1\" (command-line) (*) |
| ", |
| ) |
| .run(); |
| } |