mirror of
https://github.com/rust-lang/cargo
synced 2024-10-31 07:46:57 +00:00
9831e83fb2
Fixes #12433
2201 lines
46 KiB
Rust
2201 lines
46 KiB
Rust
//! 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 duplicates_with_proc_macro() {
|
|
Package::new("dupe-dep", "1.0.0").publish();
|
|
Package::new("dupe-dep", "2.0.0").publish();
|
|
Package::new("proc", "1.0.0")
|
|
.proc_macro(true)
|
|
.dep("dupe-dep", "1.0")
|
|
.publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
proc = "1.0"
|
|
dupe-dep = "2.0"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("tree")
|
|
.with_stdout(
|
|
"\
|
|
foo v0.1.0 ([..]/foo)
|
|
├── dupe-dep v2.0.0
|
|
└── proc v1.0.0 (proc-macro)
|
|
└── dupe-dep v1.0.0
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("tree --duplicates")
|
|
.with_stdout(
|
|
"\
|
|
dupe-dep v1.0.0
|
|
└── proc v1.0.0 (proc-macro)
|
|
└── foo v0.1.0 ([..]/foo)
|
|
|
|
dupe-dep v2.0.0
|
|
└── foo v0.1.0 ([..]/foo)
|
|
",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("tree --duplicates --edges no-proc-macro")
|
|
.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)
|
|
",
|
|
)
|
|
.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 one of the following specifications:
|
|
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();
|
|
}
|