mirror of
https://github.com/rust-lang/cargo
synced 2024-10-31 07:46:57 +00:00
2788 lines
68 KiB
Rust
2788 lines
68 KiB
Rust
//! 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(); }",
|
|
)
|
|
.dep("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"
|
|
baz = "0.1.0"
|
|
|
|
[patch.crates-io]
|
|
bar = { path = "bar" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
"
|
|
extern crate bar;
|
|
extern crate baz;
|
|
pub fn bar() {
|
|
bar::bar();
|
|
baz::baz();
|
|
}
|
|
",
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[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 [..]
|
|
",
|
|
)
|
|
.run();
|
|
|
|
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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.1.1 ([..])
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[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")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.1.1 ([..])
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[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' }
|
|
"#,
|
|
)
|
|
.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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.1.1 ([..])
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn nonexistent() {
|
|
Package::new("baz", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1.0"
|
|
|
|
[patch.crates-io]
|
|
bar = { path = "bar" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
"extern crate bar; pub fn foo() { bar::bar(); }",
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[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("[FINISHED] [..]").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn patch_git() {
|
|
let bar = git::repo(&paths::root().join("override"))
|
|
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = {{ git = '{}' }}
|
|
|
|
[patch.'{0}']
|
|
bar = {{ path = "bar" }}
|
|
"#,
|
|
bar.url()
|
|
),
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
"extern crate bar; pub fn foo() { bar::bar(); }",
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", "pub fn bar() {}")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] git repository `file://[..]`
|
|
[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 patch_to_git() {
|
|
let bar = git::repo(&paths::root().join("override"))
|
|
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("src/lib.rs", "pub fn bar() {}")
|
|
.build();
|
|
|
|
Package::new("bar", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
|
|
[patch.crates-io]
|
|
bar = {{ git = '{}' }}
|
|
"#,
|
|
bar.url()
|
|
),
|
|
)
|
|
.file(
|
|
"src/lib.rs",
|
|
"extern crate bar; pub fn foo() { bar::bar(); }",
|
|
)
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] git repository `file://[..]`
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.1.0 (file://[..])
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
p.cargo("check").with_stderr("[FINISHED] [..]").run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn unused() {
|
|
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" }
|
|
"#,
|
|
)
|
|
.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(
|
|
"\
|
|
[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_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.
|
|
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(
|
|
"\
|
|
[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(
|
|
"\
|
|
[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"))
|
|
.file("Cargo.toml", &basic_manifest("bar", "0.2.0"))
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
|
|
[patch.crates-io]
|
|
bar = {{ git = '{}' }}
|
|
"#,
|
|
foo.url()
|
|
),
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] git repository `file://[..]`
|
|
[UPDATING] `dummy-registry` index
|
|
[WARNING] Patch `bar v0.2.0 ([..])` 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 ([..])` was not used in the crate graph.
|
|
Check that [..]
|
|
with the [..]
|
|
what is [..]
|
|
version. [..]
|
|
[FINISHED] [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn add_patch() {
|
|
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(
|
|
"\
|
|
[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.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(
|
|
"\
|
|
[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_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(
|
|
"\
|
|
[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()
|
|
.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.1"))
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[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.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(
|
|
"\
|
|
[WARNING] Patch `bar v0.1.1 ([CWD]/bar)` was not used in the crate graph.
|
|
Check that [..]
|
|
with the [..]
|
|
what is [..]
|
|
version. [..]
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]",
|
|
)
|
|
.run();
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[WARNING] Patch `bar v0.1.1 ([CWD]/bar)` was not used in the crate graph.
|
|
Check that [..]
|
|
with the [..]
|
|
what is [..]
|
|
version. [..]
|
|
[FINISHED] [..]",
|
|
)
|
|
.run();
|
|
|
|
p.cargo("update").run();
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[CHECKING] bar v0.1.1 ([CWD]/bar)
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[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
|
|
[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
|
|
[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 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#"
|
|
[workspace]
|
|
members = ["a", "b", "c"]
|
|
|
|
[patch.crates-io]
|
|
c = { path = "c" }
|
|
"#,
|
|
)
|
|
.file("a/Cargo.toml", &basic_manifest("a", "0.1.0"))
|
|
.file("a/src/lib.rs", "")
|
|
.file(
|
|
"b/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "b"
|
|
version = "0.1.0"
|
|
[dependencies]
|
|
c = "0.1.0"
|
|
"#,
|
|
)
|
|
.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")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] [..]
|
|
[CHECKING] a [..]
|
|
[FINISHED] [..]",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn new_minor() {
|
|
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' }
|
|
"#,
|
|
)
|
|
.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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.1.1 [..]
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn transitive_new_minor() {
|
|
Package::new("baz", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = 'bar' }
|
|
|
|
[patch.crates-io]
|
|
baz = { path = 'baz' }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = '0.1.0'
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.file("baz/Cargo.toml", &basic_manifest("baz", "0.1.1"))
|
|
.file("baz/src/lib.rs", r#""#)
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[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 [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn new_major() {
|
|
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.2.0"
|
|
|
|
[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", r#""#)
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[CHECKING] bar v0.2.0 [..]
|
|
[CHECKING] foo v0.0.1 ([CWD])
|
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
|
",
|
|
)
|
|
.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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[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 [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn transitive_new_major() {
|
|
Package::new("baz", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = { path = 'bar' }
|
|
|
|
[patch.crates-io]
|
|
baz = { path = 'baz' }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.1.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = '0.2.0'
|
|
"#,
|
|
)
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.file("baz/Cargo.toml", &basic_manifest("baz", "0.2.0"))
|
|
.file("baz/src/lib.rs", r#""#)
|
|
.build();
|
|
|
|
p.cargo("check")
|
|
.with_stderr(
|
|
"\
|
|
[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://[..]`
|
|
[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 [..]
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn remove_patch() {
|
|
Package::new("foo", "0.1.0").publish();
|
|
Package::new("bar", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
|
|
[patch.crates-io]
|
|
foo = { path = 'foo' }
|
|
bar = { path = 'bar' }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.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()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[patch.some-other-source]
|
|
bar = { path = 'bar' }
|
|
"#,
|
|
)
|
|
.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_status(101)
|
|
.with_stderr(
|
|
"\
|
|
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
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn replace_with_crates_io() {
|
|
Package::new("bar", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
authors = []
|
|
|
|
[patch.crates-io]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.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_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[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
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn patch_in_virtual() {
|
|
Package::new("bar", "0.1.0").publish();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["foo"]
|
|
|
|
[patch.crates-io]
|
|
bar = { path = "bar" }
|
|
"#,
|
|
)
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.0"))
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.file(
|
|
"foo/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.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()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
authors = []
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
baz = "0.1"
|
|
|
|
[patch.crates-io]
|
|
bar = { path = "bar" }
|
|
baz = { path = "baz" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
|
|
.file("bar/src/lib.rs", r#""#)
|
|
.file(
|
|
"baz/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "0.1.1"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
bar = "0.1"
|
|
"#,
|
|
)
|
|
.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();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn replace_prerelease() {
|
|
Package::new("baz", "1.1.0-pre.1").publish();
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[workspace]
|
|
members = ["bar"]
|
|
|
|
[patch.crates-io]
|
|
baz = { path = "./baz" }
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "bar"
|
|
version = "0.5.0"
|
|
authors = []
|
|
|
|
[dependencies]
|
|
baz = "1.1.0-pre.1"
|
|
"#,
|
|
)
|
|
.file(
|
|
"bar/src/main.rs",
|
|
"extern crate baz; fn main() { baz::baz() }",
|
|
)
|
|
.file(
|
|
"baz/Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "baz"
|
|
version = "1.1.0-pre.1"
|
|
authors = []
|
|
[workspace]
|
|
"#,
|
|
)
|
|
.file("baz/src/lib.rs", "pub fn baz() {}")
|
|
.build();
|
|
|
|
p.cargo("check").run();
|
|
}
|
|
|
|
#[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();
|
|
}
|
|
|
|
#[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();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
[dependencies]
|
|
bar = "0.1"
|
|
[patch.crates-io]
|
|
bar = {{ path = "bar" }}
|
|
bar2 = {{ git = '{}', package = 'bar' }}
|
|
"#,
|
|
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")
|
|
.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();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
[dependencies]
|
|
bar = "0.1"
|
|
[patch.crates-io]
|
|
bar = {{ path = "bar" }}
|
|
bar2 = {{ git = '{}', package = 'bar' }}
|
|
"#,
|
|
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")
|
|
.with_stderr(
|
|
"\
|
|
warning: Patch `bar v0.1.1 [..]` was not used in the crate graph.
|
|
Perhaps you misspelled the source URL being patched.
|
|
Possible URLs for `[patch.<URL>]`:
|
|
[CWD]/bar
|
|
[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();
|
|
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
&format!(
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.0.1"
|
|
[dependencies]
|
|
bar = "*"
|
|
[patch.crates-io]
|
|
bar = {{ path = "bar" }}
|
|
bar2 = {{ git = '{}', package = 'bar' }}
|
|
"#,
|
|
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")
|
|
.with_stderr(
|
|
"\
|
|
warning: Patch `bar v0.1.0 [..]` was not used in the crate graph.
|
|
Perhaps you misspelled the source URL being patched.
|
|
Possible URLs for `[patch.<URL>]`:
|
|
[CWD]/bar
|
|
[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();
|
|
}
|
|
|
|
#[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")
|
|
.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();
|
|
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(
|
|
"\
|
|
[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 <pkg>`.
|
|
p.cargo("update bar")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `dummy-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] `dummy-registry` index
|
|
[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(
|
|
"\
|
|
[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:
|
|
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#"
|
|
[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("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:
|
|
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#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
bar = "0.1.1"
|
|
|
|
[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:
|
|
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(
|
|
"\
|
|
[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(
|
|
"\
|
|
[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(
|
|
"\
|
|
[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:
|
|
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(
|
|
"\
|
|
[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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[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(
|
|
"\
|
|
[UPDATING] `dummy-registry` index
|
|
[UPDATING] `alternative` index
|
|
[DOWNLOADING] crates ...
|
|
[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(
|
|
"\
|
|
[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(
|
|
"\
|
|
[UPDATING] `alternative` index
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[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 bar")
|
|
.with_stderr(
|
|
"\
|
|
[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(
|
|
"\
|
|
[UPDATING] `alternative` index
|
|
[UPDATING] `dummy-registry` index
|
|
[DOWNLOADING] crates ...
|
|
[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")
|
|
.arg("-Zgit=shallow-deps")
|
|
.masquerade_as_nightly_cargo(&[
|
|
"unstable features must be available for -Z gitoxide and -Z git",
|
|
]);
|
|
}
|
|
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();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn mismatched_version_with_prerelease() {
|
|
Package::new("prerelease-deps", "0.0.1").publish();
|
|
// A patch to a location that has an prerelease version
|
|
let p = project()
|
|
.file(
|
|
"Cargo.toml",
|
|
r#"
|
|
[package]
|
|
name = "foo"
|
|
version = "0.1.0"
|
|
|
|
[dependencies]
|
|
prerelease-deps = "0.1.0"
|
|
|
|
[patch.crates-io]
|
|
prerelease-deps = { path = "./prerelease-deps" }
|
|
"#,
|
|
)
|
|
.file("src/lib.rs", "")
|
|
.file(
|
|
"prerelease-deps/Cargo.toml",
|
|
&basic_manifest("prerelease-deps", "0.1.1-pre1"),
|
|
)
|
|
.file("prerelease-deps/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 the requirement `prerelease-deps = "^0.1.0"`
|
|
candidate versions found which didn't match: 0.1.1-pre1, 0.0.1
|
|
location searched: `dummy-registry` index (which is replacing registry `crates-io`)
|
|
required by package `foo v0.1.0 [..]`
|
|
if you are looking for the prerelease package it needs to be specified explicitly
|
|
prerelease-deps = { version = "0.1.1-pre1" }
|
|
perhaps a crate was updated and forgotten to be re-vendored?"#,
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn from_config_empty() {
|
|
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.'']
|
|
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_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] [patch] entry `` should be a URL or registry name
|
|
|
|
Caused by:
|
|
invalid url ``: relative URL without a base
|
|
",
|
|
)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn from_manifest_empty() {
|
|
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.'']
|
|
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_status(101)
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] failed to parse manifest at `[CWD]/Cargo.toml`
|
|
|
|
Caused by:
|
|
[patch] entry `` should be a URL or registry name
|
|
|
|
Caused by:
|
|
invalid url ``: relative URL without a base
|
|
",
|
|
)
|
|
.run();
|
|
}
|