apply nit notes

Signed-off-by: onur-ozkan <work@onurozkan.dev>
This commit is contained in:
onur-ozkan 2025-04-01 21:56:58 +00:00
parent 78cb4538ee
commit 3f70f197f2
2 changed files with 72 additions and 26 deletions

View file

@ -22,6 +22,9 @@
# Inherits configuration values from different configuration files (a.k.a. config extensions). # Inherits configuration values from different configuration files (a.k.a. config extensions).
# Supports absolute paths, and uses the current directory (where the bootstrap was invoked) # Supports absolute paths, and uses the current directory (where the bootstrap was invoked)
# as the base if the given path is not absolute. # as the base if the given path is not absolute.
#
# The overriding logic follows a right-to-left order. For example, in `include = ["a.toml", "b.toml"]`,
# extension `b.toml` overrides `a.toml`. Also, parent extensions always overrides the inner ones.
#include = [] #include = []
# Keeps track of major changes made to this configuration. # Keeps track of major changes made to this configuration.

View file

@ -751,6 +751,7 @@ enum ReplaceOpt {
trait Merge { trait Merge {
fn merge( fn merge(
&mut self, &mut self,
parent_config_path: Option<PathBuf>,
included_extensions: &mut HashSet<PathBuf>, included_extensions: &mut HashSet<PathBuf>,
other: Self, other: Self,
replace: ReplaceOpt, replace: ReplaceOpt,
@ -760,6 +761,7 @@ trait Merge {
impl Merge for TomlConfig { impl Merge for TomlConfig {
fn merge( fn merge(
&mut self, &mut self,
parent_config_path: Option<PathBuf>,
included_extensions: &mut HashSet<PathBuf>, included_extensions: &mut HashSet<PathBuf>,
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include }: Self, TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include }: Self,
replace: ReplaceOpt, replace: ReplaceOpt,
@ -767,19 +769,27 @@ impl Merge for TomlConfig {
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) { fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
if let Some(new) = y { if let Some(new) = y {
if let Some(original) = x { if let Some(original) = x {
original.merge(&mut Default::default(), new, replace); original.merge(None, &mut Default::default(), new, replace);
} else { } else {
*x = Some(new); *x = Some(new);
} }
} }
} }
for include_path in include.clone().unwrap_or_default() { let parent_dir = parent_config_path
.as_ref()
.and_then(|p| p.parent().map(ToOwned::to_owned))
.unwrap_or_default();
for include_path in include.clone().unwrap_or_default().iter().rev() {
let include_path = parent_dir.join(include_path);
let include_path = include_path.canonicalize().unwrap_or_else(|e| {
eprintln!("ERROR: Failed to canonicalize '{}' path: {e}", include_path.display());
exit!(2);
});
let included_toml = Config::get_toml(&include_path).unwrap_or_else(|e| { let included_toml = Config::get_toml(&include_path).unwrap_or_else(|e| {
eprintln!( eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
"ERROR: Failed to parse default config profile at '{}': {e}",
include_path.display()
);
exit!(2); exit!(2);
}); });
@ -789,13 +799,20 @@ impl Merge for TomlConfig {
include_path.display() include_path.display()
); );
self.merge(included_extensions, included_toml, ReplaceOpt::Override); self.merge(
Some(include_path.clone()),
included_extensions,
included_toml,
// Ensures that parent configuration always takes precedence
// over child configurations.
ReplaceOpt::IgnoreDuplicate,
);
included_extensions.remove(&include_path); included_extensions.remove(&include_path);
} }
self.change_id.inner.merge(&mut Default::default(), change_id.inner, replace); self.change_id.inner.merge(None, &mut Default::default(), change_id.inner, replace);
self.profile.merge(&mut Default::default(), profile, replace); self.profile.merge(None, &mut Default::default(), profile, replace);
do_merge(&mut self.build, build, replace); do_merge(&mut self.build, build, replace);
do_merge(&mut self.install, install, replace); do_merge(&mut self.install, install, replace);
@ -810,7 +827,7 @@ impl Merge for TomlConfig {
(Some(original_target), Some(new_target)) => { (Some(original_target), Some(new_target)) => {
for (triple, new) in new_target { for (triple, new) in new_target {
if let Some(original) = original_target.get_mut(&triple) { if let Some(original) = original_target.get_mut(&triple) {
original.merge(&mut Default::default(), new, replace); original.merge(None, &mut Default::default(), new, replace);
} else { } else {
original_target.insert(triple, new); original_target.insert(triple, new);
} }
@ -831,7 +848,13 @@ macro_rules! define_config {
} }
impl Merge for $name { impl Merge for $name {
fn merge(&mut self, _included_extensions: &mut HashSet<PathBuf>, other: Self, replace: ReplaceOpt) { fn merge(
&mut self,
_parent_config_path: Option<PathBuf>,
_included_extensions: &mut HashSet<PathBuf>,
other: Self,
replace: ReplaceOpt
) {
$( $(
match replace { match replace {
ReplaceOpt::IgnoreDuplicate => { ReplaceOpt::IgnoreDuplicate => {
@ -933,6 +956,7 @@ macro_rules! define_config {
impl<T> Merge for Option<T> { impl<T> Merge for Option<T> {
fn merge( fn merge(
&mut self, &mut self,
_parent_config_path: Option<PathBuf>,
_included_extensions: &mut HashSet<PathBuf>, _included_extensions: &mut HashSet<PathBuf>,
other: Self, other: Self,
replace: ReplaceOpt, replace: ReplaceOpt,
@ -1581,7 +1605,8 @@ impl Config {
// but not if `bootstrap.toml` hasn't been created. // but not if `bootstrap.toml` hasn't been created.
let mut toml = if !using_default_path || toml_path.exists() { let mut toml = if !using_default_path || toml_path.exists() {
config.config = Some(if cfg!(not(test)) { config.config = Some(if cfg!(not(test)) {
toml_path.canonicalize().unwrap() toml_path = toml_path.canonicalize().unwrap();
toml_path.clone()
} else { } else {
toml_path.clone() toml_path.clone()
}); });
@ -1609,6 +1634,24 @@ impl Config {
toml.profile = Some("dist".into()); toml.profile = Some("dist".into());
} }
// Reverse the list to ensure the last added config extension remains the most dominant.
// For example, given ["a.toml", "b.toml"], "b.toml" should take precedence over "a.toml".
//
// This must be handled before applying the `profile` since `include`s should always take
// precedence over `profile`s.
for include_path in toml.include.clone().unwrap_or_default().iter().rev() {
let included_toml = get_toml(include_path).unwrap_or_else(|e| {
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
exit!(2);
});
toml.merge(
Some(toml_path.join(include_path)),
&mut Default::default(),
included_toml,
ReplaceOpt::IgnoreDuplicate,
);
}
if let Some(include) = &toml.profile { if let Some(include) = &toml.profile {
// Allows creating alias for profile names, allowing // Allows creating alias for profile names, allowing
// profiles to be renamed while maintaining back compatibility // profiles to be renamed while maintaining back compatibility
@ -1630,18 +1673,12 @@ impl Config {
); );
exit!(2); exit!(2);
}); });
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::IgnoreDuplicate); toml.merge(
} Some(include_path),
&mut Default::default(),
for include_path in toml.include.clone().unwrap_or_default() { included_toml,
let included_toml = get_toml(&include_path).unwrap_or_else(|e| { ReplaceOpt::IgnoreDuplicate,
eprintln!( );
"ERROR: Failed to parse default config profile at '{}': {e}",
include_path.display()
);
exit!(2);
});
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::Override);
} }
let mut override_toml = TomlConfig::default(); let mut override_toml = TomlConfig::default();
@ -1652,7 +1689,12 @@ impl Config {
let mut err = match get_table(option) { let mut err = match get_table(option) {
Ok(v) => { Ok(v) => {
override_toml.merge(&mut Default::default(), v, ReplaceOpt::ErrorOnDuplicate); override_toml.merge(
None,
&mut Default::default(),
v,
ReplaceOpt::ErrorOnDuplicate,
);
continue; continue;
} }
Err(e) => e, Err(e) => e,
@ -1664,6 +1706,7 @@ impl Config {
match get_table(&format!(r#"{key}="{value}""#)) { match get_table(&format!(r#"{key}="{value}""#)) {
Ok(v) => { Ok(v) => {
override_toml.merge( override_toml.merge(
None,
&mut Default::default(), &mut Default::default(),
v, v,
ReplaceOpt::ErrorOnDuplicate, ReplaceOpt::ErrorOnDuplicate,
@ -1677,7 +1720,7 @@ impl Config {
eprintln!("failed to parse override `{option}`: `{err}"); eprintln!("failed to parse override `{option}`: `{err}");
exit!(2) exit!(2)
} }
toml.merge(&mut Default::default(), override_toml, ReplaceOpt::Override); toml.merge(None, &mut Default::default(), override_toml, ReplaceOpt::Override);
config.change_id = toml.change_id.inner; config.change_id = toml.change_id.inner;