mirror of
https://github.com/rust-lang/cargo
synced 2024-07-05 01:19:13 +00:00
Compare commits
3 Commits
93c2ede8e6
...
48dc39eedd
Author | SHA1 | Date | |
---|---|---|---|
|
48dc39eedd | ||
|
6414a5b68f | ||
|
3f37cb8c25 |
|
@ -1,8 +1,11 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::command_prelude::*;
|
use crate::command_prelude::*;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use cargo::ops::{self, UpdateOptions};
|
use cargo::ops::{self, UpdateOptions};
|
||||||
use cargo::util::print_available_packages;
|
use cargo::util::print_available_packages;
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
pub fn cli() -> Command {
|
pub fn cli() -> Command {
|
||||||
subcommand("update")
|
subcommand("update")
|
||||||
|
@ -92,28 +95,39 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
|
||||||
let update_opts = UpdateOptions {
|
let update_opts = UpdateOptions {
|
||||||
recursive: args.flag("recursive"),
|
recursive: args.flag("recursive"),
|
||||||
precise: args.get_one::<String>("precise").map(String::as_str),
|
precise: args.get_one::<String>("precise").map(String::as_str),
|
||||||
|
breaking: args.flag("breaking"),
|
||||||
to_update,
|
to_update,
|
||||||
dry_run: args.dry_run(),
|
dry_run: args.dry_run(),
|
||||||
workspace: args.flag("workspace"),
|
workspace: args.flag("workspace"),
|
||||||
gctx,
|
gctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.flag("breaking") {
|
let breaking_update = update_opts.breaking
|
||||||
gctx.cli_unstable()
|
|| (update_opts.precise.is_some() && gctx.cli_unstable().unstable_options);
|
||||||
.fail_if_stable_opt("--breaking", 12425)?;
|
|
||||||
|
|
||||||
let upgrades = ops::upgrade_manifests(&mut ws, &update_opts.to_update)?;
|
// We are using the term "upgrade" here, which is the typical case, but
|
||||||
ops::resolve_ws(&ws, update_opts.dry_run)?;
|
// it can also be a downgrade. In general, it is a change to a version
|
||||||
ops::write_manifest_upgrades(&ws, &upgrades, update_opts.dry_run)?;
|
// req matching a precise version.
|
||||||
|
let upgrades = if breaking_update {
|
||||||
if update_opts.dry_run {
|
if update_opts.breaking {
|
||||||
update_opts
|
gctx.cli_unstable()
|
||||||
.gctx
|
.fail_if_stable_opt("--breaking", 12425)?;
|
||||||
.shell()
|
|
||||||
.warn("aborting update due to dry run")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!("allowing breaking updates");
|
||||||
|
ops::upgrade_manifests(&mut ws, &update_opts.to_update, &update_opts.precise)?
|
||||||
} else {
|
} else {
|
||||||
ops::update_lockfile(&ws, &update_opts)?;
|
HashMap::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
ops::update_lockfile(&ws, &update_opts, &upgrades)?;
|
||||||
|
ops::write_manifest_upgrades(&ws, &upgrades, update_opts.dry_run)?;
|
||||||
|
|
||||||
|
if update_opts.dry_run {
|
||||||
|
update_opts
|
||||||
|
.gctx
|
||||||
|
.shell()
|
||||||
|
.warn("aborting update due to dry run")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -14,6 +14,7 @@ use crate::util::toml_mut::manifest::LocalManifest;
|
||||||
use crate::util::toml_mut::upgrade::upgrade_requirement;
|
use crate::util::toml_mut::upgrade::upgrade_requirement;
|
||||||
use crate::util::{style, OptVersionReq};
|
use crate::util::{style, OptVersionReq};
|
||||||
use crate::util::{CargoResult, VersionExt};
|
use crate::util::{CargoResult, VersionExt};
|
||||||
|
use anyhow::Context;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use semver::{Op, Version, VersionReq};
|
use semver::{Op, Version, VersionReq};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -26,6 +27,7 @@ pub struct UpdateOptions<'a> {
|
||||||
pub gctx: &'a GlobalContext,
|
pub gctx: &'a GlobalContext,
|
||||||
pub to_update: Vec<String>,
|
pub to_update: Vec<String>,
|
||||||
pub precise: Option<&'a str>,
|
pub precise: Option<&'a str>,
|
||||||
|
pub breaking: bool,
|
||||||
pub recursive: bool,
|
pub recursive: bool,
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
pub workspace: bool,
|
pub workspace: bool,
|
||||||
|
@ -49,7 +51,11 @@ pub fn generate_lockfile(ws: &Workspace<'_>) -> CargoResult<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {
|
pub fn update_lockfile(
|
||||||
|
ws: &Workspace<'_>,
|
||||||
|
opts: &UpdateOptions<'_>,
|
||||||
|
upgrades: &UpgradeMap,
|
||||||
|
) -> CargoResult<()> {
|
||||||
if opts.recursive && opts.precise.is_some() {
|
if opts.recursive && opts.precise.is_some() {
|
||||||
anyhow::bail!("cannot specify both recursive and precise simultaneously")
|
anyhow::bail!("cannot specify both recursive and precise simultaneously")
|
||||||
}
|
}
|
||||||
|
@ -165,7 +171,12 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
|
||||||
.filter(|s| !s.is_registry())
|
.filter(|s| !s.is_registry())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let keep = |p: &PackageId| !to_avoid_sources.contains(&p.source_id()) && !to_avoid.contains(p);
|
let keep = |p: &PackageId| {
|
||||||
|
(!to_avoid_sources.contains(&p.source_id()) && !to_avoid.contains(p))
|
||||||
|
// In case of `--breaking`, we want to keep all packages unchanged that
|
||||||
|
// didn't get upgraded.
|
||||||
|
|| (opts.breaking && !upgrades.contains_key(&(p.name().to_string(), p.source_id())))
|
||||||
|
};
|
||||||
|
|
||||||
let mut resolve = ops::resolve_with_previous(
|
let mut resolve = ops::resolve_with_previous(
|
||||||
&mut registry,
|
&mut registry,
|
||||||
|
@ -185,11 +196,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
|
||||||
opts.precise.is_some(),
|
opts.precise.is_some(),
|
||||||
&mut registry,
|
&mut registry,
|
||||||
)?;
|
)?;
|
||||||
if opts.dry_run {
|
if !opts.dry_run {
|
||||||
opts.gctx
|
|
||||||
.shell()
|
|
||||||
.warn("not updating lockfile due to dry run")?;
|
|
||||||
} else {
|
|
||||||
ops::write_pkg_lockfile(ws, &mut resolve)?;
|
ops::write_pkg_lockfile(ws, &mut resolve)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -217,6 +224,7 @@ pub fn print_lockfile_changes(
|
||||||
pub fn upgrade_manifests(
|
pub fn upgrade_manifests(
|
||||||
ws: &mut Workspace<'_>,
|
ws: &mut Workspace<'_>,
|
||||||
to_update: &Vec<String>,
|
to_update: &Vec<String>,
|
||||||
|
precise: &Option<&str>,
|
||||||
) -> CargoResult<UpgradeMap> {
|
) -> CargoResult<UpgradeMap> {
|
||||||
let gctx = ws.gctx();
|
let gctx = ws.gctx();
|
||||||
let mut upgrades = HashMap::new();
|
let mut upgrades = HashMap::new();
|
||||||
|
@ -245,6 +253,7 @@ pub fn upgrade_manifests(
|
||||||
upgrade_dependency(
|
upgrade_dependency(
|
||||||
&gctx,
|
&gctx,
|
||||||
&to_update,
|
&to_update,
|
||||||
|
precise,
|
||||||
&mut registry,
|
&mut registry,
|
||||||
&mut upgrades,
|
&mut upgrades,
|
||||||
&mut upgrade_messages,
|
&mut upgrade_messages,
|
||||||
|
@ -259,6 +268,7 @@ pub fn upgrade_manifests(
|
||||||
fn upgrade_dependency(
|
fn upgrade_dependency(
|
||||||
gctx: &GlobalContext,
|
gctx: &GlobalContext,
|
||||||
to_update: &Vec<PackageIdSpec>,
|
to_update: &Vec<PackageIdSpec>,
|
||||||
|
precise: &Option<&str>,
|
||||||
registry: &mut PackageRegistry<'_>,
|
registry: &mut PackageRegistry<'_>,
|
||||||
upgrades: &mut UpgradeMap,
|
upgrades: &mut UpgradeMap,
|
||||||
upgrade_messages: &mut HashSet<String>,
|
upgrade_messages: &mut HashSet<String>,
|
||||||
|
@ -316,7 +326,7 @@ fn upgrade_dependency(
|
||||||
let query =
|
let query =
|
||||||
crate::core::dependency::Dependency::parse(name, None, dependency.source_id().clone())?;
|
crate::core::dependency::Dependency::parse(name, None, dependency.source_id().clone())?;
|
||||||
|
|
||||||
let possibilities = {
|
let possibilities = if precise.is_none() {
|
||||||
loop {
|
loop {
|
||||||
match registry.query_vec(&query, QueryKind::Exact) {
|
match registry.query_vec(&query, QueryKind::Exact) {
|
||||||
std::task::Poll::Ready(res) => {
|
std::task::Poll::Ready(res) => {
|
||||||
|
@ -325,6 +335,8 @@ fn upgrade_dependency(
|
||||||
std::task::Poll::Pending => registry.block_until_ready()?,
|
std::task::Poll::Pending => registry.block_until_ready()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let latest = if !possibilities.is_empty() {
|
let latest = if !possibilities.is_empty() {
|
||||||
|
@ -338,17 +350,23 @@ fn upgrade_dependency(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(latest) = latest else {
|
let new_version = if let Some(precise) = precise {
|
||||||
|
Version::parse(precise)
|
||||||
|
.with_context(|| format!("invalid version format for precise version `{precise}`"))?
|
||||||
|
} else if let Some(latest) = latest {
|
||||||
|
latest.clone()
|
||||||
|
} else {
|
||||||
|
// Breaking (not precise) upgrade did not find a latest version
|
||||||
trace!("skipping dependency `{name}` without any published versions");
|
trace!("skipping dependency `{name}` without any published versions");
|
||||||
return Ok(dependency);
|
return Ok(dependency);
|
||||||
};
|
};
|
||||||
|
|
||||||
if current.matches(&latest) {
|
if current.matches(&new_version) {
|
||||||
trace!("skipping dependency `{name}` without a breaking update available");
|
trace!("skipping dependency `{name}` without a breaking update available");
|
||||||
return Ok(dependency);
|
return Ok(dependency);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some((new_req_string, _)) = upgrade_requirement(¤t.to_string(), latest)? else {
|
let Some((new_req_string, _)) = upgrade_requirement(¤t.to_string(), &new_version)? else {
|
||||||
trace!("skipping dependency `{name}` because the version requirement didn't change");
|
trace!("skipping dependency `{name}` because the version requirement didn't change");
|
||||||
return Ok(dependency);
|
return Ok(dependency);
|
||||||
};
|
};
|
||||||
|
@ -356,14 +374,36 @@ fn upgrade_dependency(
|
||||||
let upgrade_message = format!("{name} {current} -> {new_req_string}");
|
let upgrade_message = format!("{name} {current} -> {new_req_string}");
|
||||||
trace!(upgrade_message);
|
trace!(upgrade_message);
|
||||||
|
|
||||||
|
let old_version = semver::Version::new(
|
||||||
|
comparator.major,
|
||||||
|
comparator.minor.unwrap_or_default(),
|
||||||
|
comparator.patch.unwrap_or_default(),
|
||||||
|
);
|
||||||
|
let is_downgrade = new_version < old_version;
|
||||||
|
let status = if is_downgrade {
|
||||||
|
"Downgrading"
|
||||||
|
} else {
|
||||||
|
"Upgrading"
|
||||||
|
};
|
||||||
|
|
||||||
if upgrade_messages.insert(upgrade_message.clone()) {
|
if upgrade_messages.insert(upgrade_message.clone()) {
|
||||||
gctx.shell()
|
gctx.shell()
|
||||||
.status_with_color("Upgrading", &upgrade_message, &style::GOOD)?;
|
.status_with_color(status, &upgrade_message, &style::WARN)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
upgrades.insert((name.to_string(), dependency.source_id()), latest.clone());
|
upgrades.insert(
|
||||||
|
(name.to_string(), dependency.source_id()),
|
||||||
|
new_version.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let new_version_req = VersionReq::parse(&new_version.to_string())?;
|
||||||
|
|
||||||
|
let req = if precise.is_some() {
|
||||||
|
OptVersionReq::Precise(new_version, new_version_req)
|
||||||
|
} else {
|
||||||
|
OptVersionReq::Req(new_version_req)
|
||||||
|
};
|
||||||
|
|
||||||
let req = OptVersionReq::Req(VersionReq::parse(&latest.to_string())?);
|
|
||||||
let mut dep = dependency.clone();
|
let mut dep = dependency.clone();
|
||||||
dep.set_version_req(req);
|
dep.set_version_req(req);
|
||||||
Ok(dep)
|
Ok(dep)
|
||||||
|
|
|
@ -117,9 +117,9 @@ impl OptVersionReq {
|
||||||
/// and we're not sure if this part of the functionality should be implemented in semver or cargo.
|
/// and we're not sure if this part of the functionality should be implemented in semver or cargo.
|
||||||
pub fn matches_prerelease(&self, version: &Version) -> bool {
|
pub fn matches_prerelease(&self, version: &Version) -> bool {
|
||||||
if version.is_prerelease() {
|
if version.is_prerelease() {
|
||||||
let mut version = version.clone();
|
let mut version_cleaned = version.clone();
|
||||||
version.pre = semver::Prerelease::EMPTY;
|
version_cleaned.pre = semver::Prerelease::EMPTY;
|
||||||
return self.matches(&version);
|
return self.matches(&version) || self.matches(&version_cleaned);
|
||||||
}
|
}
|
||||||
self.matches(version)
|
self.matches(version)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use anyhow::bail;
|
||||||
|
|
||||||
use crate::CargoResult;
|
use crate::CargoResult;
|
||||||
|
|
||||||
/// Upgrade an existing requirement to a new version.
|
/// Upgrade an existing requirement to a new version.
|
||||||
|
@ -27,15 +29,8 @@ pub(crate) fn upgrade_requirement(
|
||||||
new_req_text.remove(0);
|
new_req_text.remove(0);
|
||||||
}
|
}
|
||||||
// Validate contract
|
// Validate contract
|
||||||
#[cfg(debug_assertions)]
|
if !new_req.matches(version) {
|
||||||
{
|
bail!("New requirement {new_req_text} is invalid, because it doesn't match {version}")
|
||||||
assert!(
|
|
||||||
new_req.matches(version),
|
|
||||||
"New req {} is invalid, because {} does not match {}",
|
|
||||||
new_req_text,
|
|
||||||
new_req,
|
|
||||||
version
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if new_req_text == req_text {
|
if new_req_text == req_text {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
@ -178,6 +178,7 @@ mod tree;
|
||||||
mod tree_graph_features;
|
mod tree_graph_features;
|
||||||
mod unit_graph;
|
mod unit_graph;
|
||||||
mod update;
|
mod update;
|
||||||
|
mod update_duplicated_with_precise_breaking_feature;
|
||||||
mod vendor;
|
mod vendor;
|
||||||
mod verify_project;
|
mod verify_project;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
|
@ -65,8 +65,8 @@ fn update_pre_release() {
|
||||||
p.cargo("update my-dependency --precise 0.1.2-pre.0 -Zunstable-options")
|
p.cargo("update my-dependency --precise 0.1.2-pre.0 -Zunstable-options")
|
||||||
.masquerade_as_nightly_cargo(&["precise-pre-release"])
|
.masquerade_as_nightly_cargo(&["precise-pre-release"])
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
|
[UPGRADING] my-dependency ^0.1.1 -> ^0.1.2-pre.0
|
||||||
[UPDATING] `dummy-registry` index
|
[UPDATING] `dummy-registry` index
|
||||||
[UPDATING] my-dependency v0.1.1 -> v0.1.2-pre.0
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
@ -98,8 +98,8 @@ fn update_pre_release_differ() {
|
||||||
p.cargo("update -p my-dependency --precise 0.1.2-pre.0 -Zunstable-options")
|
p.cargo("update -p my-dependency --precise 0.1.2-pre.0 -Zunstable-options")
|
||||||
.masquerade_as_nightly_cargo(&["precise-pre-release"])
|
.masquerade_as_nightly_cargo(&["precise-pre-release"])
|
||||||
.with_stderr_data(str![[r#"
|
.with_stderr_data(str![[r#"
|
||||||
|
[DOWNGRADING] my-dependency ^0.1.2 -> ^0.1.2-pre.0
|
||||||
[UPDATING] `dummy-registry` index
|
[UPDATING] `dummy-registry` index
|
||||||
[DOWNGRADING] my-dependency v0.1.2 -> v0.1.2-pre.0
|
|
||||||
|
|
||||||
"#]])
|
"#]])
|
||||||
.run();
|
.run();
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,703 @@
|
||||||
|
//! Duplicating tests for `cargo update --precise` with unstable-options
|
||||||
|
//! enabled. This will make sure we check backward compatibility when the
|
||||||
|
//! capability of making breaking changes has been implemented. When that
|
||||||
|
//! feature is stabilized, this file can be deleted.
|
||||||
|
|
||||||
|
use cargo_test_support::prelude::*;
|
||||||
|
use cargo_test_support::registry::Package;
|
||||||
|
use cargo_test_support::{basic_lib_manifest, git, project, str};
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn update_precise_downgrade() {
|
||||||
|
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 -Zunstable-options serde:0.2.1 --precise 0.2.0")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options serde:1.2 --precise 1.6.0")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options serde:1.2 --precise 1.9.0")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
// 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 -Zunstable-options serde --precise 0.0.1+first")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("update -Zunstable-options serde --precise 0.0.1+second")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options serde --precise 0.0.1+first")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options serde:0.2.1 --precise 0.2.2")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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_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 -Zunstable-options serde:0.2.1 --precise 0.2.2 --recursive")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.with_status(1)
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[ERROR] the argument '--precise <PRECISE>' cannot be used with '--recursive'
|
||||||
|
|
||||||
|
Usage: cargo[EXE] update -Z <FLAG> --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 -Zunstable-options serde --precise 0.2.0")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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"
|
||||||
|
}
|
||||||
|
"#]]
|
||||||
|
.json(),
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
p.cargo("update -Zunstable-options serde --precise 0.2.0")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.with_stderr_data(str![[r#"
|
||||||
|
[UPDATING] `dummy-registry` index
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 -Zunstable-options bar --precise 0.1")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options bar --precise 0.1.1+does-not-match")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options bar --precise 0.1.1")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options bar --precise 0.1.3+foo")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options bar --precise 0.1.3")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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_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] 2 packages to latest compatible versions
|
||||||
|
|
||||||
|
"#]])
|
||||||
|
.run();
|
||||||
|
|
||||||
|
assert!(p.read_lockfile().contains(&head_id));
|
||||||
|
|
||||||
|
p.cargo("update -Zunstable-options git --precise")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options git --precise")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options git --precise")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 -Zunstable-options git --precise")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 update_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 -Zunstable-options --precise 0.1.1 bar")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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 update_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 -Zunstable-options --precise 0.1.1 bar")
|
||||||
|
.masquerade_as_nightly_cargo(&["update-precise-breaking"])
|
||||||
|
.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\""));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user