Skip to content

Commit d2d5f35

Browse files
authored
chore(config): figment provider clean up (#11539)
1 parent 8f682de commit d2d5f35

File tree

2 files changed

+60
-51
lines changed

2 files changed

+60
-51
lines changed

crates/config/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,14 +705,14 @@ impl Config {
705705
if let Some(global_toml) = Self::foundry_dir_toml().filter(|p| p.exists()) {
706706
figment = Self::merge_toml_provider(
707707
figment,
708-
TomlFileProvider::new(None, global_toml).cached(),
708+
TomlFileProvider::new(None, global_toml),
709709
profile.clone(),
710710
);
711711
}
712712
// merge local foundry.toml file
713713
figment = Self::merge_toml_provider(
714714
figment,
715-
TomlFileProvider::new(Some("FOUNDRY_CONFIG"), root.join(Self::FILE_NAME)).cached(),
715+
TomlFileProvider::new(Some("FOUNDRY_CONFIG"), root.join(Self::FILE_NAME)),
716716
profile.clone(),
717717
);
718718

crates/config/src/providers/ext.rs

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ use figment::{
66
};
77
use foundry_compilers::ProjectPathsConfig;
88
use heck::ToSnakeCase;
9-
use std::path::{Path, PathBuf};
9+
use std::{
10+
cell::OnceCell,
11+
path::{Path, PathBuf},
12+
};
1013

1114
pub(crate) trait ProviderExt: Provider + Sized {
1215
fn rename(
@@ -46,18 +49,19 @@ impl<P: Provider> ProviderExt for P {}
4649
/// A convenience provider to retrieve a toml file.
4750
/// This will return an error if the env var is set but the file does not exist
4851
pub(crate) struct TomlFileProvider {
49-
pub env_var: Option<&'static str>,
50-
pub default: PathBuf,
51-
pub cache: Option<Result<Map<Profile, Dict>, Error>>,
52+
env_var: Option<&'static str>,
53+
env_val: OnceCell<Option<String>>,
54+
default: PathBuf,
55+
cache: OnceCell<Result<Map<Profile, Dict>, Error>>,
5256
}
5357

5458
impl TomlFileProvider {
55-
pub(crate) fn new(env_var: Option<&'static str>, default: impl Into<PathBuf>) -> Self {
56-
Self { env_var, default: default.into(), cache: None }
59+
pub(crate) fn new(env_var: Option<&'static str>, default: PathBuf) -> Self {
60+
Self { env_var, env_val: OnceCell::new(), default, cache: OnceCell::new() }
5761
}
5862

59-
fn env_val(&self) -> Option<String> {
60-
self.env_var.and_then(Env::var)
63+
fn env_val(&self) -> Option<&str> {
64+
self.env_val.get_or_init(|| self.env_var.and_then(Env::var)).as_deref()
6165
}
6266

6367
fn file(&self) -> PathBuf {
@@ -74,11 +78,6 @@ impl TomlFileProvider {
7478
false
7579
}
7680

77-
pub(crate) fn cached(mut self) -> Self {
78-
self.cache = Some(self.read());
79-
self
80-
}
81-
8281
/// Reads and processes the TOML configuration file, handling inheritance if configured.
8382
fn read(&self) -> Result<Map<Profile, Dict>, Error> {
8483
use serde::de::Error as _;
@@ -248,7 +247,7 @@ impl Provider for TomlFileProvider {
248247
}
249248

250249
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
251-
if let Some(cache) = self.cache.as_ref() { cache.clone() } else { self.read() }
250+
self.cache.get_or_init(|| self.read()).clone()
252251
}
253252
}
254253

@@ -262,17 +261,21 @@ impl<P: Provider> Provider for ForcedSnakeCaseData<P> {
262261
}
263262

264263
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
265-
let mut map = Map::new();
266-
for (profile, dict) in self.0.data()? {
264+
let mut map = self.0.data()?;
265+
for (profile, dict) in &mut map {
267266
if Config::STANDALONE_SECTIONS.contains(&profile.as_ref()) {
268267
// don't force snake case for keys in standalone sections
269-
map.insert(profile, dict);
270268
continue;
271269
}
272-
map.insert(profile, dict.into_iter().map(|(k, v)| (k.to_snake_case(), v)).collect());
270+
let dict2 = std::mem::take(dict);
271+
*dict = dict2.into_iter().map(|(k, v)| (k.to_snake_case(), v)).collect();
273272
}
274273
Ok(map)
275274
}
275+
276+
fn profile(&self) -> Option<Profile> {
277+
self.0.profile()
278+
}
276279
}
277280

278281
/// A Provider that handles breaking changes in toml files
@@ -299,14 +302,14 @@ impl<P: Provider> Provider for BackwardsCompatTomlProvider<P> {
299302
dict.insert("solc".to_string(), v);
300303
}
301304
}
302-
303-
if let Some(v) = dict.remove("odyssey") {
304-
dict.insert("odyssey".to_string(), v);
305-
}
306305
map.insert(profile, dict);
307306
}
308307
Ok(map)
309308
}
309+
310+
fn profile(&self) -> Option<Profile> {
311+
self.0.profile()
312+
}
310313
}
311314

312315
/// A provider that sets the `src` and `output` path depending on their existence.
@@ -474,13 +477,15 @@ impl<P: Provider> Provider for RenameProfileProvider<P> {
474477
fn metadata(&self) -> Metadata {
475478
self.provider.metadata()
476479
}
480+
477481
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
478482
let mut data = self.provider.data()?;
479483
if let Some(data) = data.remove(&self.from) {
480484
return Ok(Map::from([(self.to.clone(), data)]));
481485
}
482486
Ok(Default::default())
483487
}
488+
484489
fn profile(&self) -> Option<Profile> {
485490
Some(self.to.clone())
486491
}
@@ -517,31 +522,32 @@ impl<P: Provider> Provider for UnwrapProfileProvider<P> {
517522
fn metadata(&self) -> Metadata {
518523
self.provider.metadata()
519524
}
525+
520526
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
521-
self.provider.data().and_then(|mut data| {
522-
if let Some(profiles) = data.remove(&self.wrapping_key) {
523-
for (profile_str, profile_val) in profiles {
524-
let profile = Profile::new(&profile_str);
525-
if profile != self.profile {
526-
continue;
527-
}
528-
match profile_val {
529-
Value::Dict(_, dict) => return Ok(profile.collect(dict)),
530-
bad_val => {
531-
let mut err = Error::from(figment::error::Kind::InvalidType(
532-
bad_val.to_actual(),
533-
"dict".into(),
534-
));
535-
err.metadata = Some(self.provider.metadata());
536-
err.profile = Some(self.profile.clone());
537-
return Err(err);
538-
}
527+
let mut data = self.provider.data()?;
528+
if let Some(profiles) = data.remove(&self.wrapping_key) {
529+
for (profile_str, profile_val) in profiles {
530+
let profile = Profile::new(&profile_str);
531+
if profile != self.profile {
532+
continue;
533+
}
534+
match profile_val {
535+
Value::Dict(_, dict) => return Ok(profile.collect(dict)),
536+
bad_val => {
537+
let mut err = Error::from(figment::error::Kind::InvalidType(
538+
bad_val.to_actual(),
539+
"dict".into(),
540+
));
541+
err.metadata = Some(self.provider.metadata());
542+
err.profile = Some(self.profile.clone());
543+
return Err(err);
539544
}
540545
}
541546
}
542-
Ok(Default::default())
543-
})
547+
}
548+
Ok(Default::default())
544549
}
550+
545551
fn profile(&self) -> Option<Profile> {
546552
Some(self.profile.clone())
547553
}
@@ -578,15 +584,18 @@ impl<P: Provider> Provider for WrapProfileProvider<P> {
578584
fn metadata(&self) -> Metadata {
579585
self.provider.metadata()
580586
}
587+
581588
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
582589
if let Some(inner) = self.provider.data()?.remove(&self.profile) {
583590
let value = Value::from(inner);
584-
let dict = [(self.profile.to_string().to_snake_case(), value)].into_iter().collect();
591+
let mut dict = Dict::new();
592+
dict.insert(self.profile.as_str().as_str().to_snake_case(), value);
585593
Ok(self.wrapping_key.collect(dict))
586594
} else {
587595
Ok(Default::default())
588596
}
589597
}
598+
590599
fn profile(&self) -> Option<Profile> {
591600
Some(self.profile.clone())
592601
}
@@ -631,6 +640,7 @@ impl<P: Provider> Provider for OptionalStrictProfileProvider<P> {
631640
fn metadata(&self) -> Metadata {
632641
self.provider.metadata()
633642
}
643+
634644
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
635645
let mut figment = Figment::from(&self.provider);
636646
for profile in &self.profiles {
@@ -651,6 +661,7 @@ impl<P: Provider> Provider for OptionalStrictProfileProvider<P> {
651661
err
652662
})
653663
}
664+
654665
fn profile(&self) -> Option<Profile> {
655666
self.profiles.last().cloned()
656667
}
@@ -677,13 +688,11 @@ impl<P: Provider> Provider for FallbackProfileProvider<P> {
677688
}
678689

679690
fn data(&self) -> Result<Map<Profile, Dict>, Error> {
680-
let data = self.provider.data()?;
681-
if let Some(fallback) = data.get(&self.fallback) {
682-
let mut inner = data.get(&self.profile).cloned().unwrap_or_default();
691+
let mut data = self.provider.data()?;
692+
if let Some(fallback) = data.remove(&self.fallback) {
693+
let mut inner = data.remove(&self.profile).unwrap_or_default();
683694
for (k, v) in fallback {
684-
if !inner.contains_key(k) {
685-
inner.insert(k.to_owned(), v.clone());
686-
}
695+
inner.entry(k).or_insert(v);
687696
}
688697
Ok(self.profile.collect(inner))
689698
} else {

0 commit comments

Comments
 (0)