mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Support [patch] in .cargo/config files
This patch adds support for `[patch]` sections in `.cargo/config.toml` files. Patches from config files defer to `[patch]` in `Cargo.toml` if both provide a patch for the same crate. The current implementation merge config patches into the workspace manifest patches. It's unclear if that's the right long-term plan, or whether these patches should be stored separately (though likely still in the manifest). Regardless, they _should_ likely continue to be parsed when the manifest is parsed so that errors and such occur in the same place regardless of where a patch is specified. Fixes #5539.
This commit is contained in:
parent
572e201536
commit
8178f22ee9
@ -551,6 +551,7 @@ pub struct CliUnstable {
|
|||||||
pub extra_link_arg: bool,
|
pub extra_link_arg: bool,
|
||||||
pub credential_process: bool,
|
pub credential_process: bool,
|
||||||
pub configurable_env: bool,
|
pub configurable_env: bool,
|
||||||
|
pub patch_in_config: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \
|
const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \
|
||||||
@ -707,6 +708,7 @@ impl CliUnstable {
|
|||||||
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
|
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
|
||||||
"jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?,
|
"jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?,
|
||||||
"configurable-env" => self.configurable_env = parse_empty(k, v)?,
|
"configurable-env" => self.configurable_env = parse_empty(k, v)?,
|
||||||
|
"patch-in-config" => self.patch_in_config = parse_empty(k, v)?,
|
||||||
"features" => {
|
"features" => {
|
||||||
// For now this is still allowed (there are still some
|
// For now this is still allowed (there are still some
|
||||||
// unstable options like "compare"). This should be removed at
|
// unstable options like "compare"). This should be removed at
|
||||||
|
@ -1531,9 +1531,12 @@ impl TomlManifest {
|
|||||||
Ok(replace)
|
Ok(replace)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn patch(&self, cx: &mut Context<'_, '_>) -> CargoResult<HashMap<Url, Vec<Dependency>>> {
|
fn patch_(
|
||||||
|
table: Option<&BTreeMap<String, BTreeMap<String, TomlDependency>>>,
|
||||||
|
cx: &mut Context<'_, '_>,
|
||||||
|
) -> CargoResult<HashMap<Url, Vec<Dependency>>> {
|
||||||
let mut patch = HashMap::new();
|
let mut patch = HashMap::new();
|
||||||
for (url, deps) in self.patch.iter().flatten() {
|
for (url, deps) in table.into_iter().flatten() {
|
||||||
let url = match &url[..] {
|
let url = match &url[..] {
|
||||||
CRATES_IO_REGISTRY => CRATES_IO_INDEX.parse().unwrap(),
|
CRATES_IO_REGISTRY => CRATES_IO_INDEX.parse().unwrap(),
|
||||||
_ => cx
|
_ => cx
|
||||||
@ -1554,6 +1557,25 @@ impl TomlManifest {
|
|||||||
Ok(patch)
|
Ok(patch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn patch(&self, cx: &mut Context<'_, '_>) -> CargoResult<HashMap<Url, Vec<Dependency>>> {
|
||||||
|
let from_manifest = Self::patch_(self.patch.as_ref(), cx)?;
|
||||||
|
|
||||||
|
let config_patch: Option<BTreeMap<String, BTreeMap<String, TomlDependency>>> =
|
||||||
|
cx.config.get("patch")?;
|
||||||
|
|
||||||
|
if config_patch.is_some() && !cx.config.cli_unstable().patch_in_config {
|
||||||
|
cx.warnings.push("`[patch]` in .cargo/config.toml ignored, the -Zpatch-in-config command-line flag is required".to_owned());
|
||||||
|
return Ok(from_manifest);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut from_config = Self::patch_(config_patch.as_ref(), cx)?;
|
||||||
|
if from_config.is_empty() {
|
||||||
|
return Ok(from_manifest);
|
||||||
|
}
|
||||||
|
from_config.extend(from_manifest);
|
||||||
|
Ok(from_config)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the path to the build script if one exists for this crate.
|
/// Returns the path to the build script if one exists for this crate.
|
||||||
fn maybe_custom_build(
|
fn maybe_custom_build(
|
||||||
&self,
|
&self,
|
||||||
|
@ -66,6 +66,91 @@ fn replace() {
|
|||||||
p.cargo("build").with_stderr("[FINISHED] [..]").run();
|
p.cargo("build").with_stderr("[FINISHED] [..]").run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cargo_test]
|
||||||
|
fn from_config_without_z() {
|
||||||
|
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("build")
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[WARNING] `[patch]` in .cargo/config.toml ignored, the -Zpatch-in-config command-line flag is required
|
||||||
|
[UPDATING] `[ROOT][..]` index
|
||||||
|
[DOWNLOADING] crates ...
|
||||||
|
[DOWNLOADED] bar v0.1.0 ([..])
|
||||||
|
[COMPILING] bar v0.1.0
|
||||||
|
[COMPILING] foo v0.0.1 ([CWD])
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.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("build -Zpatch-in-config")
|
||||||
|
.masquerade_as_nightly_cargo()
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[UPDATING] `[ROOT][..]` index
|
||||||
|
[COMPILING] bar v0.1.1 ([..])
|
||||||
|
[COMPILING] foo v0.0.1 ([CWD])
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn nonexistent() {
|
fn nonexistent() {
|
||||||
Package::new("baz", "0.1.0").publish();
|
Package::new("baz", "0.1.0").publish();
|
||||||
@ -268,6 +353,78 @@ fn unused() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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("build -Zpatch-in-config")
|
||||||
|
.masquerade_as_nightly_cargo()
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[UPDATING] `[ROOT][..]` index
|
||||||
|
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[DOWNLOADING] crates ...
|
||||||
|
[DOWNLOADED] bar v0.1.0 [..]
|
||||||
|
[COMPILING] bar v0.1.0
|
||||||
|
[COMPILING] foo v0.0.1 ([CWD])
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
p.cargo("build -Zpatch-in-config")
|
||||||
|
.masquerade_as_nightly_cargo()
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[..]
|
||||||
|
[FINISHED] [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// unused patch should be in the lock file
|
||||||
|
let lock = p.read_lockfile();
|
||||||
|
let toml: toml::Value = toml::from_str(&lock).unwrap();
|
||||||
|
assert_eq!(toml["patch"]["unused"].as_array().unwrap().len(), 1);
|
||||||
|
assert_eq!(toml["patch"]["unused"][0]["name"].as_str(), Some("bar"));
|
||||||
|
assert_eq!(
|
||||||
|
toml["patch"]["unused"][0]["version"].as_str(),
|
||||||
|
Some("0.2.0")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn unused_git() {
|
fn unused_git() {
|
||||||
Package::new("bar", "0.1.0").publish();
|
Package::new("bar", "0.1.0").publish();
|
||||||
@ -395,6 +552,66 @@ fn add_patch() {
|
|||||||
p.cargo("build").with_stderr("[FINISHED] [..]").run();
|
p.cargo("build").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("build")
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[UPDATING] `[ROOT][..]` index
|
||||||
|
[DOWNLOADING] crates ...
|
||||||
|
[DOWNLOADED] bar v0.1.0 [..]
|
||||||
|
[COMPILING] bar v0.1.0
|
||||||
|
[COMPILING] foo v0.0.1 ([CWD])
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
p.cargo("build").with_stderr("[FINISHED] [..]").run();
|
||||||
|
|
||||||
|
p.change_file(
|
||||||
|
".cargo/config.toml",
|
||||||
|
r#"
|
||||||
|
[patch.crates-io]
|
||||||
|
bar = { path = 'bar' }
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
p.cargo("build -Zpatch-in-config")
|
||||||
|
.masquerade_as_nightly_cargo()
|
||||||
|
.with_stderr(
|
||||||
|
"\
|
||||||
|
[COMPILING] bar v0.1.0 ([CWD]/bar)
|
||||||
|
[COMPILING] foo v0.0.1 ([CWD])
|
||||||
|
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.run();
|
||||||
|
p.cargo("build -Zpatch-in-config")
|
||||||
|
.masquerade_as_nightly_cargo()
|
||||||
|
.with_stderr("[FINISHED] [..]")
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
#[cargo_test]
|
#[cargo_test]
|
||||||
fn add_ignored_patch() {
|
fn add_ignored_patch() {
|
||||||
Package::new("bar", "0.1.0").publish();
|
Package::new("bar", "0.1.0").publish();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user