Skip to content

Commit 72aee9e

Browse files
committed
Auto merge of #9839 - jonhoo:prefer-cargo-toml-patch, r=ehuss
Stabilize patch-in-config (and prefer config over manifest) Tracking issue: #9269 --- This stabilizes the `patch-in-config` feature ([unstable entry](https://doc.rust-lang.org/cargo/reference/unstable.html#patch-in-config)) following the discussion in #9269 (comment). As requested, this PR _also_ changes the precedence behavior such that a `[patch]` for the same dependency in both `.cargo/config.toml` and `Cargo.toml` prefers the patch from the configuration file over the one from the manifest, which matches the behavior of other overlapping configuration options. The corresponding test has also been updated to reflect this change in behavior.
2 parents 54c341d + e2777ee commit 72aee9e

File tree

5 files changed

+58
-106
lines changed

5 files changed

+58
-106
lines changed

src/cargo/core/features.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,6 @@ unstable_cli_options!(
648648
panic_abort_tests: bool = ("Enable support to run tests with -Cpanic=abort"),
649649
host_config: bool = ("Enable the [host] section in the .cargo/config.toml file"),
650650
target_applies_to_host: bool = ("Enable the `target-applies-to-host` key in the .cargo/config.toml file"),
651-
patch_in_config: bool = ("Allow `[patch]` sections in .cargo/config.toml files"),
652651
rustdoc_map: bool = ("Allow passing external documentation mappings to rustdoc"),
653652
separate_nightlies: bool = (HIDDEN),
654653
terminal_width: Option<Option<usize>> = ("Provide a terminal width to rustc for error truncation"),
@@ -697,6 +696,8 @@ const STABILIZED_EXTRA_LINK_ARG: &str = "Additional linker arguments are now \
697696

698697
const STABILIZED_CONFIGURABLE_ENV: &str = "The [env] section is now always enabled.";
699698

699+
const STABILIZED_PATCH_IN_CONFIG: &str = "The patch-in-config feature is now always enabled.";
700+
700701
fn deserialize_build_std<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
701702
where
702703
D: serde::Deserializer<'de>,
@@ -841,7 +842,6 @@ impl CliUnstable {
841842
"jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?,
842843
"host-config" => self.host_config = parse_empty(k, v)?,
843844
"target-applies-to-host" => self.target_applies_to_host = parse_empty(k, v)?,
844-
"patch-in-config" => self.patch_in_config = parse_empty(k, v)?,
845845
"features" => {
846846
// For now this is still allowed (there are still some
847847
// unstable options like "compare"). This should be removed at
@@ -877,6 +877,7 @@ impl CliUnstable {
877877
"package-features" => stabilized_warn(k, "1.51", STABILIZED_PACKAGE_FEATURES),
878878
"extra-link-arg" => stabilized_warn(k, "1.56", STABILIZED_EXTRA_LINK_ARG),
879879
"configurable-env" => stabilized_warn(k, "1.56", STABILIZED_CONFIGURABLE_ENV),
880+
"patch-in-config" => stabilized_warn(k, "1.56", STABILIZED_PATCH_IN_CONFIG),
880881
"future-incompat-report" => self.future_incompat_report = parse_empty(k, v)?,
881882
_ => bail!("unknown `-Z` flag specified: {}", k),
882883
}

src/cargo/core/workspace.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -362,11 +362,6 @@ impl<'cfg> Workspace<'cfg> {
362362
BTreeMap<String, BTreeMap<String, TomlDependency<ConfigRelativePath>>>,
363363
> = self.config.get("patch")?;
364364

365-
if config_patch.is_some() && !self.config.cli_unstable().patch_in_config {
366-
self.config.shell().warn("`[patch]` in cargo config was ignored, the -Zpatch-in-config command-line flag is required".to_owned())?;
367-
return Ok(HashMap::new());
368-
}
369-
370365
let source = SourceId::for_path(self.root())?;
371366

372367
let mut warnings = Vec::new();
@@ -434,24 +429,24 @@ impl<'cfg> Workspace<'cfg> {
434429

435430
// We could just chain from_manifest and from_config,
436431
// but that's not quite right as it won't deal with overlaps.
437-
let mut combined = from_manifest.clone();
438-
for (url, cdeps) in from_config {
439-
if let Some(deps) = combined.get_mut(&url) {
440-
// We want from_manifest to take precedence for each patched name.
432+
let mut combined = from_config;
433+
for (url, deps_from_manifest) in from_manifest {
434+
if let Some(deps_from_config) = combined.get_mut(&url) {
435+
// We want from_config to take precedence for each patched name.
441436
// NOTE: This is inefficient if the number of patches is large!
442-
let mut left = cdeps.clone();
443-
for dep in &mut *deps {
444-
if let Some(i) = left.iter().position(|cdep| {
437+
let mut from_manifest_pruned = deps_from_manifest.clone();
438+
for dep_from_config in &mut *deps_from_config {
439+
if let Some(i) = from_manifest_pruned.iter().position(|dep_from_manifest| {
445440
// XXX: should this also take into account version numbers?
446-
dep.name_in_toml() == cdep.name_in_toml()
441+
dep_from_config.name_in_toml() == dep_from_manifest.name_in_toml()
447442
}) {
448-
left.swap_remove(i);
443+
from_manifest_pruned.swap_remove(i);
449444
}
450445
}
451446
// Whatever is left does not exist in manifest dependencies.
452-
deps.extend(left);
447+
deps_from_config.extend(from_manifest_pruned);
453448
} else {
454-
combined.insert(url.clone(), cdeps.clone());
449+
combined.insert(url.clone(), deps_from_manifest.clone());
455450
}
456451
}
457452
Ok(combined)

src/doc/src/reference/config.md

+28
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ retry = 2 # network retries
111111
git-fetch-with-cli = true # use the `git` executable for git operations
112112
offline = false # do not access the network
113113

114+
[patch.<registry>]
115+
# Same keys as for [patch] in Cargo.toml
116+
114117
[profile.<name>] # Modify profile settings via config.
115118
opt-level = 0 # Optimization level.
116119
debug = true # Include debug info.
@@ -650,6 +653,31 @@ needed, and generate an error if it encounters a network error.
650653

651654
Can be overridden with the `--offline` command-line option.
652655

656+
#### `[patch]`
657+
658+
Just as you can override dependencies using [`[patch]` in
659+
`Cargo.toml`](overriding-dependencies.md#the-patch-section), you can
660+
override them in the cargo configuration file to apply those patches to
661+
any affected build. The format is identical to the one used in
662+
`Cargo.toml`.
663+
664+
Since `.cargo/config.toml` files are not usually checked into source
665+
control, you should prefer patching using `Cargo.toml` where possible to
666+
ensure that other developers can compile your crate in their own
667+
environments. Patching through cargo configuration files is generally
668+
only appropriate when the patch section is automatically generated by an
669+
external build tool.
670+
671+
If a given dependency is patched both in a cargo configuration file and
672+
a `Cargo.toml` file, the patch in the configuration file is used. If
673+
multiple configuration files patch the same dependency, standard cargo
674+
configuration merging is used, which prefers the value defined closest
675+
to the current directory, with `$HOME/.cargo/config.toml` taking the
676+
lowest precedence.
677+
678+
Relative `path` dependencies in such a `[patch]` section are resolved
679+
relative to the configuration file they appear in.
680+
653681
#### `[profile]`
654682

655683
The `[profile]` table can be used to globally change profile settings, and

src/doc/src/reference/unstable.md

+7-26
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ Each new feature described below should explain how to use it.
100100
* Configuration
101101
* [config-cli](#config-cli) — Adds the ability to pass configuration options on the command-line.
102102
* [config-include](#config-include) — Adds the ability for config files to include other files.
103-
* [patch-in-config](#patch-in-config) — Adds support for specifying the `[patch]` table in config files.
104103
* [`cargo config`](#cargo-config) — Adds a new subcommand for viewing config files.
105104
* Registries
106105
* [credential-process](#credential-process) — Adds support for fetching registry tokens from an external authentication program.
@@ -1227,31 +1226,6 @@ The supported values for `FREQUENCY` are 'always` and 'never', which control
12271226
whether or not a message is printed out at the end of `cargo build` / `cargo check`.
12281227

12291228

1230-
### patch-in-config
1231-
* Original Pull Request: [#9204](https://github.com/rust-lang/cargo/pull/9204)
1232-
* Tracking Issue: [#9269](https://github.com/rust-lang/cargo/issues/9269)
1233-
1234-
The `-Z patch-in-config` flag enables the use of `[patch]` sections in
1235-
cargo configuration files (`.cargo/config.toml`). The format of such
1236-
`[patch]` sections is identical to the one used in `Cargo.toml`.
1237-
1238-
Since `.cargo/config.toml` files are not usually checked into source
1239-
control, you should prefer patching using `Cargo.toml` where possible to
1240-
ensure that other developers can compile your crate in their own
1241-
environments. Patching through cargo configuration files is generally
1242-
only appropriate when the patch section is automatically generated by an
1243-
external build tool.
1244-
1245-
If a given dependency is patched both in a cargo configuration file and
1246-
a `Cargo.toml` file, the patch in `Cargo.toml` is used. If multiple
1247-
configuration files patch the same dependency, standard cargo
1248-
configuration merging is used, which prefers the value defined closest
1249-
to the current directory, with `$HOME/.cargo/config.toml` taking the
1250-
lowest precedence.
1251-
1252-
Relative `path` dependencies in such a `[patch]` section are resolved
1253-
relative to the configuration file they appear in.
1254-
12551229
### `cargo config`
12561230

12571231
* Original Issue: [#2362](https://github.com/rust-lang/cargo/issues/2362)
@@ -1463,3 +1437,10 @@ serde = "1.0.117"
14631437
[profile.dev.package.foo]
14641438
codegen-backend = "cranelift"
14651439
```
1440+
1441+
### patch-in-config
1442+
1443+
The `-Z patch-in-config` flag, and the corresponding support for
1444+
`[patch]` section in Cargo configuration files has been stabilized in
1445+
the 1.56 release. See the [patch field](config.html#patch) for more
1446+
information.

tests/testsuite/patch.rs

+9-62
Original file line numberDiff line numberDiff line change
@@ -66,50 +66,6 @@ fn replace() {
6666
p.cargo("build").with_stderr("[FINISHED] [..]").run();
6767
}
6868

69-
#[cargo_test]
70-
fn from_config_without_z() {
71-
Package::new("bar", "0.1.0").publish();
72-
73-
let p = project()
74-
.file(
75-
"Cargo.toml",
76-
r#"
77-
[package]
78-
name = "foo"
79-
version = "0.0.1"
80-
authors = []
81-
82-
[dependencies]
83-
bar = "0.1.0"
84-
"#,
85-
)
86-
.file(
87-
".cargo/config.toml",
88-
r#"
89-
[patch.crates-io]
90-
bar = { path = 'bar' }
91-
"#,
92-
)
93-
.file("src/lib.rs", "")
94-
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
95-
.file("bar/src/lib.rs", r#""#)
96-
.build();
97-
98-
p.cargo("build")
99-
.with_stderr(
100-
"\
101-
[WARNING] `[patch]` in cargo config was ignored, the -Zpatch-in-config command-line flag is required
102-
[UPDATING] `dummy-registry` index
103-
[DOWNLOADING] crates ...
104-
[DOWNLOADED] bar v0.1.0 ([..])
105-
[COMPILING] bar v0.1.0
106-
[COMPILING] foo v0.0.1 ([CWD])
107-
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
108-
",
109-
)
110-
.run();
111-
}
112-
11369
#[cargo_test]
11470
fn from_config() {
11571
Package::new("bar", "0.1.0").publish();
@@ -139,8 +95,7 @@ fn from_config() {
13995
.file("bar/src/lib.rs", r#""#)
14096
.build();
14197

142-
p.cargo("build -Zpatch-in-config")
143-
.masquerade_as_nightly_cargo()
98+
p.cargo("build")
14499
.with_stderr(
145100
"\
146101
[UPDATING] `dummy-registry` index
@@ -181,8 +136,7 @@ fn from_config_relative() {
181136
.file("bar/src/lib.rs", r#""#)
182137
.build();
183138

184-
p.cargo("build -Zpatch-in-config")
185-
.masquerade_as_nightly_cargo()
139+
p.cargo("build")
186140
.with_stderr(
187141
"\
188142
[UPDATING] `dummy-registry` index
@@ -211,23 +165,22 @@ fn from_config_precedence() {
211165
bar = "0.1.0"
212166
213167
[patch.crates-io]
214-
bar = { path = 'bar' }
168+
bar = { path = 'no-such-path' }
215169
"#,
216170
)
217171
.file(
218172
".cargo/config.toml",
219173
r#"
220174
[patch.crates-io]
221-
bar = { path = 'no-such-path' }
175+
bar = { path = 'bar' }
222176
"#,
223177
)
224178
.file("src/lib.rs", "")
225179
.file("bar/Cargo.toml", &basic_manifest("bar", "0.1.1"))
226180
.file("bar/src/lib.rs", r#""#)
227181
.build();
228182

229-
p.cargo("build -Zpatch-in-config")
230-
.masquerade_as_nightly_cargo()
183+
p.cargo("build")
231184
.with_stderr(
232185
"\
233186
[UPDATING] `dummy-registry` index
@@ -519,8 +472,7 @@ fn unused_from_config() {
519472
.file("bar/src/lib.rs", "not rust code")
520473
.build();
521474

522-
p.cargo("build -Zpatch-in-config")
523-
.masquerade_as_nightly_cargo()
475+
p.cargo("build")
524476
.with_stderr(
525477
"\
526478
[UPDATING] `dummy-registry` index
@@ -537,8 +489,7 @@ fn unused_from_config() {
537489
",
538490
)
539491
.run();
540-
p.cargo("build -Zpatch-in-config")
541-
.masquerade_as_nightly_cargo()
492+
p.cargo("build")
542493
.with_stderr(
543494
"\
544495
[WARNING] Patch `bar v0.2.0 ([CWD]/bar)` was not used in the crate graph.
@@ -733,8 +684,7 @@ fn add_patch_from_config() {
733684
"#,
734685
);
735686

736-
p.cargo("build -Zpatch-in-config")
737-
.masquerade_as_nightly_cargo()
687+
p.cargo("build")
738688
.with_stderr(
739689
"\
740690
[COMPILING] bar v0.1.0 ([CWD]/bar)
@@ -743,10 +693,7 @@ fn add_patch_from_config() {
743693
",
744694
)
745695
.run();
746-
p.cargo("build -Zpatch-in-config")
747-
.masquerade_as_nightly_cargo()
748-
.with_stderr("[FINISHED] [..]")
749-
.run();
696+
p.cargo("build").with_stderr("[FINISHED] [..]").run();
750697
}
751698

752699
#[cargo_test]

0 commit comments

Comments
 (0)