Skip to content

Commit 3f70f19

Browse files
committed
apply nit notes
Signed-off-by: onur-ozkan <[email protected]>
1 parent 78cb453 commit 3f70f19

File tree

2 files changed

+72
-26
lines changed

2 files changed

+72
-26
lines changed

Diff for: bootstrap.example.toml

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
# Inherits configuration values from different configuration files (a.k.a. config extensions).
2323
# Supports absolute paths, and uses the current directory (where the bootstrap was invoked)
2424
# as the base if the given path is not absolute.
25+
#
26+
# The overriding logic follows a right-to-left order. For example, in `include = ["a.toml", "b.toml"]`,
27+
# extension `b.toml` overrides `a.toml`. Also, parent extensions always overrides the inner ones.
2528
#include = []
2629

2730
# Keeps track of major changes made to this configuration.

Diff for: src/bootstrap/src/core/config/config.rs

+69-26
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,7 @@ enum ReplaceOpt {
751751
trait Merge {
752752
fn merge(
753753
&mut self,
754+
parent_config_path: Option<PathBuf>,
754755
included_extensions: &mut HashSet<PathBuf>,
755756
other: Self,
756757
replace: ReplaceOpt,
@@ -760,26 +761,35 @@ trait Merge {
760761
impl Merge for TomlConfig {
761762
fn merge(
762763
&mut self,
764+
parent_config_path: Option<PathBuf>,
763765
included_extensions: &mut HashSet<PathBuf>,
764766
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include }: Self,
765767
replace: ReplaceOpt,
766768
) {
767769
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
768770
if let Some(new) = y {
769771
if let Some(original) = x {
770-
original.merge(&mut Default::default(), new, replace);
772+
original.merge(None, &mut Default::default(), new, replace);
771773
} else {
772774
*x = Some(new);
773775
}
774776
}
775777
}
776778

777-
for include_path in include.clone().unwrap_or_default() {
779+
let parent_dir = parent_config_path
780+
.as_ref()
781+
.and_then(|p| p.parent().map(ToOwned::to_owned))
782+
.unwrap_or_default();
783+
784+
for include_path in include.clone().unwrap_or_default().iter().rev() {
785+
let include_path = parent_dir.join(include_path);
786+
let include_path = include_path.canonicalize().unwrap_or_else(|e| {
787+
eprintln!("ERROR: Failed to canonicalize '{}' path: {e}", include_path.display());
788+
exit!(2);
789+
});
790+
778791
let included_toml = Config::get_toml(&include_path).unwrap_or_else(|e| {
779-
eprintln!(
780-
"ERROR: Failed to parse default config profile at '{}': {e}",
781-
include_path.display()
782-
);
792+
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
783793
exit!(2);
784794
});
785795

@@ -789,13 +799,20 @@ impl Merge for TomlConfig {
789799
include_path.display()
790800
);
791801

792-
self.merge(included_extensions, included_toml, ReplaceOpt::Override);
802+
self.merge(
803+
Some(include_path.clone()),
804+
included_extensions,
805+
included_toml,
806+
// Ensures that parent configuration always takes precedence
807+
// over child configurations.
808+
ReplaceOpt::IgnoreDuplicate,
809+
);
793810

794811
included_extensions.remove(&include_path);
795812
}
796813

797-
self.change_id.inner.merge(&mut Default::default(), change_id.inner, replace);
798-
self.profile.merge(&mut Default::default(), profile, replace);
814+
self.change_id.inner.merge(None, &mut Default::default(), change_id.inner, replace);
815+
self.profile.merge(None, &mut Default::default(), profile, replace);
799816

800817
do_merge(&mut self.build, build, replace);
801818
do_merge(&mut self.install, install, replace);
@@ -810,7 +827,7 @@ impl Merge for TomlConfig {
810827
(Some(original_target), Some(new_target)) => {
811828
for (triple, new) in new_target {
812829
if let Some(original) = original_target.get_mut(&triple) {
813-
original.merge(&mut Default::default(), new, replace);
830+
original.merge(None, &mut Default::default(), new, replace);
814831
} else {
815832
original_target.insert(triple, new);
816833
}
@@ -831,7 +848,13 @@ macro_rules! define_config {
831848
}
832849

833850
impl Merge for $name {
834-
fn merge(&mut self, _included_extensions: &mut HashSet<PathBuf>, other: Self, replace: ReplaceOpt) {
851+
fn merge(
852+
&mut self,
853+
_parent_config_path: Option<PathBuf>,
854+
_included_extensions: &mut HashSet<PathBuf>,
855+
other: Self,
856+
replace: ReplaceOpt
857+
) {
835858
$(
836859
match replace {
837860
ReplaceOpt::IgnoreDuplicate => {
@@ -933,6 +956,7 @@ macro_rules! define_config {
933956
impl<T> Merge for Option<T> {
934957
fn merge(
935958
&mut self,
959+
_parent_config_path: Option<PathBuf>,
936960
_included_extensions: &mut HashSet<PathBuf>,
937961
other: Self,
938962
replace: ReplaceOpt,
@@ -1581,7 +1605,8 @@ impl Config {
15811605
// but not if `bootstrap.toml` hasn't been created.
15821606
let mut toml = if !using_default_path || toml_path.exists() {
15831607
config.config = Some(if cfg!(not(test)) {
1584-
toml_path.canonicalize().unwrap()
1608+
toml_path = toml_path.canonicalize().unwrap();
1609+
toml_path.clone()
15851610
} else {
15861611
toml_path.clone()
15871612
});
@@ -1609,6 +1634,24 @@ impl Config {
16091634
toml.profile = Some("dist".into());
16101635
}
16111636

1637+
// Reverse the list to ensure the last added config extension remains the most dominant.
1638+
// For example, given ["a.toml", "b.toml"], "b.toml" should take precedence over "a.toml".
1639+
//
1640+
// This must be handled before applying the `profile` since `include`s should always take
1641+
// precedence over `profile`s.
1642+
for include_path in toml.include.clone().unwrap_or_default().iter().rev() {
1643+
let included_toml = get_toml(include_path).unwrap_or_else(|e| {
1644+
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
1645+
exit!(2);
1646+
});
1647+
toml.merge(
1648+
Some(toml_path.join(include_path)),
1649+
&mut Default::default(),
1650+
included_toml,
1651+
ReplaceOpt::IgnoreDuplicate,
1652+
);
1653+
}
1654+
16121655
if let Some(include) = &toml.profile {
16131656
// Allows creating alias for profile names, allowing
16141657
// profiles to be renamed while maintaining back compatibility
@@ -1630,18 +1673,12 @@ impl Config {
16301673
);
16311674
exit!(2);
16321675
});
1633-
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::IgnoreDuplicate);
1634-
}
1635-
1636-
for include_path in toml.include.clone().unwrap_or_default() {
1637-
let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
1638-
eprintln!(
1639-
"ERROR: Failed to parse default config profile at '{}': {e}",
1640-
include_path.display()
1641-
);
1642-
exit!(2);
1643-
});
1644-
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::Override);
1676+
toml.merge(
1677+
Some(include_path),
1678+
&mut Default::default(),
1679+
included_toml,
1680+
ReplaceOpt::IgnoreDuplicate,
1681+
);
16451682
}
16461683

16471684
let mut override_toml = TomlConfig::default();
@@ -1652,7 +1689,12 @@ impl Config {
16521689

16531690
let mut err = match get_table(option) {
16541691
Ok(v) => {
1655-
override_toml.merge(&mut Default::default(), v, ReplaceOpt::ErrorOnDuplicate);
1692+
override_toml.merge(
1693+
None,
1694+
&mut Default::default(),
1695+
v,
1696+
ReplaceOpt::ErrorOnDuplicate,
1697+
);
16561698
continue;
16571699
}
16581700
Err(e) => e,
@@ -1664,6 +1706,7 @@ impl Config {
16641706
match get_table(&format!(r#"{key}="{value}""#)) {
16651707
Ok(v) => {
16661708
override_toml.merge(
1709+
None,
16671710
&mut Default::default(),
16681711
v,
16691712
ReplaceOpt::ErrorOnDuplicate,
@@ -1677,7 +1720,7 @@ impl Config {
16771720
eprintln!("failed to parse override `{option}`: `{err}");
16781721
exit!(2)
16791722
}
1680-
toml.merge(&mut Default::default(), override_toml, ReplaceOpt::Override);
1723+
toml.merge(None, &mut Default::default(), override_toml, ReplaceOpt::Override);
16811724

16821725
config.change_id = toml.change_id.inner;
16831726

0 commit comments

Comments
 (0)