mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00

Instead of always listing the absolute latest version as a warning color, we now differentiate - compatible updates are always actionable - incompatible, direct deps are always actionable These get reported and made yellow while non-actionable messages are unstyled. This is not intended as *the* solution for #13908 though it makes improvements in that direction. This is prep work for improved MSRV reporting where we will differentiate this further by only considering MSRV-compatible updates as actionable (or rustc-compatible when not using MSRV-aware reslver). I just used a broad stroke to say "compatible" in the message means "semver compatible" and use `^` - We could focus on "compatible with dependent version reqs" which is what will be most actionable but seeing if we can get away without having to track all in-coming version reqs. - We could be more nuanced in language but the more verbose we are, the more we take away from higher priority messages
2713 lines
74 KiB
Rust
2713 lines
74 KiB
Rust
//! Tests for the `cargo update` command.
|
|
|
|
use cargo_test_support::compare::assert_e2e;
|
|
use cargo_test_support::prelude::*;
|
|
use cargo_test_support::registry::{self};
|
|
use cargo_test_support::registry::{Dependency, Package};
|
|
use cargo_test_support::{basic_lib_manifest, basic_manifest, git, project, str};
|
|
|
|
#[cargo_test]
|
|
fn minor_update_two_places() {
|
|
Package::new("log", "0.1.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1"
|
|
foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
Package::new("log", "0.1.1").publish();
|
|
|
|
p.change_file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1.1"
|
|
"#,
|
|
);
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn transitive_minor_update() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.1.0").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
log = "0.1"
|
|
foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.1.1").dep("log", "0.1.1").publish();
|
|
|
|
// Note that `serde` isn't actually updated here! The default behavior for
|
|
// `update` right now is to as conservatively as possible attempt to satisfy
|
|
// an update. In this case we previously locked the dependency graph to `log
|
|
// 0.1.0`, but nothing on the command line says we're allowed to update
|
|
// that. As a result the update of `serde` here shouldn't update to `serde
|
|
// 0.1.1` as that would also force an update to `log 0.1.1`.
|
|
//
|
|
// Also note that this is probably counterintuitive and weird. We may wish
|
|
// to change this one day.
|
|
p.cargo("update serde")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 0 packages to latest compatible versions
|
|
[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn conservative() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.1.0").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
log = "0.1"
|
|
foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.1.1").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] serde v0.1.0 -> v0.1.1
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_via_new_dep() {
|
|
Package::new("log", "0.1.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1"
|
|
# foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
Package::new("log", "0.1.1").publish();
|
|
|
|
p.uncomment_root_manifest();
|
|
p.cargo("check").env("CARGO_LOG", "cargo=trace").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_via_new_member() {
|
|
Package::new("log", "0.1.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[workspace]
|
|
# members = [ "foo" ]
|
|
|
|
[dependencies]
|
|
log = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
Package::new("log", "0.1.1").publish();
|
|
|
|
p.uncomment_root_manifest();
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn add_dep_deep_new_requirement() {
|
|
Package::new("log", "0.1.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
log = "0.1"
|
|
# bar = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("bar", "0.1.0").dep("log", "0.1.1").publish();
|
|
|
|
p.uncomment_root_manifest();
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn everything_real_deep() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("foo", "0.1.0").dep("log", "0.1").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
foo = "0.1"
|
|
# bar = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("bar", "0.1.0").dep("log", "0.1.1").publish();
|
|
|
|
p.uncomment_root_manifest();
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn change_package_version() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "a-foo"
|
|
version = "0.2.0-alpha"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = "bar", version = "0.2.0-alpha" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0-alpha"))
|
|
.file("bar/src/lib.rs", "")
|
|
.file(
|
|
"Cargo.lock",
|
|
r#"
|
|
[[package]]
|
|
name = "foo"
|
|
version = "0.2.0"
|
|
dependencies = ["bar 0.2.0"]
|
|
|
|
[[package]]
|
|
name = "bar"
|
|
version = "0.2.0"
|
|
"#,
|
|
)
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_precise() {
|
|
Package::new("serde", "0.1.0").publish();
|
|
Package::new("serde", "0.2.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("serde", "0.2.0").publish();
|
|
|
|
p.cargo("update serde:0.2.1 --precise 0.2.0")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNGRADING] serde v0.2.1 -> v0.2.0
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_precise_mismatched() {
|
|
Package::new("serde", "1.2.0").publish();
|
|
Package::new("serde", "1.2.1").publish();
|
|
Package::new("serde", "1.6.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "~1.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
// `1.6.0` does not match `"~1.2"`
|
|
p.cargo("update serde:1.2 --precise 1.6.0")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] failed to select a version for the requirement `serde = "~1.2"`
|
|
candidate versions found which didn't match: 1.6.0
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `bar v0.0.1 ([ROOT]/foo)`
|
|
perhaps a crate was updated and forgotten to be re-vendored?
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
|
|
// `1.9.0` does not exist
|
|
p.cargo("update serde:1.2 --precise 1.9.0")
|
|
// This terrible error message has been the same for a long time. A fix is more than welcome!
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `serde` found
|
|
location searched: registry `crates-io`
|
|
required by package `bar v0.0.1 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_precise_build_metadata() {
|
|
Package::new("serde", "0.0.1+first").publish();
|
|
Package::new("serde", "0.0.1+second").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
serde = "0.0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
p.cargo("update serde --precise 0.0.1+first").run();
|
|
|
|
p.cargo("update serde --precise 0.0.1+second")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] serde v0.0.1+first -> v0.0.1+second
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// This is not considered "Downgrading". Build metadata are not assumed to
|
|
// be ordered.
|
|
p.cargo("update serde --precise 0.0.1+first")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] serde v0.0.1+second -> v0.0.1+first
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_precise_do_not_force_update_deps() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde:0.2.1 --precise 0.2.2")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] serde v0.2.1 -> v0.2.2
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_recursive() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde:0.2.1 --recursive")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] log v0.1.0 -> v0.1.1
|
|
[UPDATING] serde v0.2.1 -> v0.2.2
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_aggressive_alias_for_recursive() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde:0.2.1 --aggressive")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] log v0.1.0 -> v0.1.1
|
|
[UPDATING] serde v0.2.1 -> v0.2.2
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_recursive_conflicts_with_precise() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.2.1").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.2.2").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde:0.2.1 --precise 0.2.2 --recursive")
|
|
.with_status(1)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the argument '--precise <PRECISE>' cannot be used with '--recursive'
|
|
|
|
Usage: cargo[EXE] update --precise <PRECISE> <SPEC|--package [<SPEC>]>
|
|
|
|
For more information, try '--help'.
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
// cargo update should respect its arguments even without a lockfile.
|
|
// See issue "Running cargo update without a Cargo.lock ignores arguments"
|
|
// at <https://github.com/rust-lang/cargo/issues/6872>.
|
|
#[cargo_test]
|
|
fn update_precise_first_run() {
|
|
Package::new("serde", "0.1.0").publish();
|
|
Package::new("serde", "0.2.0").publish();
|
|
Package::new("serde", "0.2.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
serde = "0.2"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("update serde --precise 0.2.0")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNGRADING] serde v0.2.1 -> v0.2.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Assert `cargo metadata` shows serde 0.2.0
|
|
p.cargo("metadata")
|
|
.with_stdout_data(
|
|
str![[r#"
|
|
{
|
|
"metadata": null,
|
|
"packages": [
|
|
{
|
|
"authors": [],
|
|
"categories": [],
|
|
"default_run": null,
|
|
"dependencies": [
|
|
{
|
|
"features": [],
|
|
"kind": null,
|
|
"name": "serde",
|
|
"optional": false,
|
|
"registry": null,
|
|
"rename": null,
|
|
"req": "^0.2",
|
|
"source": "registry+https://github.com/rust-lang/crates.io-index",
|
|
"target": null,
|
|
"uses_default_features": true
|
|
}
|
|
],
|
|
"description": null,
|
|
"documentation": null,
|
|
"edition": "2015",
|
|
"features": {},
|
|
"homepage": null,
|
|
"id": "path+[ROOTURL]/foo#bar@0.0.1",
|
|
"keywords": [],
|
|
"license": null,
|
|
"license_file": null,
|
|
"links": null,
|
|
"manifest_path": "[ROOT]/foo/Cargo.toml",
|
|
"metadata": null,
|
|
"name": "bar",
|
|
"publish": null,
|
|
"readme": null,
|
|
"repository": null,
|
|
"rust_version": null,
|
|
"source": null,
|
|
"targets": [
|
|
{
|
|
"crate_types": [
|
|
"lib"
|
|
],
|
|
"doc": true,
|
|
"doctest": true,
|
|
"edition": "2015",
|
|
"kind": [
|
|
"lib"
|
|
],
|
|
"name": "bar",
|
|
"src_path": "[ROOT]/foo/src/lib.rs",
|
|
"test": true
|
|
}
|
|
],
|
|
"version": "0.0.1"
|
|
},
|
|
{
|
|
"authors": [],
|
|
"categories": [],
|
|
"default_run": null,
|
|
"dependencies": [],
|
|
"description": null,
|
|
"documentation": null,
|
|
"edition": "2015",
|
|
"features": {},
|
|
"homepage": null,
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0",
|
|
"keywords": [],
|
|
"license": null,
|
|
"license_file": null,
|
|
"links": null,
|
|
"manifest_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/Cargo.toml",
|
|
"metadata": null,
|
|
"name": "serde",
|
|
"publish": null,
|
|
"readme": null,
|
|
"repository": null,
|
|
"rust_version": null,
|
|
"source": "registry+https://github.com/rust-lang/crates.io-index",
|
|
"targets": [
|
|
{
|
|
"crate_types": [
|
|
"lib"
|
|
],
|
|
"doc": true,
|
|
"doctest": true,
|
|
"edition": "2015",
|
|
"kind": [
|
|
"lib"
|
|
],
|
|
"name": "serde",
|
|
"src_path": "[ROOT]/home/.cargo/registry/src/-[HASH]/serde-0.2.0/src/lib.rs",
|
|
"test": true
|
|
}
|
|
],
|
|
"version": "0.2.0"
|
|
}
|
|
],
|
|
"resolve": {
|
|
"nodes": [
|
|
{
|
|
"dependencies": [
|
|
"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
|
|
],
|
|
"deps": [
|
|
{
|
|
"dep_kinds": [
|
|
{
|
|
"kind": null,
|
|
"target": null
|
|
}
|
|
],
|
|
"name": "serde",
|
|
"pkg": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
|
|
}
|
|
],
|
|
"features": [],
|
|
"id": "path+[ROOTURL]/foo#bar@0.0.1"
|
|
},
|
|
{
|
|
"dependencies": [],
|
|
"deps": [],
|
|
"features": [],
|
|
"id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
|
|
}
|
|
],
|
|
"root": "path+[ROOTURL]/foo#bar@0.0.1"
|
|
},
|
|
"target_directory": "[ROOT]/foo/target",
|
|
"version": 1,
|
|
"workspace_default_members": [
|
|
"path+[ROOTURL]/foo#bar@0.0.1"
|
|
],
|
|
"workspace_members": [
|
|
"path+[ROOTURL]/foo#bar@0.0.1"
|
|
],
|
|
"workspace_root": "[ROOT]/foo"
|
|
}
|
|
"#]]
|
|
.is_json(),
|
|
)
|
|
.run();
|
|
|
|
p.cargo("update serde --precise 0.2.0")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn preserve_top_comment() {
|
|
let p = project().file("src/lib.rs", "").build();
|
|
|
|
p.cargo("update").run();
|
|
|
|
let lockfile = p.read_lockfile();
|
|
assert!(lockfile.starts_with("# This file is automatically @generated by Cargo.\n# It is not intended for manual editing.\n"));
|
|
|
|
let mut lines = lockfile.lines().collect::<Vec<_>>();
|
|
lines.insert(2, "# some other comment");
|
|
let mut lockfile = lines.join("\n");
|
|
lockfile.push('\n'); // .lines/.join loses the last newline
|
|
println!("saving Cargo.lock contents:\n{}", lockfile);
|
|
|
|
p.change_file("Cargo.lock", &lockfile);
|
|
|
|
p.cargo("update").run();
|
|
|
|
let lockfile2 = p.read_lockfile();
|
|
println!("loaded Cargo.lock contents:\n{}", lockfile2);
|
|
|
|
assert_eq!(lockfile, lockfile2);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn dry_run_update() {
|
|
Package::new("log", "0.1.0").publish();
|
|
Package::new("serde", "0.1.0").dep("log", "0.1").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
log = "0.1"
|
|
foo = { path = "foo" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
serde = "0.1"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
let old_lockfile = p.read_lockfile();
|
|
|
|
Package::new("log", "0.1.1").publish();
|
|
Package::new("serde", "0.1.1").dep("log", "0.1").publish();
|
|
|
|
p.cargo("update serde --dry-run")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] serde v0.1.0 -> v0.1.1
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
[WARNING] not updating lockfile due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
let new_lockfile = p.read_lockfile();
|
|
assert_eq!(old_lockfile, new_lockfile)
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn workspace_only() {
|
|
let p = project().file("src/main.rs", "fn main() {}").build();
|
|
p.cargo("generate-lockfile").run();
|
|
let lock1 = p.read_lockfile();
|
|
|
|
p.change_file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
authors = []
|
|
version = "0.0.2"
|
|
edition = "2015"
|
|
"#,
|
|
);
|
|
p.cargo("update --workspace").run();
|
|
let lock2 = p.read_lockfile();
|
|
|
|
assert_ne!(lock1, lock2);
|
|
assert!(lock1.contains("0.0.1"));
|
|
assert!(lock2.contains("0.0.2"));
|
|
assert!(!lock1.contains("0.0.2"));
|
|
assert!(!lock2.contains("0.0.1"));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn precise_with_build_metadata() {
|
|
// +foo syntax shouldn't be necessary with --precise
|
|
Package::new("bar", "0.1.0+extra-stuff.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("generate-lockfile").run();
|
|
Package::new("bar", "0.1.1+extra-stuff.1").publish();
|
|
Package::new("bar", "0.1.2+extra-stuff.2").publish();
|
|
|
|
p.cargo("update bar --precise 0.1")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] invalid version format for precise version `0.1`
|
|
|
|
Caused by:
|
|
unexpected end of input while parsing minor version number
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update bar --precise 0.1.1+does-not-match")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `bar` found
|
|
location searched: registry `crates-io`
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update bar --precise 0.1.1")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] bar v0.1.0+extra-stuff.0 -> v0.1.1+extra-stuff.1
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
Package::new("bar", "0.1.3").publish();
|
|
p.cargo("update bar --precise 0.1.3+foo")
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[ERROR] no matching package named `bar` found
|
|
location searched: registry `crates-io`
|
|
required by package `foo v0.1.0 ([ROOT]/foo)`
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update bar --precise 0.1.3")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] bar v0.1.1+extra-stuff.1 -> v0.1.3
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_only_members_order_one() {
|
|
let git_project = git::new("rustdns", |project| {
|
|
project
|
|
.file("Cargo.toml", &basic_lib_manifest("rustdns"))
|
|
.file("src/lib.rs", "pub fn bar() {}")
|
|
});
|
|
|
|
let workspace_toml = format!(
|
|
r#"
|
|
[workspace.package]
|
|
version = "2.29.8"
|
|
edition = "2021"
|
|
publish = false
|
|
|
|
[workspace]
|
|
members = [
|
|
"rootcrate",
|
|
"subcrate",
|
|
]
|
|
resolver = "2"
|
|
|
|
[workspace.dependencies]
|
|
# Internal crates
|
|
subcrate = {{ version = "*", path = "./subcrate" }}
|
|
|
|
# External dependencies
|
|
rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
|
|
"#,
|
|
git_project.url()
|
|
);
|
|
let p = project()
|
|
.file("Cargo.toml", &workspace_toml)
|
|
.file(
|
|
"rootcrate/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "rootcrate"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
subcrate.workspace = true
|
|
"#,
|
|
)
|
|
.file("rootcrate/src/main.rs", "fn main() {}")
|
|
.file(
|
|
"subcrate/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "subcrate"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
rustdns.workspace = true
|
|
"#,
|
|
)
|
|
.file("subcrate/src/lib.rs", "pub foo() {}")
|
|
.build();
|
|
|
|
// First time around we should compile both foo and bar
|
|
p.cargo("generate-lockfile")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] git repository `[ROOTURL]/rustdns`
|
|
[LOCKING] 1 package to latest compatible version
|
|
|
|
"#]])
|
|
.run();
|
|
// Modify a file manually, shouldn't trigger a recompile
|
|
git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
|
|
// Commit the changes and make sure we don't trigger a recompile because the
|
|
// lock file says not to change
|
|
let repo = git2::Repository::open(&git_project.root()).unwrap();
|
|
git::add(&repo);
|
|
git::commit(&repo);
|
|
p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
|
|
|
|
p.cargo("update -p rootcrate")
|
|
.with_stderr_data(str![[r#"
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] rootcrate v2.29.8 ([ROOT]/foo/rootcrate) -> v2.29.81
|
|
[UPDATING] subcrate v2.29.8 ([ROOT]/foo/subcrate) -> v2.29.81
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_only_members_order_two() {
|
|
let git_project = git::new("rustdns", |project| {
|
|
project
|
|
.file("Cargo.toml", &basic_lib_manifest("rustdns"))
|
|
.file("src/lib.rs", "pub fn bar() {}")
|
|
});
|
|
|
|
let workspace_toml = format!(
|
|
r#"
|
|
[workspace.package]
|
|
version = "2.29.8"
|
|
edition = "2021"
|
|
publish = false
|
|
|
|
[workspace]
|
|
members = [
|
|
"crate2",
|
|
"crate1",
|
|
]
|
|
resolver = "2"
|
|
|
|
[workspace.dependencies]
|
|
# Internal crates
|
|
crate1 = {{ version = "*", path = "./crate1" }}
|
|
|
|
# External dependencies
|
|
rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
|
|
"#,
|
|
git_project.url()
|
|
);
|
|
let p = project()
|
|
.file("Cargo.toml", &workspace_toml)
|
|
.file(
|
|
"crate2/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "crate2"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
crate1.workspace = true
|
|
"#,
|
|
)
|
|
.file("crate2/src/main.rs", "fn main() {}")
|
|
.file(
|
|
"crate1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "crate1"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
rustdns.workspace = true
|
|
"#,
|
|
)
|
|
.file("crate1/src/lib.rs", "pub foo() {}")
|
|
.build();
|
|
|
|
// First time around we should compile both foo and bar
|
|
p.cargo("generate-lockfile")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] git repository `[ROOTURL]/rustdns`
|
|
[LOCKING] 1 package to latest compatible version
|
|
|
|
"#]])
|
|
.run();
|
|
// Modify a file manually, shouldn't trigger a recompile
|
|
git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
|
|
// Commit the changes and make sure we don't trigger a recompile because the
|
|
// lock file says not to change
|
|
let repo = git2::Repository::open(&git_project.root()).unwrap();
|
|
git::add(&repo);
|
|
git::commit(&repo);
|
|
p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
|
|
|
|
p.cargo("update -p crate2")
|
|
.with_stderr_data(str![[r#"
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81
|
|
[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_only_members_with_workspace() {
|
|
let git_project = git::new("rustdns", |project| {
|
|
project
|
|
.file("Cargo.toml", &basic_lib_manifest("rustdns"))
|
|
.file("src/lib.rs", "pub fn bar() {}")
|
|
});
|
|
|
|
let workspace_toml = format!(
|
|
r#"
|
|
[workspace.package]
|
|
version = "2.29.8"
|
|
edition = "2021"
|
|
publish = false
|
|
|
|
[workspace]
|
|
members = [
|
|
"crate2",
|
|
"crate1",
|
|
]
|
|
resolver = "2"
|
|
|
|
[workspace.dependencies]
|
|
# Internal crates
|
|
crate1 = {{ version = "*", path = "./crate1" }}
|
|
|
|
# External dependencies
|
|
rustdns = {{ version = "0.5.0", default-features = false, git = "{}" }}
|
|
"#,
|
|
git_project.url()
|
|
);
|
|
let p = project()
|
|
.file("Cargo.toml", &workspace_toml)
|
|
.file(
|
|
"crate2/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "crate2"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
crate1.workspace = true
|
|
"#,
|
|
)
|
|
.file("crate2/src/main.rs", "fn main() {}")
|
|
.file(
|
|
"crate1/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "crate1"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
|
|
[dependencies]
|
|
rustdns.workspace = true
|
|
"#,
|
|
)
|
|
.file("crate1/src/lib.rs", "pub foo() {}")
|
|
.build();
|
|
|
|
// First time around we should compile both foo and bar
|
|
p.cargo("generate-lockfile")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] git repository `[ROOTURL]/rustdns`
|
|
[LOCKING] 1 package to latest compatible version
|
|
|
|
"#]])
|
|
.run();
|
|
// Modify a file manually, shouldn't trigger a recompile
|
|
git_project.change_file("src/lib.rs", r#"pub fn bar() { println!("hello!"); }"#);
|
|
// Commit the changes and make sure we don't trigger a recompile because the
|
|
// lock file says not to change
|
|
let repo = git2::Repository::open(&git_project.root()).unwrap();
|
|
git::add(&repo);
|
|
git::commit(&repo);
|
|
p.change_file("Cargo.toml", &workspace_toml.replace("2.29.8", "2.29.81"));
|
|
|
|
p.cargo("update --workspace")
|
|
.with_stderr_data(str![[r#"
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] crate1 v2.29.8 ([ROOT]/foo/crate1) -> v2.29.81
|
|
[UPDATING] crate2 v2.29.8 ([ROOT]/foo/crate2) -> v2.29.81
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_precise_git_revisions() {
|
|
let (git_project, git_repo) = git::new_repo("git", |p| {
|
|
p.file("Cargo.toml", &basic_lib_manifest("git"))
|
|
.file("src/lib.rs", "")
|
|
});
|
|
let tag_name = "Nazgûl";
|
|
git::tag(&git_repo, tag_name);
|
|
let tag_commit_id = git_repo.head().unwrap().target().unwrap().to_string();
|
|
|
|
git_project.change_file("src/lib.rs", "fn f() {}");
|
|
git::add(&git_repo);
|
|
let head_id = git::commit(&git_repo).to_string();
|
|
let short_id = &head_id[..8];
|
|
let url = git_project.url();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
git = {{ git = '{url}' }}
|
|
"#
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("fetch")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] git repository `[ROOTURL]/git`
|
|
[LOCKING] 1 package to latest compatible version
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
assert!(p.read_lockfile().contains(&head_id));
|
|
|
|
p.cargo("update git --precise")
|
|
.arg(tag_name)
|
|
.with_stderr_data(format!(
|
|
"\
|
|
[UPDATING] git repository `[ROOTURL]/git`
|
|
[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}
|
|
",
|
|
&tag_commit_id[..8],
|
|
))
|
|
.run();
|
|
|
|
assert!(p.read_lockfile().contains(&tag_commit_id));
|
|
assert!(!p.read_lockfile().contains(&head_id));
|
|
|
|
p.cargo("update git --precise")
|
|
.arg(short_id)
|
|
.with_stderr_data(format!(
|
|
"\
|
|
[UPDATING] git repository `[ROOTURL]/git`
|
|
[UPDATING] git v0.5.0 ([ROOTURL]/git[..]) -> #{short_id}
|
|
",
|
|
))
|
|
.run();
|
|
|
|
assert!(p.read_lockfile().contains(&head_id));
|
|
assert!(!p.read_lockfile().contains(&tag_commit_id));
|
|
|
|
// updating back to tag still requires a git fetch,
|
|
// as the ref may change over time.
|
|
p.cargo("update git --precise")
|
|
.arg(tag_name)
|
|
.with_stderr_data(format!(
|
|
"\
|
|
[UPDATING] git repository `[ROOTURL]/git`
|
|
[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}
|
|
",
|
|
&tag_commit_id[..8],
|
|
))
|
|
.run();
|
|
|
|
assert!(p.read_lockfile().contains(&tag_commit_id));
|
|
assert!(!p.read_lockfile().contains(&head_id));
|
|
|
|
// Now make a tag looks like an oid.
|
|
// It requires a git fetch, as the oid cannot be found in preexisting git db.
|
|
let arbitrary_tag: String = std::iter::repeat('a').take(head_id.len()).collect();
|
|
git::tag(&git_repo, &arbitrary_tag);
|
|
|
|
p.cargo("update git --precise")
|
|
.arg(&arbitrary_tag)
|
|
.with_stderr_data(format!(
|
|
"\
|
|
[UPDATING] git repository `[ROOTURL]/git`
|
|
[UPDATING] git v0.5.0 ([ROOTURL]/git#[..]) -> #{}
|
|
",
|
|
&head_id[..8],
|
|
))
|
|
.run();
|
|
|
|
assert!(p.read_lockfile().contains(&head_id));
|
|
assert!(!p.read_lockfile().contains(&tag_commit_id));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn precise_yanked() {
|
|
Package::new("bar", "0.1.0").publish();
|
|
Package::new("bar", "0.1.1").yanked(true).publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
// Use non-yanked version.
|
|
let lockfile = p.read_lockfile();
|
|
assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.0\""));
|
|
|
|
p.cargo("update --precise 0.1.1 bar")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] selected package `bar@0.1.1` was yanked by the author
|
|
[NOTE] if possible, try a compatible non-yanked version
|
|
[UPDATING] bar v0.1.0 -> v0.1.1
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Use yanked version.
|
|
let lockfile = p.read_lockfile();
|
|
assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.1\""));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn precise_yanked_multiple_presence() {
|
|
Package::new("bar", "0.1.0").publish();
|
|
Package::new("bar", "0.1.1").yanked(true).publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
baz = { package = "bar", version = "0.1" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
// Use non-yanked version.
|
|
let lockfile = p.read_lockfile();
|
|
assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.0\""));
|
|
|
|
p.cargo("update --precise 0.1.1 bar")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] selected package `bar@0.1.1` was yanked by the author
|
|
[NOTE] if possible, try a compatible non-yanked version
|
|
[UPDATING] bar v0.1.0 -> v0.1.1
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Use yanked version.
|
|
let lockfile = p.read_lockfile();
|
|
assert!(lockfile.contains("\nname = \"bar\"\nversion = \"0.1.1\""));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn report_behind() {
|
|
Package::new("two-ver", "0.1.0").publish();
|
|
Package::new("two-ver", "0.2.0").publish();
|
|
Package::new("pre", "1.0.0-alpha.0").publish();
|
|
Package::new("pre", "1.0.0-alpha.1").publish();
|
|
Package::new("breaking", "0.1.0").publish();
|
|
Package::new("breaking", "0.2.0").publish();
|
|
Package::new("breaking", "0.2.1-alpha.0").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
|
|
[dependencies]
|
|
breaking = "0.1"
|
|
pre = "=1.0.0-alpha.0"
|
|
two-ver = "0.2.0"
|
|
two-ver-one = { version = "0.1.0", package = "two-ver" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
Package::new("breaking", "0.1.1").publish();
|
|
|
|
p.cargo("update --dry-run")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] breaking v0.1.0 -> v0.1.1 (latest: v0.2.0)
|
|
[NOTE] pass `--verbose` to see 2 unchanged dependencies behind latest
|
|
[WARNING] not updating lockfile due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update --dry-run --verbose")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] breaking v0.1.0 -> v0.1.1 (latest: v0.2.0)
|
|
[UNCHANGED] pre v1.0.0-alpha.0 (latest compatible: v1.0.0-alpha.1)
|
|
[UNCHANGED] two-ver v0.1.0 (latest: v0.2.0)
|
|
[NOTE] to see how you depend on a package, run `cargo tree --invert --package <dep>@<ver>`
|
|
[WARNING] not updating lockfile due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update").run();
|
|
|
|
p.cargo("update --dry-run")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 0 packages to latest compatible versions
|
|
[NOTE] pass `--verbose` to see 3 unchanged dependencies behind latest
|
|
[WARNING] not updating lockfile due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
p.cargo("update --dry-run --verbose")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 0 packages to latest compatible versions
|
|
[UNCHANGED] breaking v0.1.1 (latest: v0.2.0)
|
|
[UNCHANGED] pre v1.0.0-alpha.0 (latest compatible: v1.0.0-alpha.1)
|
|
[UNCHANGED] two-ver v0.1.0 (latest: v0.2.0)
|
|
[NOTE] to see how you depend on a package, run `cargo tree --invert --package <dep>@<ver>`
|
|
[WARNING] not updating lockfile due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_with_missing_feature() {
|
|
// Attempting to update a package to a version with a missing feature
|
|
// should produce a warning.
|
|
Package::new("bar", "0.1.0").feature("feat1", &[]).publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
edition = "2015"
|
|
|
|
[dependencies]
|
|
bar = {version="0.1", features=["feat1"]}
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
// Publish an update that is missing the feature.
|
|
Package::new("bar", "0.1.1").publish();
|
|
|
|
p.cargo("update")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 0 packages to latest compatible versions
|
|
[NOTE] pass `--verbose` to see 1 unchanged dependencies behind latest
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Publish a fixed version, should not warn.
|
|
Package::new("bar", "0.1.2").feature("feat1", &[]).publish();
|
|
p.cargo("update")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v0.1.0 -> v0.1.2
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_unstable() {
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("update --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] the `--breaking` flag is unstable, pass `-Z unstable-options` to enable it
|
|
See https://github.com/rust-lang/cargo/issues/12425 for more information about the `--breaking` flag.
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_dry_run() {
|
|
Package::new("incompatible", "1.0.0").publish();
|
|
Package::new("ws", "1.0.0").publish();
|
|
|
|
let root_manifest = r#"
|
|
# Check if formatting is preserved. Nothing here should change, due to dry-run.
|
|
|
|
[workspace]
|
|
members = ["foo"]
|
|
|
|
[workspace.dependencies]
|
|
ws = "1.0" # Preserve formatting
|
|
"#;
|
|
|
|
let crate_manifest = r#"
|
|
# Check if formatting is preserved. Nothing here should change, due to dry-run.
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
incompatible = "1.0" # Preserve formatting
|
|
ws.workspace = true # Preserve formatting
|
|
"#;
|
|
|
|
let p = project()
|
|
.file("Cargo.toml", root_manifest)
|
|
.file("foo/Cargo.toml", crate_manifest)
|
|
.file("foo/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
let lock_file = p.read_file("Cargo.lock");
|
|
|
|
Package::new("incompatible", "1.0.1").publish();
|
|
Package::new("ws", "1.0.1").publish();
|
|
|
|
Package::new("incompatible", "2.0.0").publish();
|
|
Package::new("ws", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --dry-run --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPGRADING] incompatible ^1.0 -> ^2.0
|
|
[UPGRADING] ws ^1.0 -> ^2.0
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
[UPDATING] incompatible v1.0.0 -> v2.0.0
|
|
[UPDATING] ws v1.0.0 -> v2.0.0
|
|
[WARNING] aborting update due to dry run
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let root_manifest_after = p.read_file("Cargo.toml");
|
|
assert_e2e().eq(&root_manifest_after, root_manifest);
|
|
|
|
let crate_manifest_after = p.read_file("foo/Cargo.toml");
|
|
assert_e2e().eq(&crate_manifest_after, crate_manifest);
|
|
|
|
let lock_file_after = p.read_file("Cargo.lock");
|
|
assert_e2e().eq(&lock_file_after, lock_file);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking() {
|
|
registry::alt_init();
|
|
Package::new("compatible", "1.0.0").publish();
|
|
Package::new("incompatible", "1.0.0").publish();
|
|
Package::new("pinned", "1.0.0").publish();
|
|
Package::new("less-than", "1.0.0").publish();
|
|
Package::new("renamed-from", "1.0.0").publish();
|
|
Package::new("pre-release", "1.0.0").publish();
|
|
Package::new("yanked", "1.0.0").publish();
|
|
Package::new("ws", "1.0.0").publish();
|
|
Package::new("shared", "1.0.0").publish();
|
|
Package::new("multiple-locations", "1.0.0").publish();
|
|
Package::new("multiple-versions", "1.0.0").publish();
|
|
Package::new("multiple-versions", "2.0.0").publish();
|
|
Package::new("alternative-1", "1.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("alternative-2", "1.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("bar", "1.0.0").alternative(true).publish();
|
|
Package::new("multiple-registries", "1.0.0").publish();
|
|
Package::new("multiple-registries", "2.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("multiple-source-types", "1.0.0").publish();
|
|
Package::new("platform-specific", "1.0.0").publish();
|
|
Package::new("dev", "1.0.0").publish();
|
|
Package::new("build", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
# Check if formatting is preserved
|
|
|
|
[workspace]
|
|
members = ["foo", "bar"]
|
|
|
|
[workspace.dependencies]
|
|
ws = "1.0" # This line gets partially rewritten
|
|
"#,
|
|
)
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
# Check if formatting is preserved
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
compatible = "1.0" # Comment
|
|
incompatible = "1.0" # Comment
|
|
pinned = "=1.0" # Comment
|
|
less-than = "<99.0" # Comment
|
|
renamed-to = { package = "renamed-from", version = "1.0" } # Comment
|
|
pre-release = "1.0" # Comment
|
|
yanked = "1.0" # Comment
|
|
ws.workspace = true # Comment
|
|
shared = "1.0" # Comment
|
|
multiple-locations = { path = "../multiple-locations", version = "1.0" } # Comment
|
|
multiple-versions = "1.0" # Comment
|
|
alternative-1 = { registry = "alternative", version = "1.0" } # Comment
|
|
multiple-registries = "1.0" # Comment
|
|
bar = { path = "../bar", registry = "alternative", version = "1.0.0" } # Comment
|
|
multiple-source-types = { path = "../multiple-source-types", version = "1.0.0" } # Comment
|
|
|
|
[dependencies.alternative-2] # Comment
|
|
version = "1.0" # Comment
|
|
registry = "alternative" # Comment
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
platform-specific = "1.0" # Comment
|
|
|
|
[dev-dependencies]
|
|
dev = "1.0" # Comment
|
|
|
|
[build-dependencies]
|
|
build = "1.0" # Comment
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "1.0.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
shared = "1.0"
|
|
multiple-versions = "2.0"
|
|
multiple-registries = { registry = "alternative", version = "2.0" } # Comment
|
|
multiple-source-types = "1.0" # Comment
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.file(
|
|
"multiple-locations/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "multiple-locations"
|
|
version = "1.0.0"
|
|
edition = "2015"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("multiple-locations/src/lib.rs", "")
|
|
.file(
|
|
"multiple-source-types/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "multiple-source-types"
|
|
version = "1.0.0"
|
|
edition = "2015"
|
|
authors = []
|
|
"#,
|
|
)
|
|
.file("multiple-source-types/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("compatible", "1.0.1").publish();
|
|
Package::new("incompatible", "1.0.1").publish();
|
|
Package::new("pinned", "1.0.1").publish();
|
|
Package::new("less-than", "1.0.1").publish();
|
|
Package::new("renamed-from", "1.0.1").publish();
|
|
Package::new("ws", "1.0.1").publish();
|
|
Package::new("multiple-locations", "1.0.1").publish();
|
|
Package::new("multiple-versions", "1.0.1").publish();
|
|
Package::new("multiple-versions", "2.0.1").publish();
|
|
Package::new("alternative-1", "1.0.1")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("alternative-2", "1.0.1")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("platform-specific", "1.0.1").publish();
|
|
Package::new("dev", "1.0.1").publish();
|
|
Package::new("build", "1.0.1").publish();
|
|
|
|
Package::new("incompatible", "2.0.0").publish();
|
|
Package::new("pinned", "2.0.0").publish();
|
|
Package::new("less-than", "2.0.0").publish();
|
|
Package::new("renamed-from", "2.0.0").publish();
|
|
Package::new("pre-release", "2.0.0-alpha").publish();
|
|
Package::new("yanked", "2.0.0").yanked(true).publish();
|
|
Package::new("ws", "2.0.0").publish();
|
|
Package::new("shared", "2.0.0").publish();
|
|
Package::new("multiple-locations", "2.0.0").publish();
|
|
Package::new("multiple-versions", "3.0.0").publish();
|
|
Package::new("alternative-1", "2.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("alternative-2", "2.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("bar", "2.0.0").alternative(true).publish();
|
|
Package::new("multiple-registries", "2.0.0").publish();
|
|
Package::new("multiple-registries", "3.0.0")
|
|
.alternative(true)
|
|
.publish();
|
|
Package::new("multiple-source-types", "2.0.0").publish();
|
|
Package::new("platform-specific", "2.0.0").publish();
|
|
Package::new("dev", "2.0.0").publish();
|
|
Package::new("build", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `alternative` index
|
|
[UPGRADING] multiple-registries ^2.0 -> ^3.0
|
|
[UPDATING] `dummy-registry` index
|
|
[UPGRADING] multiple-source-types ^1.0 -> ^2.0
|
|
[UPGRADING] multiple-versions ^2.0 -> ^3.0
|
|
[UPGRADING] shared ^1.0 -> ^2.0
|
|
[UPGRADING] alternative-1 ^1.0 -> ^2.0
|
|
[UPGRADING] alternative-2 ^1.0 -> ^2.0
|
|
[UPGRADING] incompatible ^1.0 -> ^2.0
|
|
[UPGRADING] multiple-registries ^1.0 -> ^2.0
|
|
[UPGRADING] multiple-versions ^1.0 -> ^3.0
|
|
[UPGRADING] ws ^1.0 -> ^2.0
|
|
[UPGRADING] dev ^1.0 -> ^2.0
|
|
[UPGRADING] build ^1.0 -> ^2.0
|
|
[UPGRADING] platform-specific ^1.0 -> ^2.0
|
|
[LOCKING] 12 packages to latest compatible versions
|
|
[UPDATING] alternative-1 v1.0.0 (registry `alternative`) -> v2.0.0
|
|
[UPDATING] alternative-2 v1.0.0 (registry `alternative`) -> v2.0.0
|
|
[UPDATING] build v1.0.0 -> v2.0.0
|
|
[UPDATING] dev v1.0.0 -> v2.0.0
|
|
[UPDATING] incompatible v1.0.0 -> v2.0.0
|
|
[UPDATING] multiple-registries v2.0.0 (registry `alternative`) -> v3.0.0
|
|
[UPDATING] multiple-registries v1.0.0 -> v2.0.0
|
|
[UPDATING] multiple-source-types v1.0.0 -> v2.0.0
|
|
[ADDING] multiple-versions v3.0.0
|
|
[UPDATING] platform-specific v1.0.0 -> v2.0.0
|
|
[UPDATING] shared v1.0.0 -> v2.0.0
|
|
[UPDATING] ws v1.0.0 -> v2.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let root_manifest = p.read_file("Cargo.toml");
|
|
assert_e2e().eq(
|
|
&root_manifest,
|
|
str![[r#"
|
|
|
|
# Check if formatting is preserved
|
|
|
|
[workspace]
|
|
members = ["foo", "bar"]
|
|
|
|
[workspace.dependencies]
|
|
ws = "2.0" # This line gets partially rewritten
|
|
"#]],
|
|
);
|
|
|
|
let foo_manifest = p.read_file("foo/Cargo.toml");
|
|
|
|
assert_e2e().eq(
|
|
&foo_manifest,
|
|
str![[r#"
|
|
|
|
# Check if formatting is preserved
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
compatible = "1.0" # Comment
|
|
incompatible = "2.0" # Comment
|
|
pinned = "=1.0" # Comment
|
|
less-than = "<99.0" # Comment
|
|
renamed-to = { package = "renamed-from", version = "1.0" } # Comment
|
|
pre-release = "1.0" # Comment
|
|
yanked = "1.0" # Comment
|
|
ws.workspace = true # Comment
|
|
shared = "2.0" # Comment
|
|
multiple-locations = { path = "../multiple-locations", version = "1.0" } # Comment
|
|
multiple-versions = "3.0" # Comment
|
|
alternative-1 = { registry = "alternative", version = "2.0" } # Comment
|
|
multiple-registries = "2.0" # Comment
|
|
bar = { path = "../bar", registry = "alternative", version = "1.0.0" } # Comment
|
|
multiple-source-types = { path = "../multiple-source-types", version = "1.0.0" } # Comment
|
|
|
|
[dependencies.alternative-2] # Comment
|
|
version = "2.0" # Comment
|
|
registry = "alternative" # Comment
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
platform-specific = "2.0" # Comment
|
|
|
|
[dev-dependencies]
|
|
dev = "2.0" # Comment
|
|
|
|
[build-dependencies]
|
|
build = "2.0" # Comment
|
|
"#]],
|
|
);
|
|
|
|
let bar_manifest = p.read_file("bar/Cargo.toml");
|
|
|
|
assert_e2e().eq(
|
|
&bar_manifest,
|
|
str![[r#"
|
|
|
|
[package]
|
|
name = "bar"
|
|
version = "1.0.0"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
shared = "2.0"
|
|
multiple-versions = "3.0"
|
|
multiple-registries = { registry = "alternative", version = "3.0" } # Comment
|
|
multiple-source-types = "2.0" # Comment
|
|
"#]],
|
|
);
|
|
|
|
p.cargo("update")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `alternative` index
|
|
[UPDATING] `dummy-registry` index
|
|
[LOCKING] 4 packages to latest compatible versions
|
|
[UPDATING] compatible v1.0.0 -> v1.0.1
|
|
[UPDATING] less-than v1.0.0 -> v2.0.0
|
|
[UPDATING] pinned v1.0.0 -> v1.0.1 (latest: v2.0.0)
|
|
[UPDATING] renamed-from v1.0.0 -> v1.0.1 (latest: v2.0.0)
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_specific_packages() {
|
|
Package::new("just-foo", "1.0.0")
|
|
.add_dep(Dependency::new("transitive-compatible", "1.0.0").build())
|
|
.add_dep(Dependency::new("transitive-incompatible", "1.0.0").build())
|
|
.publish();
|
|
Package::new("just-bar", "1.0.0").publish();
|
|
Package::new("shared", "1.0.0").publish();
|
|
Package::new("ws", "1.0.0").publish();
|
|
Package::new("transitive-compatible", "1.0.0").publish();
|
|
Package::new("transitive-incompatible", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["foo", "bar"]
|
|
|
|
[workspace.dependencies]
|
|
ws = "1.0"
|
|
"#,
|
|
)
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
just-foo = "1.0"
|
|
shared = "1.0"
|
|
ws.workspace = true
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
just-bar = "1.0"
|
|
shared = "1.0"
|
|
ws.workspace = true
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("just-foo", "1.0.1")
|
|
.add_dep(Dependency::new("transitive-compatible", "1.0.0").build())
|
|
.add_dep(Dependency::new("transitive-incompatible", "1.0.0").build())
|
|
.publish();
|
|
Package::new("just-bar", "1.0.1").publish();
|
|
Package::new("shared", "1.0.1").publish();
|
|
Package::new("ws", "1.0.1").publish();
|
|
Package::new("transitive-compatible", "1.0.1").publish();
|
|
Package::new("transitive-incompatible", "1.0.1").publish();
|
|
|
|
Package::new("just-foo", "2.0.0")
|
|
// Upgrading just-foo implies accepting an update of transitive-compatible.
|
|
.add_dep(Dependency::new("transitive-compatible", "1.0.1").build())
|
|
// Upgrading just-foo implies accepting a major update of transitive-incompatible.
|
|
.add_dep(Dependency::new("transitive-incompatible", "2.0.0").build())
|
|
.publish();
|
|
Package::new("just-bar", "2.0.0").publish();
|
|
Package::new("shared", "2.0.0").publish();
|
|
Package::new("ws", "2.0.0").publish();
|
|
Package::new("transitive-incompatible", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking just-foo shared ws")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPGRADING] shared ^1.0 -> ^2.0
|
|
[UPGRADING] ws ^1.0 -> ^2.0
|
|
[UPGRADING] just-foo ^1.0 -> ^2.0
|
|
[LOCKING] 5 packages to latest compatible versions
|
|
[UPDATING] just-foo v1.0.0 -> v2.0.0
|
|
[UPDATING] shared v1.0.0 -> v2.0.0
|
|
[UPDATING] transitive-compatible v1.0.0 -> v1.0.1
|
|
[UPDATING] transitive-incompatible v1.0.0 -> v2.0.0
|
|
[UPDATING] ws v1.0.0 -> v2.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_specific_packages_that_wont_update() {
|
|
Package::new("compatible", "1.0.0").publish();
|
|
Package::new("renamed-from", "1.0.0").publish();
|
|
Package::new("non-semver", "1.0.0").publish();
|
|
Package::new("bar", "1.0.0")
|
|
.add_dep(Dependency::new("transitive-compatible", "1.0.0").build())
|
|
.add_dep(Dependency::new("transitive-incompatible", "1.0.0").build())
|
|
.publish();
|
|
Package::new("transitive-compatible", "1.0.0").publish();
|
|
Package::new("transitive-incompatible", "1.0.0").publish();
|
|
|
|
let crate_manifest = r#"
|
|
# Check if formatting is preserved
|
|
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
compatible = "1.0" # Comment
|
|
renamed-to = { package = "renamed-from", version = "1.0" } # Comment
|
|
non-semver = "~1.0" # Comment
|
|
bar = "1.0" # Comment
|
|
"#;
|
|
|
|
let p = project()
|
|
.file("Cargo.toml", crate_manifest)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
let lock_file = p.read_file("Cargo.lock");
|
|
|
|
Package::new("compatible", "1.0.1").publish();
|
|
Package::new("renamed-from", "1.0.1").publish();
|
|
Package::new("non-semver", "1.0.1").publish();
|
|
Package::new("transitive-compatible", "1.0.1").publish();
|
|
Package::new("transitive-incompatible", "1.0.1").publish();
|
|
|
|
Package::new("renamed-from", "2.0.0").publish();
|
|
Package::new("non-semver", "2.0.0").publish();
|
|
Package::new("transitive-incompatible", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking compatible renamed-from non-semver transitive-compatible transitive-incompatible")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let crate_manifest_after = p.read_file("Cargo.toml");
|
|
assert_e2e().eq(&crate_manifest_after, crate_manifest);
|
|
|
|
let lock_file_after = p.read_file("Cargo.lock");
|
|
assert_e2e().eq(&lock_file_after, lock_file);
|
|
|
|
p.cargo(
|
|
"update compatible renamed-from non-semver transitive-compatible transitive-incompatible",
|
|
)
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[LOCKING] 5 packages to latest compatible versions
|
|
[UPDATING] compatible v1.0.0 -> v1.0.1
|
|
[UPDATING] non-semver v1.0.0 -> v1.0.1 (latest: v2.0.0)
|
|
[UPDATING] renamed-from v1.0.0 -> v1.0.1 (latest: v2.0.0)
|
|
[UPDATING] transitive-compatible v1.0.0 -> v1.0.1
|
|
[UPDATING] transitive-incompatible v1.0.0 -> v1.0.1 (latest: v2.0.0)
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_without_lock_file() {
|
|
Package::new("compatible", "1.0.0").publish();
|
|
Package::new("incompatible", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
compatible = "1.0" # Comment
|
|
incompatible = "1.0" # Comment
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
Package::new("compatible", "1.0.1").publish();
|
|
Package::new("incompatible", "1.0.1").publish();
|
|
|
|
Package::new("incompatible", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] incompatible ^1.0 -> ^2.0
|
|
[LOCKING] 2 packages to latest compatible versions
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_spec_version() {
|
|
Package::new("compatible", "1.0.0").publish();
|
|
Package::new("incompatible", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
compatible = "1.0" # Comment
|
|
incompatible = "1.0" # Comment
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("compatible", "1.0.1").publish();
|
|
Package::new("incompatible", "1.0.1").publish();
|
|
|
|
Package::new("incompatible", "2.0.0").publish();
|
|
|
|
// Invalid spec
|
|
p.cargo("update -Zunstable-options --breaking incompatible@foo")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_status(101)
|
|
.with_stderr_data(str![[r#"
|
|
[ERROR] invalid package ID specification: `incompatible@foo`
|
|
|
|
Caused by:
|
|
expected a version like "1.32"
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Spec version not matching our current dependencies
|
|
p.cargo("update -Zunstable-options --breaking incompatible@2.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#""#]])
|
|
.run();
|
|
|
|
// Spec source not matching our current dependencies
|
|
p.cargo("update -Zunstable-options --breaking https://alternative.com#incompatible@1.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#""#]])
|
|
.run();
|
|
|
|
// Accepted spec
|
|
p.cargo("update -Zunstable-options --breaking incompatible@1.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] incompatible ^1.0 -> ^2.0
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] incompatible v1.0.0 -> v2.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Accepted spec, full format
|
|
Package::new("incompatible", "3.0.0").publish();
|
|
p.cargo("update -Zunstable-options --breaking https://github.com/rust-lang/crates.io-index#incompatible@2.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] incompatible ^2.0 -> ^3.0
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] incompatible v2.0.0 -> v3.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Spec matches a dependency that will not be upgraded
|
|
p.cargo("update -Zunstable-options --breaking compatible@1.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// Non-existing versions
|
|
p.cargo("update -Zunstable-options --breaking incompatible@9.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#""#]])
|
|
.run();
|
|
|
|
p.cargo("update -Zunstable-options --breaking compatible@9.0.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#""#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_spec_version_transitive() {
|
|
Package::new("dep", "1.0.0").publish();
|
|
Package::new("dep", "1.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
dep = "1.0"
|
|
bar = { path = "bar", version = "0.0.1" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
dep = "1.1"
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("dep", "1.1.1").publish();
|
|
Package::new("dep", "2.0.0").publish();
|
|
|
|
// Will upgrade the direct dependency
|
|
p.cargo("update -Zunstable-options --breaking dep@1.0")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] dep ^1.0 -> ^2.0
|
|
[LOCKING] 1 package to latest compatible version
|
|
[ADDING] dep v2.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// But not the transitive one, because bar is not a workspace member
|
|
p.cargo("update -Zunstable-options --breaking dep@1.1")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
// A non-breaking update is different, as it will update transitive dependencies
|
|
p.cargo("update dep@1.1")
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] dep v1.1.0 -> v1.1.1 (latest: v2.0.0)
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_mixed_compatibility() {
|
|
Package::new("mixed-compatibility", "1.0.0").publish();
|
|
Package::new("mixed-compatibility", "2.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["foo", "bar"]
|
|
"#,
|
|
)
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-compatibility = "1.0"
|
|
"#,
|
|
)
|
|
.file("foo/src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-compatibility = "2.0"
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("mixed-compatibility", "2.0.1").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] mixed-compatibility ^1.0 -> ^2.0
|
|
[LOCKING] 1 package to latest compatible version
|
|
[ADDING] mixed-compatibility v2.0.1
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_mixed_pinning_renaming() {
|
|
Package::new("mixed-pinned", "1.0.0").publish();
|
|
Package::new("mixed-ws-pinned", "1.0.0").publish();
|
|
Package::new("renamed-from", "1.0.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["pinned", "unpinned", "mixed"]
|
|
|
|
[workspace.dependencies]
|
|
mixed-ws-pinned = "=1.0"
|
|
"#,
|
|
)
|
|
.file(
|
|
"pinned/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "pinned"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-pinned = "=1.0"
|
|
mixed-ws-pinned.workspace = true
|
|
renamed-to = { package = "renamed-from", version = "1.0" }
|
|
"#,
|
|
)
|
|
.file("pinned/src/lib.rs", "")
|
|
.file(
|
|
"unpinned/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "unpinned"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-pinned = "1.0"
|
|
mixed-ws-pinned = "1.0"
|
|
renamed-from = "1.0"
|
|
"#,
|
|
)
|
|
.file("unpinned/src/lib.rs", "")
|
|
.file(
|
|
"mixed/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "mixed"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[target.'cfg(windows)'.dependencies]
|
|
mixed-pinned = "1.0"
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
mixed-pinned = "=1.0"
|
|
"#,
|
|
)
|
|
.file("mixed/src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
Package::new("mixed-pinned", "2.0.0").publish();
|
|
Package::new("mixed-ws-pinned", "2.0.0").publish();
|
|
Package::new("renamed-from", "2.0.0").publish();
|
|
|
|
p.cargo("update -Zunstable-options --breaking")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `[..]` index
|
|
[UPGRADING] mixed-pinned ^1.0 -> ^2.0
|
|
[UPGRADING] mixed-ws-pinned ^1.0 -> ^2.0
|
|
[UPGRADING] renamed-from ^1.0 -> ^2.0
|
|
[LOCKING] 3 packages to latest compatible versions
|
|
[ADDING] mixed-pinned v2.0.0
|
|
[ADDING] mixed-ws-pinned v2.0.0
|
|
[ADDING] renamed-from v2.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
let root_manifest = p.read_file("Cargo.toml");
|
|
assert_e2e().eq(
|
|
&root_manifest,
|
|
str![[r#"
|
|
|
|
[workspace]
|
|
members = ["pinned", "unpinned", "mixed"]
|
|
|
|
[workspace.dependencies]
|
|
mixed-ws-pinned = "=1.0"
|
|
"#]],
|
|
);
|
|
|
|
let pinned_manifest = p.read_file("pinned/Cargo.toml");
|
|
assert_e2e().eq(
|
|
&pinned_manifest,
|
|
str![[r#"
|
|
|
|
[package]
|
|
name = "pinned"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-pinned = "=1.0"
|
|
mixed-ws-pinned.workspace = true
|
|
renamed-to = { package = "renamed-from", version = "1.0" }
|
|
"#]],
|
|
);
|
|
|
|
let unpinned_manifest = p.read_file("unpinned/Cargo.toml");
|
|
assert_e2e().eq(
|
|
&unpinned_manifest,
|
|
str![[r#"
|
|
|
|
[package]
|
|
name = "unpinned"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
mixed-pinned = "2.0"
|
|
mixed-ws-pinned = "2.0"
|
|
renamed-from = "2.0"
|
|
"#]],
|
|
);
|
|
|
|
let mixed_manifest = p.read_file("mixed/Cargo.toml");
|
|
assert_e2e().eq(
|
|
&mixed_manifest,
|
|
str![[r#"
|
|
|
|
[package]
|
|
name = "mixed"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[target.'cfg(windows)'.dependencies]
|
|
mixed-pinned = "2.0"
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
mixed-pinned = "=1.0"
|
|
"#]],
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_pre_release_downgrade() {
|
|
Package::new("bar", "2.0.0-beta.21").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "2.0.0-beta.21"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
// The purpose of this test is
|
|
// to demonstrate that `update --breaking` will not try to downgrade to the latest stable version (1.7.0),
|
|
// but will rather keep the latest pre-release (2.0.0-beta.21).
|
|
Package::new("bar", "1.7.0").publish();
|
|
p.cargo("update -Zunstable-options --breaking bar")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
|
|
"#]])
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn update_breaking_pre_release_upgrade() {
|
|
Package::new("bar", "2.0.0-beta.21").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
edition = "2015"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "2.0.0-beta.21"
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("generate-lockfile").run();
|
|
|
|
// TODO: `2.0.0-beta.21` can be upgraded to `2.0.0-beta.22`
|
|
Package::new("bar", "2.0.0-beta.22").publish();
|
|
p.cargo("update -Zunstable-options --breaking bar")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
|
|
"#]])
|
|
.run();
|
|
// TODO: `2.0.0-beta.21` can be upgraded to `2.0.0`
|
|
Package::new("bar", "2.0.0").publish();
|
|
p.cargo("update -Zunstable-options --breaking bar")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
|
|
"#]])
|
|
.run();
|
|
|
|
Package::new("bar", "3.0.0").publish();
|
|
p.cargo("update -Zunstable-options --breaking bar")
|
|
.masquerade_as_nightly_cargo(&["update-breaking"])
|
|
.with_stderr_data(str![[r#"
|
|
[UPDATING] `dummy-registry` index
|
|
[UPGRADING] bar ^2.0.0-beta.21 -> ^3.0.0
|
|
[LOCKING] 1 package to latest compatible version
|
|
[UPDATING] bar v2.0.0-beta.21 -> v3.0.0
|
|
|
|
"#]])
|
|
.run();
|
|
}
|