cargo/tests/testsuite/patch.rs

2661 lines
65 KiB
Rust
Raw Normal View History

2019-11-25 02:42:45 +00:00
//! Tests for `[patch]` table source replacement.
use cargo_test_support::git;
use cargo_test_support::paths;
use cargo_test_support::registry::{self, Package};
use cargo_test_support::{basic_manifest, project};
use std::fs;
#[cargo_test]
fn replace() {
Package::new("bar", "0.1.0").publish();
Package::new("baz", "0.1.0")
.file(
"src/lib.rs",
"extern crate bar; pub fn baz() { bar::bar(); }",
2018-12-08 11:19:47 +00:00
)
.dep("bar", "0.1.0")
.publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
baz = "0.1.0"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
"#,
2018-12-08 11:19:47 +00:00
)
.file(
2018-03-14 15:17:44 +00:00
"src/lib.rs",
"
extern crate bar;
extern crate baz;
pub fn bar() {
bar::bar();
baz::baz();
}
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] baz v0.1.0 ([..])
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] baz v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
2018-03-14 15:17:44 +00:00
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn from_config() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
"#,
)
.file(
".cargo/config.toml",
r#"
[patch.crates-io]
bar = { path = 'bar' }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..])
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
2021-03-08 21:53:29 +00:00
#[cargo_test]
fn from_config_relative() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
"#,
)
.file(
"../.cargo/config.toml",
r#"
[patch.crates-io]
bar = { path = 'foo/bar' }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
2021-03-08 21:53:29 +00:00
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..])
[CHECKING] foo v0.0.1 ([CWD])
2021-03-08 21:53:29 +00:00
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
2021-02-26 17:29:33 +00:00
#[cargo_test]
fn from_config_precedence() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = 'no-such-path' }
2021-02-26 17:29:33 +00:00
"#,
)
.file(
".cargo/config.toml",
r#"
[patch.crates-io]
bar = { path = 'bar' }
2021-02-26 17:29:33 +00:00
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
2021-02-26 17:29:33 +00:00
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..])
[CHECKING] foo v0.0.1 ([CWD])
2021-02-26 17:29:33 +00:00
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn nonexistent() {
Package::new("baz", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
"#,
2018-12-08 11:19:47 +00:00
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
2018-12-08 11:19:47 +00:00
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn patch_git() {
let bar = git::repo(&paths::root().join("override"))
2018-07-24 22:35:01 +00:00
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "")
.build();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = {{ git = '{}' }}
2020-09-27 00:59:58 +00:00
[patch.'{0}']
bar = {{ path = "bar" }}
"#,
bar.url()
2018-03-14 15:17:44 +00:00
),
2018-12-08 11:19:47 +00:00
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
2018-12-08 11:19:47 +00:00
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "pub fn bar() {}")
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2018-09-09 23:59:48 +00:00
[UPDATING] git repository `file://[..]`
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn patch_to_git() {
let bar = git::repo(&paths::root().join("override"))
2018-07-24 22:35:01 +00:00
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "pub fn bar() {}")
.build();
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = {{ git = '{}' }}
"#,
bar.url()
2018-03-14 15:17:44 +00:00
),
2018-12-08 11:19:47 +00:00
)
.file(
"src/lib.rs",
"extern crate bar; pub fn foo() { bar::bar(); }",
2018-12-08 11:19:47 +00:00
)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2018-09-09 23:59:48 +00:00
[UPDATING] git repository `file://[..]`
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.0 (file://[..])
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn unused() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0"))
.file("bar/src/lib.rs", "not rust code")
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-12-21 01:33:41 +00:00
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check")
2018-12-21 01:33:41 +00:00
.with_stderr(
"\
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-12-21 01:33:41 +00:00
[FINISHED] [..]
",
)
.run();
// unused patch should be in the lock file
let lock = p.read_lockfile();
let toml: toml::Table = 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"));
2018-03-14 15:17:44 +00:00
assert_eq!(
toml["patch"]["unused"][0]["version"].as_str(),
Some("0.2.0")
);
}
#[cargo_test]
fn unused_with_mismatch_source_being_patched() {
registry::alt_init();
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.alternative]
bar = { path = "bar" }
[patch.crates-io]
bar = { path = "baz" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0"))
.file("bar/src/lib.rs", "not rust code")
.file("baz/Cargo.toml", &basic_manifest("bar", "0.3.0"))
.file("baz/src/lib.rs", "not rust code")
.build();
p.cargo("check")
.with_stderr(
"\
[UPDATING] `dummy-registry` index
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
2022-08-03 01:22:50 +00:00
Perhaps you misspelled the source URL being patched.
Possible URLs for `[patch.<URL>]`:
crates-io
[WARNING] Patch `bar v0.3.0 ([CWD]/baz)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn prefer_patch_version() {
Package::new("bar", "0.1.2").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = "bar" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check")
.with_stderr(
"\
[FINISHED] [..]
",
)
.run();
// there should be no patch.unused in the toml file
let lock = p.read_lockfile();
let toml: toml::Table = toml::from_str(&lock).unwrap();
assert!(toml.get("patch").is_none());
}
#[cargo_test]
fn unused_from_config() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
"#,
)
.file(
".cargo/config.toml",
r#"
[patch.crates-io]
bar = { path = "bar" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0"))
.file("bar/src/lib.rs", "not rust code")
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check")
.with_stderr(
"\
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
[FINISHED] [..]
",
)
.run();
// unused patch should be in the lock file
let lock = p.read_lockfile();
let toml: toml::Table = 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.2.0")
);
}
#[cargo_test]
fn unused_git() {
Package::new("bar", "0.1.0").publish();
let foo = git::repo(&paths::root().join("override"))
2018-07-24 22:35:01 +00:00
.file("Cargo.toml", &basic_manifest("bar", "0.2.0"))
.file("src/lib.rs", "")
.build();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = {{ git = '{}' }}
"#,
2018-03-14 15:17:44 +00:00
foo.url()
),
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2018-09-09 23:59:48 +00:00
[UPDATING] git repository `file://[..]`
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-12-21 01:33:41 +00:00
[WARNING] Patch `bar v0.2.0 ([..])` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check")
2018-12-21 01:33:41 +00:00
.with_stderr(
"\
[WARNING] Patch `bar v0.2.0 ([..])` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-12-21 01:33:41 +00:00
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn add_patch() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
2018-03-14 15:17:44 +00:00
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = 'bar' }
"#,
);
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn add_patch_from_config() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
p.change_file(
".cargo/config.toml",
r#"
[patch.crates-io]
bar = { path = 'bar' }
"#,
);
p.cargo("check")
.with_stderr(
"\
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn add_ignored_patch() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.1.0 [..]
[CHECKING] bar v0.1.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
2018-03-14 15:17:44 +00:00
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = 'bar' }
"#,
);
p.cargo("check")
2018-12-21 01:33:41 +00:00
.with_stderr(
"\
[WARNING] Patch `bar v0.1.1 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-12-21 01:33:41 +00:00
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
)
.run();
p.cargo("check")
2018-12-21 01:33:41 +00:00
.with_stderr(
"\
[WARNING] Patch `bar v0.1.1 ([CWD]/bar)` was not used in the crate graph.
Check that [..]
with the [..]
what is [..]
version. [..]
2018-12-21 01:33:41 +00:00
[FINISHED] [..]",
)
.run();
p.cargo("update").run();
p.cargo("check")
2018-12-21 01:33:41 +00:00
.with_stderr(
"\
[CHECKING] bar v0.1.1 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
2018-12-21 01:33:41 +00:00
[FINISHED] dev [..]
",
)
.run();
}
#[cargo_test]
fn add_patch_with_features() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = 'bar', features = ["some_feature"] }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
"\
[WARNING] patch for `bar` uses the features mechanism. \
default-features and features will not take effect because the patch dependency does not support this mechanism
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check")
.with_stderr(
"\
[WARNING] patch for `bar` uses the features mechanism. \
default-features and features will not take effect because the patch dependency does not support this mechanism
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn add_patch_with_setting_default_features() {
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1.0"
[patch.crates-io]
bar = { path = 'bar', default-features = false, features = ["none_default_feature"] }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
"\
[WARNING] patch for `bar` uses the features mechanism. \
default-features and features will not take effect because the patch dependency does not support this mechanism
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.0 ([CWD]/bar)
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
p.cargo("check")
.with_stderr(
"\
[WARNING] patch for `bar` uses the features mechanism. \
default-features and features will not take effect because the patch dependency does not support this mechanism
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
2018-12-28 01:13:31 +00:00
fn no_warn_ws_patch() {
Package::new("c", "0.1.0").publish();
// Don't issue an unused patch warning when the patch isn't used when
// partially building a workspace.
let p = project()
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[workspace]
members = ["a", "b", "c"]
2018-12-28 01:13:31 +00:00
2020-09-27 00:59:58 +00:00
[patch.crates-io]
c = { path = "c" }
"#,
2018-12-28 01:13:31 +00:00
)
.file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
.file("a/src/lib.rs", "")
.file(
"b/Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "b"
version = "0.1.0"
[dependencies]
c = "0.1.0"
"#,
2018-12-28 01:13:31 +00:00
)
.file("b/src/lib.rs", "")
.file("c/Cargo.toml", &basic_manifest("c", "0.1.0"))
.file("c/src/lib.rs", "")
.build();
p.cargo("check -p a")
2018-12-28 01:13:31 +00:00
.with_stderr(
"\
[UPDATING] [..]
[CHECKING] a [..]
2018-12-28 01:13:31 +00:00
[FINISHED] [..]",
)
.run();
}
#[cargo_test]
fn new_minor() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.0"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = 'bar' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 [..]
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn transitive_new_minor() {
Package::new("baz", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = { path = 'bar' }
2020-09-27 00:59:58 +00:00
[patch.crates-io]
baz = { path = 'baz' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"bar/Cargo.toml",
2018-03-14 15:17:44 +00:00
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "bar"
version = "0.1.0"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
baz = '0.1.0'
"#,
2018-12-08 11:19:47 +00:00
)
.file("bar/src/lib.rs", r#""#)
2018-07-24 22:35:01 +00:00
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1"))
.file("baz/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] baz v0.1.1 [..]
[CHECKING] bar v0.1.0 [..]
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn new_major() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.2.0"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = 'bar' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.2.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.2.0 [..]
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
Package::new("bar", "0.2.0").publish();
p.cargo("update").run();
p.cargo("check")
.with_stderr("[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]")
.run();
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.2.0"
"#,
);
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2018-09-14 20:33:18 +00:00
[DOWNLOADING] crates ...
[DOWNLOADED] bar v0.2.0 [..]
[CHECKING] bar v0.2.0
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn transitive_new_major() {
Package::new("baz", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = { path = 'bar' }
2020-09-27 00:59:58 +00:00
[patch.crates-io]
baz = { path = 'baz' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-03-14 15:17:44 +00:00
.file(
"bar/Cargo.toml",
2018-03-14 15:17:44 +00:00
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "bar"
version = "0.1.0"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
baz = '0.2.0'
"#,
2018-12-08 11:19:47 +00:00
)
.file("bar/src/lib.rs", r#""#)
2018-07-24 22:35:01 +00:00
.file("baz/Cargo.toml", &basic_manifest("baz", "0.2.0"))
.file("baz/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] baz v0.2.0 [..]
[CHECKING] bar v0.1.0 [..]
[CHECKING] foo v0.0.1 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
)
.run();
}
#[cargo_test]
fn shared_by_transitive() {
Package::new("baz", "0.1.1").publish();
let baz = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("baz", "0.1.2"))
.file("src/lib.rs", "")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = " 0.1.0"
[dependencies]
bar = {{ path = "bar" }}
baz = "0.1"
[patch.crates-io]
baz = {{ git = "{}", version = "0.1" }}
"#,
baz.url(),
),
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[dependencies]
baz = "0.1.1"
"#,
)
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
[UPDATING] git repository `file://[..]`
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] baz v0.1.2 [..]
[CHECKING] bar v0.1.0 [..]
[CHECKING] foo v0.1.0 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn remove_patch() {
Package::new("foo", "0.1.0").publish();
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
foo = { path = 'foo' }
bar = { path = 'bar' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
2018-07-24 22:35:01 +00:00
.file("foo/Cargo.toml", &basic_manifest("foo", "0.1.0"))
.file("foo/src/lib.rs", r#""#)
.build();
// Generate a lock file where `foo` is unused
p.cargo("check").run();
let lock_file1 = p.read_lockfile();
// Remove `foo` and generate a new lock file form the old one
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = { path = 'bar' }
"#,
);
p.cargo("check").run();
let lock_file2 = p.read_lockfile();
// Remove the lock file and build from scratch
fs::remove_file(p.root().join("Cargo.lock")).unwrap();
p.cargo("check").run();
let lock_file3 = p.read_lockfile();
assert!(lock_file1.contains("foo"));
assert_eq!(lock_file2, lock_file3);
assert_ne!(lock_file1, lock_file2);
}
#[cargo_test]
fn non_crates_io() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[patch.some-other-source]
bar = { path = 'bar' }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_status(101)
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
error: failed to parse manifest at `[..]`
Caused by:
[patch] entry `some-other-source` should be a URL or registry name
Caused by:
invalid url `some-other-source`: relative URL without a base
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn replace_with_crates_io() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
authors = []
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = "0.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
.build();
p.cargo("check")
.with_status(101)
.with_stderr(
2018-03-14 15:17:44 +00:00
"\
[UPDATING] [..]
error: failed to resolve patches for `[..]`
Caused by:
patch for `bar` in `[..]` points to the same source, but patches must point \
to different sources
2018-03-14 15:17:44 +00:00
",
2018-12-08 11:19:47 +00:00
)
.run();
}
#[cargo_test]
fn patch_in_virtual() {
Package::new("bar", "0.1.0").publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[workspace]
members = ["foo"]
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", r#""#)
2018-03-14 15:17:44 +00:00
.file(
"foo/Cargo.toml",
2018-03-14 15:17:44 +00:00
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.1.0"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file("foo/src/lib.rs", r#""#)
.build();
p.cargo("check").run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
#[cargo_test]
fn patch_depends_on_another_patch() {
Package::new("bar", "0.1.0")
.file("src/lib.rs", "broken code")
.publish();
Package::new("baz", "0.1.0")
.dep("bar", "0.1")
.file("src/lib.rs", "broken code")
.publish();
let p = project()
2018-03-14 15:17:44 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
authors = []
version = "0.1.0"
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
baz = "0.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
baz = { path = "baz" }
"#,
2018-12-08 11:19:47 +00:00
)
.file("src/lib.rs", "")
2018-07-24 22:35:01 +00:00
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", r#""#)
2018-03-14 15:17:44 +00:00
.file(
"baz/Cargo.toml",
2018-03-14 15:17:44 +00:00
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "baz"
version = "0.1.1"
authors = []
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/lib.rs", r#""#)
.build();
p.cargo("check").run();
// Nothing should be rebuilt, no registry should be updated.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
2018-05-02 22:26:48 +00:00
#[cargo_test]
2018-05-02 22:26:48 +00:00
fn replace_prerelease() {
Package::new("baz", "1.1.0-pre.1").publish();
let p = project()
2018-05-02 22:26:48 +00:00
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[workspace]
members = ["bar"]
2018-05-02 22:26:48 +00:00
2020-09-27 00:59:58 +00:00
[patch.crates-io]
baz = { path = "./baz" }
"#,
2018-12-08 11:19:47 +00:00
)
.file(
"bar/Cargo.toml",
2018-05-02 22:26:48 +00:00
r#"
[package]
2020-09-27 00:59:58 +00:00
name = "bar"
version = "0.5.0"
authors = []
2018-05-02 22:26:48 +00:00
2020-09-27 00:59:58 +00:00
[dependencies]
baz = "1.1.0-pre.1"
"#,
2018-12-08 11:19:47 +00:00
)
.file(
"bar/src/main.rs",
"extern crate baz; fn main() { baz::baz() }",
2018-12-08 11:19:47 +00:00
)
.file(
"baz/Cargo.toml",
2018-05-02 22:26:48 +00:00
r#"
[package]
2020-09-27 00:59:58 +00:00
name = "baz"
version = "1.1.0-pre.1"
authors = []
[workspace]
"#,
2018-12-08 11:19:47 +00:00
)
.file("baz/src/lib.rs", "pub fn baz() {}")
2018-05-02 22:26:48 +00:00
.build();
p.cargo("check").run();
2018-05-02 22:26:48 +00:00
}
#[cargo_test]
fn patch_older() {
Package::new("baz", "1.0.2").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = { path = 'bar' }
baz = "=1.0.1"
[patch.crates-io]
baz = { path = "./baz" }
"#,
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.5.0"
authors = []
[dependencies]
baz = "1.0.0"
"#,
)
.file("bar/src/lib.rs", "")
.file(
"baz/Cargo.toml",
r#"
[package]
name = "baz"
version = "1.0.1"
authors = []
"#,
)
.file("baz/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
[UPDATING] [..]
[CHECKING] baz v1.0.1 [..]
[CHECKING] bar v0.5.0 [..]
[CHECKING] foo v0.1.0 [..]
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn cycle() {
Package::new("a", "1.0.0").publish();
Package::new("b", "1.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[workspace]
members = ["a", "b"]
[patch.crates-io]
a = {path="a"}
b = {path="b"}
"#,
)
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "1.0.0"
[dependencies]
b = "1.0"
"#,
)
.file("a/src/lib.rs", "")
.file(
"b/Cargo.toml",
r#"
[package]
name = "b"
version = "1.0.0"
[dependencies]
a = "1.0"
"#,
)
.file("b/src/lib.rs", "")
.build();
p.cargo("check")
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
[ERROR] cyclic package dependency: [..]
package `[..]`
... which satisfies dependency `[..]` of package `[..]`
... which satisfies dependency `[..]` of package `[..]`
",
)
.run();
}
#[cargo_test]
fn multipatch() {
Package::new("a", "1.0.0").publish();
Package::new("a", "2.0.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
a1 = { version = "1", package = "a" }
a2 = { version = "2", package = "a" }
[patch.crates-io]
b1 = { path = "a1", package = "a" }
b2 = { path = "a2", package = "a" }
"#,
)
.file("src/lib.rs", "pub fn foo() { a1::f1(); a2::f2(); }")
.file(
"a1/Cargo.toml",
r#"
[package]
name = "a"
version = "1.0.0"
"#,
)
.file("a1/src/lib.rs", "pub fn f1() {}")
.file(
"a2/Cargo.toml",
r#"
[package]
name = "a"
version = "2.0.0"
"#,
)
.file("a2/src/lib.rs", "pub fn f2() {}")
.build();
p.cargo("check").run();
}
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
#[cargo_test]
fn patch_same_version() {
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "")
.build();
cargo_test_support::registry::init();
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = {{ path = "bar" }}
bar2 = {{ git = '{}', package = 'bar' }}
"#,
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
bar.url(),
),
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
"#,
)
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
error: cannot have two `[patch]` entries which both resolve to `bar v0.1.0`
",
)
.run();
}
#[cargo_test]
fn two_semver_compatible() {
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("src/lib.rs", "")
.build();
cargo_test_support::registry::init();
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = {{ path = "bar" }}
bar2 = {{ git = '{}', package = 'bar' }}
"#,
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
bar.url(),
),
)
.file("src/lib.rs", "pub fn foo() { bar::foo() }")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.2"
"#,
)
.file("bar/src/lib.rs", "pub fn foo() {}")
.build();
// assert the build succeeds and doesn't panic anywhere, and then afterwards
// assert that the build succeeds again without updating anything or
// building anything else.
p.cargo("check").run();
p.cargo("check")
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
.with_stderr(
"\
warning: Patch `bar v0.1.1 [..]` was not used in the crate graph.
2022-08-03 01:22:50 +00:00
Perhaps you misspelled the source URL being patched.
Possible URLs for `[patch.<URL>]`:
[CWD]/bar
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
[FINISHED] [..]",
)
.run();
}
#[cargo_test]
fn multipatch_select_big() {
let bar = git::repo(&paths::root().join("override"))
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("src/lib.rs", "")
.build();
cargo_test_support::registry::init();
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.0.1"
[dependencies]
bar = "*"
[patch.crates-io]
bar = {{ path = "bar" }}
bar2 = {{ git = '{}', package = 'bar' }}
"#,
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
bar.url(),
),
)
.file("src/lib.rs", "pub fn foo() { bar::foo() }")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.2.0"
"#,
)
.file("bar/src/lib.rs", "pub fn foo() {}")
.build();
// assert the build succeeds, which is only possible if 0.2.0 is selected
// since 0.1.0 is missing the function we need. Afterwards assert that the
// build succeeds again without updating anything or building anything else.
p.cargo("check").run();
p.cargo("check")
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
.with_stderr(
"\
warning: Patch `bar v0.1.0 [..]` was not used in the crate graph.
2022-08-03 01:22:50 +00:00
Perhaps you misspelled the source URL being patched.
Possible URLs for `[patch.<URL>]`:
[CWD]/bar
Fixes around multiple `[patch]` per crate This commit fixes a few bugs in handling of `[patch]` where multiple version of the same crate name have been patched in. Two sub-issues were discovered when investigating #7264: * The first issue is that the source of the assertion, the logic in `lock`, revealed a fundamental flaw in the logic. The `lock` function serves the purpose of applying a lock file to a dependency candidate and ensure that it stays within locked versions of dependencies, if they're previously found. The logic here to handle `[patch]`, however, happened a bit too late and was a bit too zealous to simply lock a dependency by name instead of accounting for the version as well. The updated logic is to move the locking of dependencies here to during the normal iteration over the list of dependencies. Adjacent to `matches_id` we check `matches_ignoring_source`. If the latter returns `true` then we double-check that the previous dependency is still in `[patch]`, and then we let it through. This means that patches with multiple versions should be correctly handled where edges drawn with `[patch]` are preserved. * The second issue, after fixing this, was found where if the exact same version was listed in `[patch]` multiple times then we would continuously update the original source since one of the replacements gets lost along the way. This commit adds a first-class warning disallowing patches pointing to the exact same crate version, since we don't have a way to prioritize amongst them anyway. Closes #7264
2019-08-26 19:52:26 +00:00
[FINISHED] [..]",
)
.run();
}
#[cargo_test]
fn canonicalize_a_bunch() {
let base = git::repo(&paths::root().join("base"))
.file("Cargo.toml", &basic_manifest("base", "0.1.0"))
.file("src/lib.rs", "")
.build();
let intermediate = git::repo(&paths::root().join("intermediate"))
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "intermediate"
version = "0.1.0"
[dependencies]
# Note the lack of trailing slash
base = {{ git = '{}' }}
"#,
base.url(),
),
)
.file("src/lib.rs", "pub fn f() { base::f() }")
.build();
let newbase = git::repo(&paths::root().join("newbase"))
.file("Cargo.toml", &basic_manifest("base", "0.1.0"))
.file("src/lib.rs", "pub fn f() {}")
.build();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.0.1"
[dependencies]
# Note the trailing slashes
base = {{ git = '{base}/' }}
intermediate = {{ git = '{intermediate}/' }}
[patch.'{base}'] # Note the lack of trailing slash
base = {{ git = '{newbase}' }}
"#,
base = base.url(),
intermediate = intermediate.url(),
newbase = newbase.url(),
),
)
.file("src/lib.rs", "pub fn a() { base::f(); intermediate::f() }")
.build();
// Once to make sure it actually works
p.cargo("check").run();
// Then a few more times for good measure to ensure no weird warnings about
// `[patch]` are printed.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
p.cargo("check").with_stderr("[FINISHED] [..]").run();
}
2020-05-14 22:56:01 +00:00
#[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("check")
2020-05-14 22:56:01 +00:00
.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::Table = toml::from_str(&lock).unwrap();
2020-05-14 22:56:01 +00:00
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 to build again, this should automatically update Cargo.lock.
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.6 ([..]/bar)
[CHECKING] foo v0.0.1 ([..]/foo)
[FINISHED] [..]
",
)
.run();
// This should not update any registry.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
assert!(!p.read_lockfile().contains("unused"));
// Restore the lock file, and see if `update` will work, too.
fs::copy(p.root().join("Cargo.lock.bak"), p.root().join("Cargo.lock")).unwrap();
// Try `update -p`.
2020-05-14 22:56:01 +00:00
p.cargo("update -p bar")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2020-05-14 22:56:01 +00:00
[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(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
2020-05-14 22:56:01 +00:00
[ADDING] bar v0.1.6 ([..]/bar)
[REMOVING] bar v0.1.5
",
)
.run();
}
#[cargo_test]
fn too_many_matches() {
// The patch locations has multiple versions that match.
registry::alt_init();
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.1.0").alternative(true).publish();
Package::new("bar", "0.1.1").alternative(true).publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = { version = "0.1", registry = "alternative" }
"#,
)
.file("src/lib.rs", "")
.build();
// Picks 0.1.1, the most recent version.
p.cargo("check")
.with_status(101)
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `alternative` index
[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index`
Caused by:
patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve
Caused by:
2021-06-27 19:18:36 +00:00
patch for `bar` in `registry `alternative`` resolved to more than one candidate
Found versions: 0.1.0, 0.1.1
Update the patch definition to select only one package.
For example, add an `=` version requirement to the patch definition, such as `version = \"=0.1.1\"`.
",
)
.run();
}
#[cargo_test]
fn no_matches() {
// A patch to a location that does not contain the named package.
let p = project()
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.1.0"
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("abc", "0.1.0"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_status(101)
.with_stderr(
"\
error: failed to resolve patches for `https://github.com/rust-lang/crates.io-index`
Caused by:
patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve
Caused by:
2020-05-20 16:25:53 +00:00
The patch location `[..]/foo/bar` does not appear to contain any packages matching the name `bar`.
",
)
.run();
}
#[cargo_test]
fn mismatched_version() {
// A patch to a location that has an old version.
let p = project()
.file(
"Cargo.toml",
r#"
2020-09-27 00:59:58 +00:00
[package]
name = "foo"
version = "0.1.0"
2020-09-27 00:59:58 +00:00
[dependencies]
bar = "0.1.1"
2020-09-27 00:59:58 +00:00
[patch.crates-io]
bar = { path = "bar", version = "0.1.1" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_status(101)
.with_stderr(
"\
[ERROR] failed to resolve patches for `https://github.com/rust-lang/crates.io-index`
Caused by:
patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve
Caused by:
2020-05-20 16:25:53 +00:00
The patch location `[..]/foo/bar` contains a `bar` package with version `0.1.0`, \
but the patch definition requires `^0.1.1`.
Check that the version in the patch location is what you expect, \
and update the patch definition to match.
",
)
.run();
}
#[cargo_test]
fn patch_walks_backwards() {
// Starting with a locked patch, change the patch so it points to an older version.
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = {path="bar"}
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
// Somehow the user changes the version backwards.
p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"));
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.0 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn patch_walks_backwards_restricted() {
// This is the same as `patch_walks_backwards`, but the patch contains a
// `version` qualifier. This is unusual, just checking a strange edge case.
Package::new("bar", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = {path="bar", version="0.1.1"}
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
// Somehow the user changes the version backwards.
p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"));
p.cargo("check")
.with_status(101)
.with_stderr(
"\
error: failed to resolve patches for `https://github.com/rust-lang/crates.io-index`
Caused by:
patch for `bar` in `https://github.com/rust-lang/crates.io-index` failed to resolve
Caused by:
2020-05-20 16:25:53 +00:00
The patch location `[..]/foo/bar` contains a `bar` package with version `0.1.0`, but the patch definition requires `^0.1.1`.
Check that the version in the patch location is what you expect, and update the patch definition to match.
",
)
.run();
}
#[cargo_test]
fn patched_dep_new_version() {
// What happens when a patch is locked, and then one of the patched
// dependencies needs to be updated. In this case, the baz requirement
// gets updated from 0.1.0 to 0.1.1.
Package::new("bar", "0.1.0").dep("baz", "0.1.0").publish();
Package::new("baz", "0.1.0").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = {path="bar"}
"#,
)
.file("src/lib.rs", "")
.file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[dependencies]
baz = "0.1"
"#,
)
.file("bar/src/lib.rs", "")
.build();
// Lock everything.
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
[DOWNLOADED] baz v0.1.0 [..]
[CHECKING] baz v0.1.0
[CHECKING] bar v0.1.0 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
Package::new("baz", "0.1.1").publish();
// Just the presence of the new version should not have changed anything.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
// Modify the patch so it requires the new version.
p.change_file(
"bar/Cargo.toml",
r#"
[package]
name = "bar"
version = "0.1.0"
[dependencies]
baz = "0.1.1"
"#,
);
// Should unlock and update cleanly.
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
2021-06-27 19:18:36 +00:00
[DOWNLOADED] baz v0.1.1 (registry `dummy-registry`)
[CHECKING] baz v0.1.1
[CHECKING] bar v0.1.0 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn patch_update_doesnt_update_other_sources() {
// Very extreme edge case, make sure a patch update doesn't update other
// sources.
registry::alt_init();
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.1.0").alternative(true).publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
bar_alt = { version = "0.1", registry = "alternative", package = "bar" }
[patch.crates-io]
bar = { path = "bar" }
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr_unordered(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[UPDATING] `alternative` index
[DOWNLOADING] crates ...
2021-06-27 19:18:36 +00:00
[DOWNLOADED] bar v0.1.0 (registry `alternative`)
[CHECKING] bar v0.1.0 (registry `alternative`)
[CHECKING] bar v0.1.0 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
// Publish new versions in both sources.
Package::new("bar", "0.1.1").publish();
Package::new("bar", "0.1.1").alternative(true).publish();
// Since it is locked, nothing should change.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
// Require new version on crates.io.
p.change_file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"));
// This should not update bar_alt.
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `dummy-registry` index
[CHECKING] bar v0.1.1 ([..]/foo/bar)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn can_update_with_alt_reg() {
// A patch to an alt reg can update.
registry::alt_init();
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.1.0").alternative(true).publish();
Package::new("bar", "0.1.1").alternative(true).publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = { version = "=0.1.1", registry = "alternative" }
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `alternative` index
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
2021-06-27 19:18:36 +00:00
[DOWNLOADED] bar v0.1.1 (registry `alternative`)
[CHECKING] bar v0.1.1 (registry `alternative`)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
Package::new("bar", "0.1.2").alternative(true).publish();
// Should remain locked.
p.cargo("check").with_stderr("[FINISHED] [..]").run();
// This does nothing, due to `=` requirement.
p.cargo("update -p bar")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `alternative` index
[UPDATING] `dummy-registry` index
",
)
.run();
// Bump to 0.1.2.
p.change_file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1"
[patch.crates-io]
bar = { version = "=0.1.2", registry = "alternative" }
"#,
);
p.cargo("check")
.with_stderr(
"\
2021-06-27 19:18:36 +00:00
[UPDATING] `alternative` index
[UPDATING] `dummy-registry` index
[DOWNLOADING] crates ...
2021-06-27 19:18:36 +00:00
[DOWNLOADED] bar v0.1.2 (registry `alternative`)
[CHECKING] bar v0.1.2 (registry `alternative`)
[CHECKING] foo v0.1.0 ([..]/foo)
[FINISHED] [..]
",
)
.run();
}
#[cargo_test]
fn gitoxide_clones_shallow_old_git_patch() {
perform_old_git_patch(true)
}
fn perform_old_git_patch(shallow: bool) {
// Example where an old lockfile with an explicit branch="master" in Cargo.toml.
Package::new("bar", "1.0.0").publish();
let (bar, bar_repo) = git::new_repo("bar", |p| {
p.file("Cargo.toml", &basic_manifest("bar", "1.0.0"))
.file("src/lib.rs", "")
});
let bar_oid = bar_repo.head().unwrap().target().unwrap();
let p = project()
.file(
"Cargo.toml",
&format!(
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "1.0"
[patch.crates-io]
bar = {{ git = "{}", branch = "master" }}
"#,
bar.url()
),
)
.file(
"Cargo.lock",
&format!(
r#"
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "bar"
version = "1.0.0"
source = "git+{}#{}"
[[package]]
name = "foo"
version = "0.1.0"
dependencies = [
"bar",
]
"#,
bar.url(),
bar_oid
),
)
.file("src/lib.rs", "")
.build();
bar.change_file("Cargo.toml", &basic_manifest("bar", "2.0.0"));
git::add(&bar_repo);
git::commit(&bar_repo);
// This *should* keep the old lock.
let mut cargo = p.cargo("tree");
if shallow {
cargo
.arg("-Zgitoxide=fetch,shallow-deps")
.masquerade_as_nightly_cargo(&["unstable features must be available for -Z gitoxide"]);
}
cargo
// .env("CARGO_LOG", "trace")
.with_stderr(
"\
[UPDATING] [..]
",
)
// .with_status(1)
.with_stdout(format!(
"\
foo v0.1.0 [..]
bar v1.0.0 (file:///[..]branch=master#{})
",
&bar_oid.to_string()[..8]
))
.run();
}
#[cargo_test]
fn old_git_patch() {
perform_old_git_patch(false)
}
// From https://github.com/rust-lang/cargo/issues/7463
#[cargo_test]
fn patch_eq_conflict_panic() {
Package::new("bar", "0.1.0").publish();
Package::new("bar", "0.1.1").publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "=0.1.0"
[dev-dependencies]
bar = "=0.1.1"
[patch.crates-io]
bar = {path="bar"}
"#,
)
.file("src/lib.rs", "")
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
.file("bar/src/lib.rs", "")
.build();
p.cargo("generate-lockfile")
.with_status(101)
.with_stderr(
r#"[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for `bar`.
... required by package `foo v0.1.0 ([..])`
versions that meet the requirements `=0.1.1` are: 0.1.1
all possible versions conflict with previously selected packages.
previously selected package `bar v0.1.0`
... which satisfies dependency `bar = "=0.1.0"` of package `foo v0.1.0 ([..])`
failed to select a version for `bar` which could resolve this conflict
"#,
)
.run();
}
// From https://github.com/rust-lang/cargo/issues/11336
#[cargo_test]
fn mismatched_version2() {
Package::new("qux", "0.1.0-beta.1").publish();
Package::new("qux", "0.1.0-beta.2").publish();
Package::new("bar", "0.1.0")
.dep("qux", "=0.1.0-beta.1")
.publish();
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
[dependencies]
bar = "0.1.0"
qux = "0.1.0-beta.2"
[patch.crates-io]
qux = { path = "qux" }
"#,
)
.file("src/lib.rs", "")
.file(
"qux/Cargo.toml",
r#"
[package]
name = "qux"
version = "0.1.0-beta.1"
"#,
)
.file("qux/src/lib.rs", "")
.build();
p.cargo("generate-lockfile")
.with_status(101)
.with_stderr(
r#"[UPDATING] `dummy-registry` index
[ERROR] failed to select a version for `qux`.
... required by package `bar v0.1.0`
... which satisfies dependency `bar = "^0.1.0"` of package `foo v0.1.0 ([..])`
versions that meet the requirements `=0.1.0-beta.1` are: 0.1.0-beta.1
all possible versions conflict with previously selected packages.
previously selected package `qux v0.1.0-beta.2`
... which satisfies dependency `qux = "^0.1.0-beta.2"` of package `foo v0.1.0 ([..])`
failed to select a version for `qux` which could resolve this conflict"#,
)
.run();
}