Skip to content

Commit

Permalink
Auto merge of #8243 - ehuss:patch-unused-can-update, r=alexcrichton
Browse files Browse the repository at this point in the history
Fix `cargo update` with unused patch.

If you end up with an unused patch in `Cargo.lock`, then you try to update the patch to a version that does not match the original unused patch, and run `cargo update`, Cargo refuses to update it with the error "patch for `bar` in `https://github.com/rust-lang/crates.io-index` did not resolve to any crates".  At this point, Cargo seems to be permanently stuck with no way to update it (unless you manually edit `Cargo.lock`).

The solution here is to add the unused patches to the "to_avoid" list, so that `cargo update` is allowed to update them.

I am uncertain if this is the best way to fix it, but seems to match my intuition of how `cargo update` is implemented.
  • Loading branch information
bors committed May 15, 2020
2 parents 2fef2e5 + 501e580 commit 13bded9
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/cargo/ops/cargo_generate_lockfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use termcolor::Color::{self, Cyan, Green, Red};

use crate::core::registry::PackageRegistry;
use crate::core::resolver::ResolveOpts;
use crate::core::PackageId;
use crate::core::{PackageId, PackageIdSpec};
use crate::core::{Resolve, SourceId, Workspace};
use crate::ops;
use crate::util::config::Config;
Expand Down Expand Up @@ -79,6 +79,7 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes

if opts.to_update.is_empty() {
to_avoid.extend(previous_resolve.iter());
to_avoid.extend(previous_resolve.unused_patches());
} else {
let mut sources = Vec::new();
for name in opts.to_update.iter() {
Expand All @@ -102,6 +103,11 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
None => dep.source_id().with_precise(None),
});
}
if let Ok(unused_id) =
PackageIdSpec::query_str(name, previous_resolve.unused_patches().iter().cloned())
{
to_avoid.insert(unused_id);
}
}

registry.add_sources(sources)?;
Expand Down
76 changes: 76 additions & 0 deletions tests/testsuite/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,3 +1445,79 @@ fn canonicalize_a_bunch() {
p.cargo("build").with_stderr("[FINISHED] [..]").run();
p.cargo("build").with_stderr("[FINISHED] [..]").run();
}

#[cargo_test]
fn update_unused_new_version() {
// If there is an unused patch entry, and then you update the patch,
// make sure `cargo update` will be able to fix the lock file.
Package::new("bar", "0.1.5").publish();

// Start with a lock file to 0.1.5, and an "unused" patch because the
// version is too old.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "0.1.5"
[patch.crates-io]
bar = { path = "../bar" }
"#,
)
.file("src/lib.rs", "")
.build();

// Patch is too old.
let bar = project()
.at("bar")
.file("Cargo.toml", &basic_manifest("bar", "0.1.4"))
.file("src/lib.rs", "")
.build();

p.cargo("build")
.with_stderr_contains("[WARNING] Patch `bar v0.1.4 [..] was not used in the crate graph.")
.run();
// unused patch should be in the lock file
let lock = p.read_lockfile();
let toml: toml::Value = toml::from_str(&lock).unwrap();
assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1);
assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("bar"));
assert_eq!(
toml["patch"]["unused"][0]["version"].as_str(),
Some("0.1.4")
);

// Oh, OK, let's update to the latest version.
bar.change_file("Cargo.toml", &basic_manifest("bar", "0.1.6"));

// Create a backup so we can test it with different options.
fs::copy(p.root().join("Cargo.lock"), p.root().join("Cargo.lock.bak")).unwrap();

// Try with `-p`.
p.cargo("update -p bar")
.with_stderr(
"\
[UPDATING] `[..]/registry` index
[ADDING] bar v0.1.6 ([..]/bar)
[REMOVING] bar v0.1.5
",
)
.run();

// Try with bare `cargo update`.
fs::copy(p.root().join("Cargo.lock.bak"), p.root().join("Cargo.lock")).unwrap();
p.cargo("update")
.with_stderr(
"\
[UPDATING] `[..]/registry` index
[ADDING] bar v0.1.6 ([..]/bar)
[REMOVING] bar v0.1.5
",
)
.run();
}

0 comments on commit 13bded9

Please sign in to comment.