implement cyclic inclusion handling
Signed-off-by: onur-ozkan <work@onurozkan.dev>
This commit is contained in:
parent
89e3befe63
commit
4e80659b32
1 changed files with 38 additions and 13 deletions
|
@ -6,6 +6,7 @@
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::fmt::{self, Display};
|
||||
use std::hash::Hash;
|
||||
use std::io::IsTerminal;
|
||||
use std::path::{Path, PathBuf, absolute};
|
||||
use std::process::Command;
|
||||
|
@ -748,19 +749,25 @@ enum ReplaceOpt {
|
|||
}
|
||||
|
||||
trait Merge {
|
||||
fn merge(&mut self, other: Self, replace: ReplaceOpt);
|
||||
fn merge(
|
||||
&mut self,
|
||||
included_extensions: &mut HashSet<PathBuf>,
|
||||
other: Self,
|
||||
replace: ReplaceOpt,
|
||||
);
|
||||
}
|
||||
|
||||
impl Merge for TomlConfig {
|
||||
fn merge(
|
||||
&mut self,
|
||||
included_extensions: &mut HashSet<PathBuf>,
|
||||
TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id, include }: Self,
|
||||
replace: ReplaceOpt,
|
||||
) {
|
||||
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
|
||||
if let Some(new) = y {
|
||||
if let Some(original) = x {
|
||||
original.merge(new, replace);
|
||||
original.merge(&mut Default::default(), new, replace);
|
||||
} else {
|
||||
*x = Some(new);
|
||||
}
|
||||
|
@ -775,11 +782,20 @@ impl Merge for TomlConfig {
|
|||
);
|
||||
exit!(2);
|
||||
});
|
||||
self.merge(included_toml, ReplaceOpt::Override);
|
||||
|
||||
assert!(
|
||||
included_extensions.insert(include_path.clone()),
|
||||
"Cyclic inclusion detected: '{}' is being included again before its previous inclusion was fully processed.",
|
||||
include_path.display()
|
||||
);
|
||||
|
||||
self.merge(included_extensions, included_toml, ReplaceOpt::Override);
|
||||
|
||||
included_extensions.remove(&include_path);
|
||||
}
|
||||
|
||||
self.change_id.inner.merge(change_id.inner, replace);
|
||||
self.profile.merge(profile, replace);
|
||||
self.change_id.inner.merge(&mut Default::default(), change_id.inner, replace);
|
||||
self.profile.merge(&mut Default::default(), profile, replace);
|
||||
|
||||
do_merge(&mut self.build, build, replace);
|
||||
do_merge(&mut self.install, install, replace);
|
||||
|
@ -794,7 +810,7 @@ impl Merge for TomlConfig {
|
|||
(Some(original_target), Some(new_target)) => {
|
||||
for (triple, new) in new_target {
|
||||
if let Some(original) = original_target.get_mut(&triple) {
|
||||
original.merge(new, replace);
|
||||
original.merge(&mut Default::default(), new, replace);
|
||||
} else {
|
||||
original_target.insert(triple, new);
|
||||
}
|
||||
|
@ -815,7 +831,7 @@ macro_rules! define_config {
|
|||
}
|
||||
|
||||
impl Merge for $name {
|
||||
fn merge(&mut self, other: Self, replace: ReplaceOpt) {
|
||||
fn merge(&mut self, _included_extensions: &mut HashSet<PathBuf>, other: Self, replace: ReplaceOpt) {
|
||||
$(
|
||||
match replace {
|
||||
ReplaceOpt::IgnoreDuplicate => {
|
||||
|
@ -915,7 +931,12 @@ macro_rules! define_config {
|
|||
}
|
||||
|
||||
impl<T> Merge for Option<T> {
|
||||
fn merge(&mut self, other: Self, replace: ReplaceOpt) {
|
||||
fn merge(
|
||||
&mut self,
|
||||
_included_extensions: &mut HashSet<PathBuf>,
|
||||
other: Self,
|
||||
replace: ReplaceOpt,
|
||||
) {
|
||||
match replace {
|
||||
ReplaceOpt::IgnoreDuplicate => {
|
||||
if self.is_none() {
|
||||
|
@ -1609,7 +1630,7 @@ impl Config {
|
|||
);
|
||||
exit!(2);
|
||||
});
|
||||
toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
|
||||
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::IgnoreDuplicate);
|
||||
}
|
||||
|
||||
for include_path in toml.include.clone().unwrap_or_default() {
|
||||
|
@ -1620,7 +1641,7 @@ impl Config {
|
|||
);
|
||||
exit!(2);
|
||||
});
|
||||
toml.merge(included_toml, ReplaceOpt::Override);
|
||||
toml.merge(&mut Default::default(), included_toml, ReplaceOpt::Override);
|
||||
}
|
||||
|
||||
let mut override_toml = TomlConfig::default();
|
||||
|
@ -1631,7 +1652,7 @@ impl Config {
|
|||
|
||||
let mut err = match get_table(option) {
|
||||
Ok(v) => {
|
||||
override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
|
||||
override_toml.merge(&mut Default::default(), v, ReplaceOpt::ErrorOnDuplicate);
|
||||
continue;
|
||||
}
|
||||
Err(e) => e,
|
||||
|
@ -1642,7 +1663,11 @@ impl Config {
|
|||
if !value.contains('"') {
|
||||
match get_table(&format!(r#"{key}="{value}""#)) {
|
||||
Ok(v) => {
|
||||
override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
|
||||
override_toml.merge(
|
||||
&mut Default::default(),
|
||||
v,
|
||||
ReplaceOpt::ErrorOnDuplicate,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
Err(e) => err = e,
|
||||
|
@ -1652,7 +1677,7 @@ impl Config {
|
|||
eprintln!("failed to parse override `{option}`: `{err}");
|
||||
exit!(2)
|
||||
}
|
||||
toml.merge(override_toml, ReplaceOpt::Override);
|
||||
toml.merge(&mut Default::default(), override_toml, ReplaceOpt::Override);
|
||||
|
||||
config.change_id = toml.change_id.inner;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue