cargo/tests/testsuite/replace.rs
Alex Crichton 6514c289d2 Improve git error messages a bit
This commit is targeted at further improving the error messages
generated from git errors. For authentication errors the actual URL
fetched is now printed out as well if it's different from the original
URL. This should help handle `insteadOf` logic where SSH urls are used
instead of HTTPS urls and users can know to track that down.

Otherwise the logic about recommending `net.git-fetch-with-cli` was
tweaked a bit and moved to the same location as the rest of our error
reporting.

Note that a change piggy-backed here as well is that `Caused by:` errors
are now automatically all tabbed over a bit instead of only having the
first line tabbed over. This required a good number of tests to be
updated, but it's just an updated in renderings.
2020-06-25 08:47:15 -07:00

1202 lines
27 KiB
Rust

//! Tests for `[replace]` table source replacement.
use cargo_test_support::git;
use cargo_test_support::paths;
use cargo_test_support::registry::Package;
use cargo_test_support::{basic_manifest, project};
#[cargo_test]
fn override_simple() {
Package::new("bar", "0.1.0").publish();
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
bar.url()
),
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
)
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[UPDATING] git repository `[..]`
[COMPILING] bar v0.1.0 (file://[..])
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn missing_version() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
bar = { git = 'https://example.com' }
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[..]`
Caused by:
replacements must specify a version to replace, but `[..]bar` does not
",
)
.run();
}
#[cargo_test]
fn invalid_semver_version() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "*"
[replace]
"bar:*" = { git = 'https://example.com' }
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr_contains(
"\
error: failed to parse manifest at `[..]`
Caused by:
replacements must specify a valid semver version to replace, but `bar:*` does not
",
)
.run();
}
#[cargo_test]
fn different_version() {
Package::new("bar", "0.2.0").publish();
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = "0.2.0"
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[..]`
Caused by:
replacements cannot specify a version requirement, but found one for [..]
",
)
.run();
}
#[cargo_test]
fn transitive() {
Package::new("bar", "0.1.0").publish();
Package::new("baz", "0.2.0")
.dep("bar", "0.1.0")
.file("src/lib.rs", "extern crate bar; fn baz() { bar::bar(); }")
.publish();
let foo = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
baz = "0.2.0"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[UPDATING] git repository `[..]`
[DOWNLOADING] crates ...
[DOWNLOADED] baz v0.2.0 (registry [..])
[COMPILING] bar v0.1.0 (file://[..])
[COMPILING] baz v0.2.0
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("build").with_stdout("").run();
}
#[cargo_test]
fn persists_across_rebuilds() {
Package::new("bar", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
)
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[UPDATING] git repository `file://[..]`
[COMPILING] bar v0.1.0 (file://[..])
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("build").with_stdout("").run();
}
#[cargo_test]
fn replace_registry_with_path() {
Package::new("bar", "0.1.0").publish();
let _ = project()
.at("bar")
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = { path = "../bar" }
"#,
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
)
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[COMPILING] bar v0.1.0 ([ROOT][..])
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn use_a_spec_to_select() {
Package::new("baz", "0.1.1")
.file("src/lib.rs", "pub fn baz1() {}")
.publish();
Package::new("baz", "0.2.0").publish();
Package::new("bar", "0.1.1")
.dep("baz", "0.2")
.file(
"src/lib.rs",
"extern crate baz; pub fn bar() { baz::baz3(); }",
)
.publish();
let foo = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("baz", "0.2.0"))
.file("src/lib.rs", "pub fn baz3() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
baz = "0.1"
[replace]
"baz:0.2.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file(
"src/lib.rs",
"
extern crate bar;
extern crate baz;
pub fn local() {
baz::baz1();
bar::bar();
}
",
)
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[UPDATING] git repository `[..]`
[DOWNLOADING] crates ...
[DOWNLOADED] [..]
[DOWNLOADED] [..]
[COMPILING] [..]
[COMPILING] [..]
[COMPILING] [..]
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn override_adds_some_deps() {
Package::new("baz", "0.1.1").publish();
Package::new("bar", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[dependencies]
baz = "0.1"
"#,
)
.file("src/lib.rs", "")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
[UPDATING] git repository `[..]`
[DOWNLOADING] crates ...
[DOWNLOADED] baz v0.1.1 (registry [..])
[COMPILING] baz v0.1.1
[COMPILING] bar v0.1.0 ([..])
[COMPILING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("build").with_stdout("").run();
Package::new("baz", "0.1.2").publish();
p.cargo("update -p")
.arg(&format!("{}#bar", foo.url()))
.with_stderr(
"\
[UPDATING] git repository `file://[..]`
[UPDATING] `[ROOT][..]` index
",
)
.run();
p.cargo("update -p https://github.com/rust-lang/crates.io-index#bar")
.with_stderr(
"\
[UPDATING] `[ROOT][..]` index
",
)
.run();
p.cargo("build").with_stdout("").run();
}
#[cargo_test]
fn locked_means_locked_yes_no_seriously_i_mean_locked() {
// this in theory exercises #2041
Package::new("baz", "0.1.0").publish();
Package::new("baz", "0.2.0").publish();
Package::new("bar", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[dependencies]
baz = "*"
"#,
)
.file("src/lib.rs", "")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
baz = "0.1"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build").with_stdout("").run();
p.cargo("build").with_stdout("").run();
}
#[cargo_test]
fn override_wrong_name() {
Package::new("baz", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
baz = "0.1"
[replace]
"baz:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..] index
[UPDATING] git repository [..]
[ERROR] failed to get `baz` as a dependency of package `foo v0.0.1 ([..])`
Caused by:
no matching package for override `[..]baz:0.1.0` found
location searched: file://[..]
version required: =0.1.0
",
)
.run();
}
#[cargo_test]
fn override_with_nothing() {
Package::new("bar", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
.file("src/lib.rs", "")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
[replace]
"bar:0.1.0" = {{ git = '{}' }}
"#,
foo.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..] index
[UPDATING] git repository [..]
[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([..])`
Caused by:
failed to load source for dependency `bar`
Caused by:
Unable to update file://[..]
Caused by:
Could not find Cargo.toml in `[..]`
",
)
.run();
}
#[cargo_test]
fn override_wrong_version() {
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[replace]
"bar:0.1.0" = { git = 'https://example.com', version = '0.2.0' }
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[..]`
Caused by:
replacements cannot specify a version requirement, but found one for `[..]bar:0.1.0`
",
)
.run();
}
#[cargo_test]
fn multiple_specs() {
Package::new("bar", "0.1.0").publish();
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{0}' }}
[replace."https://github.com/rust-lang/crates.io-index#bar:0.1.0"]
git = '{0}'
"#,
bar.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..] index
[UPDATING] git repository [..]
[ERROR] failed to get `bar` as a dependency of package `foo v0.0.1 ([..])`
Caused by:
overlapping replacement specifications found:
* [..]
* [..]
both specifications match: bar v0.1.0
",
)
.run();
}
#[cargo_test]
fn test_override_dep() {
Package::new("bar", "0.1.0").publish();
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{0}' }}
"#,
bar.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("test -p bar")
.with_status(101)
.with_stderr_contains(
"\
error: There are multiple `bar` packages in your project, and the [..]
Please re-run this command with [..]
[..]#bar:0.1.0
[..]#bar:0.1.0
",
)
.run();
}
#[cargo_test]
fn update() {
Package::new("bar", "0.1.0").publish();
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{0}' }}
"#,
bar.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("generate-lockfile").run();
p.cargo("update")
.with_stderr(
"\
[UPDATING] `[..]` index
[UPDATING] git repository `[..]`
",
)
.run();
}
// foo -> near -> far
// near is overridden with itself
#[cargo_test]
fn no_override_self() {
let deps = git::repo(&paths::root().join("override"))
.file("far/Cargo.toml", &basic_manifest("far", "0.1.0"))
.file("far/src/lib.rs", "")
.file(
"near/Cargo.toml",
r#"
[package]
name = "near"
version = "0.1.0"
authors = []
[dependencies]
far = { path = "../far" }
"#,
)
.file("near/src/lib.rs", "#![no_std] pub extern crate far;")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
near = {{ git = '{0}' }}
[replace]
"near:0.1.0" = {{ git = '{0}' }}
"#,
deps.url()
),
)
.file("src/lib.rs", "#![no_std] pub extern crate near;")
.build();
p.cargo("build --verbose").run();
}
#[cargo_test]
fn override_an_override() {
Package::new("chrono", "0.2.0")
.dep("serde", "< 0.9")
.publish();
Package::new("serde", "0.7.0")
.file("src/lib.rs", "pub fn serde07() {}")
.publish();
Package::new("serde", "0.8.0")
.file("src/lib.rs", "pub fn serde08() {}")
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
chrono = "0.2"
serde = "0.8"
[replace]
"chrono:0.2.0" = { path = "chrono" }
"serde:0.8.0" = { path = "serde" }
"#,
)
.file(
"Cargo.lock",
r#"
[[package]]
name = "foo"
version = "0.0.1"
dependencies = [
"chrono 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "chrono"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
replace = "chrono 0.2.0"
[[package]]
name = "chrono"
version = "0.2.0"
dependencies = [
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
replace = "serde 0.8.0"
[[package]]
name = "serde"
version = "0.8.0"
"#,
)
.file(
"src/lib.rs",
"
extern crate chrono;
extern crate serde;
pub fn foo() {
chrono::chrono();
serde::serde08_override();
}
",
)
.file(
"chrono/Cargo.toml",
r#"
[package]
name = "chrono"
version = "0.2.0"
authors = []
[dependencies]
serde = "< 0.9"
"#,
)
.file(
"chrono/src/lib.rs",
"
extern crate serde;
pub fn chrono() {
serde::serde07();
}
",
)
.file("serde/Cargo.toml", &basic_manifest("serde", "0.8.0"))
.file("serde/src/lib.rs", "pub fn serde08_override() {}")
.build();
p.cargo("build -v").run();
}
#[cargo_test]
fn overriding_nonexistent_no_spurious() {
Package::new("bar", "0.1.0").dep("baz", "0.1").publish();
Package::new("baz", "0.1.0").publish();
let bar = git::repo(&paths::root().join("override"))
.file(
"Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[dependencies]
baz = { path = "baz" }
"#,
)
.file("src/lib.rs", "pub fn bar() {}")
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
.file("baz/src/lib.rs", "pub fn baz() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = {{ git = '{url}' }}
"baz:0.1.0" = {{ git = '{url}' }}
"#,
url = bar.url()
),
)
.file("src/lib.rs", "")
.build();
p.cargo("build").run();
p.cargo("build")
.with_stderr(
"\
[WARNING] package replacement is not used: [..]baz:0.1.0
[FINISHED] [..]
",
)
.with_stdout("")
.run();
}
#[cargo_test]
fn no_warnings_when_replace_is_used_in_another_workspace_member() {
Package::new("bar", "0.1.0").publish();
Package::new("baz", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = [ "first_crate", "second_crate"]
[replace]
"bar:0.1.0" = { path = "local_bar" }"#,
)
.file(
"first_crate/Cargo.toml",
r#"
[package]
name = "first_crate"
version = "0.1.0"
[dependencies]
bar = "0.1.0"
"#,
)
.file("first_crate/src/lib.rs", "")
.file(
"second_crate/Cargo.toml",
&basic_manifest("second_crate", "0.1.0"),
)
.file("second_crate/src/lib.rs", "")
.file("local_bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("local_bar/src/lib.rs", "")
.build();
p.cargo("build")
.cwd("first_crate")
.with_stdout("")
.with_stderr(
"\
[UPDATING] `[..]` index
[COMPILING] bar v0.1.0 ([..])
[COMPILING] first_crate v0.1.0 ([..])
[FINISHED] [..]",
)
.run();
p.cargo("build")
.cwd("second_crate")
.with_stdout("")
.with_stderr(
"\
[COMPILING] second_crate v0.1.0 ([..])
[FINISHED] [..]",
)
.run();
}
#[cargo_test]
fn replace_to_path_dep() {
Package::new("bar", "0.1.0").dep("baz", "0.1").publish();
Package::new("baz", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[replace]
"bar:0.1.0" = { path = "bar" }
"#,
)
.file("src/lib.rs", "extern crate bar;")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[dependencies]
baz = { path = "baz" }
"#,
)
.file(
"bar/src/lib.rs",
"extern crate baz; pub fn bar() { baz::baz(); }",
)
.file("bar/baz/Cargo.toml", &basic_manifest("baz", "0.1.0"))
.file("bar/baz/src/lib.rs", "pub fn baz() {}")
.build();
p.cargo("build").run();
}
#[cargo_test]
fn override_with_default_feature() {
Package::new("another", "0.1.0").publish();
Package::new("another", "0.1.1").dep("bar", "0.1").publish();
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = { path = "bar", default-features = false }
another = "0.1"
another2 = { path = "another2" }
[replace]
'bar:0.1.0' = { path = "bar" }
"#,
)
.file("src/main.rs", "extern crate bar; fn main() { bar::bar(); }")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[features]
default = []
"#,
)
.file(
"bar/src/lib.rs",
r#"
#[cfg(feature = "default")]
pub fn bar() {}
"#,
)
.file(
"another2/Cargo.toml",
r#"
[package]
name = "another2"
version = "0.1.0"
authors = []
[dependencies]
bar = { version = "0.1", default-features = false }
"#,
)
.file("another2/src/lib.rs", "")
.build();
p.cargo("run").run();
}
#[cargo_test]
fn override_plus_dep() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
[replace]
'bar:0.1.0' = { path = "bar" }
"#,
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
authors = []
[dependencies]
foo = { path = ".." }
"#,
)
.file("bar/src/lib.rs", "")
.build();
p.cargo("build")
.with_status(101)
.with_stderr_contains("error: cyclic package dependency: [..]")
.run();
}