Skip to content

Commit ba399ae

Browse files
authored
perf: support FigmentProviders settings (#7812)
1 parent a6e7fe0 commit ba399ae

File tree

2 files changed

+108
-69
lines changed

2 files changed

+108
-69
lines changed

crates/config/src/lib.rs

Lines changed: 103 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,86 @@ impl Config {
509509
Ok(config)
510510
}
511511

512+
/// Returns the populated [Figment] using the requested [FigmentProviders] preset.
513+
///
514+
/// This will merge various providers, such as env,toml,remappings into the figment.
515+
pub fn to_figment(self, providers: FigmentProviders) -> Figment {
516+
let mut c = self;
517+
let profile = Config::selected_profile();
518+
let mut figment = Figment::default().merge(DappHardhatDirProvider(&c.__root.0));
519+
520+
// merge global foundry.toml file
521+
if let Some(global_toml) = Config::foundry_dir_toml().filter(|p| p.exists()) {
522+
figment = Config::merge_toml_provider(
523+
figment,
524+
TomlFileProvider::new(None, global_toml).cached(),
525+
profile.clone(),
526+
);
527+
}
528+
// merge local foundry.toml file
529+
figment = Config::merge_toml_provider(
530+
figment,
531+
TomlFileProvider::new(Some("FOUNDRY_CONFIG"), c.__root.0.join(Config::FILE_NAME))
532+
.cached(),
533+
profile.clone(),
534+
);
535+
536+
// merge environment variables
537+
figment = figment
538+
.merge(
539+
Env::prefixed("DAPP_")
540+
.ignore(&["REMAPPINGS", "LIBRARIES", "FFI", "FS_PERMISSIONS"])
541+
.global(),
542+
)
543+
.merge(
544+
Env::prefixed("DAPP_TEST_")
545+
.ignore(&["CACHE", "FUZZ_RUNS", "DEPTH", "FFI", "FS_PERMISSIONS"])
546+
.global(),
547+
)
548+
.merge(DappEnvCompatProvider)
549+
.merge(EtherscanEnvProvider::default())
550+
.merge(
551+
Env::prefixed("FOUNDRY_")
552+
.ignore(&["PROFILE", "REMAPPINGS", "LIBRARIES", "FFI", "FS_PERMISSIONS"])
553+
.map(|key| {
554+
let key = key.as_str();
555+
if Config::STANDALONE_SECTIONS.iter().any(|section| {
556+
key.starts_with(&format!("{}_", section.to_ascii_uppercase()))
557+
}) {
558+
key.replacen('_', ".", 1).into()
559+
} else {
560+
key.into()
561+
}
562+
})
563+
.global(),
564+
)
565+
.select(profile.clone());
566+
567+
// only resolve remappings if all providers are requested
568+
if providers.is_all() {
569+
// we try to merge remappings after we've merged all other providers, this prevents
570+
// redundant fs lookups to determine the default remappings that are eventually updated
571+
// by other providers, like the toml file
572+
let remappings = RemappingsProvider {
573+
auto_detect_remappings: figment
574+
.extract_inner::<bool>("auto_detect_remappings")
575+
.unwrap_or(true),
576+
lib_paths: figment
577+
.extract_inner::<Vec<PathBuf>>("libs")
578+
.map(Cow::Owned)
579+
.unwrap_or_else(|_| Cow::Borrowed(&c.libs)),
580+
root: &c.__root.0,
581+
remappings: figment.extract_inner::<Vec<Remapping>>("remappings"),
582+
};
583+
figment = figment.merge(remappings);
584+
}
585+
586+
// normalize defaults
587+
figment = c.normalize_defaults(figment);
588+
589+
Figment::from(c).merge(figment).select(profile)
590+
}
591+
512592
/// The config supports relative paths and tracks the root path separately see
513593
/// `Config::with_root`
514594
///
@@ -1658,77 +1738,32 @@ impl Config {
16581738
}
16591739

16601740
impl From<Config> for Figment {
1661-
fn from(mut c: Config) -> Figment {
1662-
let profile = Config::selected_profile();
1663-
let mut figment = Figment::default().merge(DappHardhatDirProvider(&c.__root.0));
1664-
1665-
// merge global foundry.toml file
1666-
if let Some(global_toml) = Config::foundry_dir_toml().filter(|p| p.exists()) {
1667-
figment = Config::merge_toml_provider(
1668-
figment,
1669-
TomlFileProvider::new(None, global_toml).cached(),
1670-
profile.clone(),
1671-
);
1672-
}
1673-
// merge local foundry.toml file
1674-
figment = Config::merge_toml_provider(
1675-
figment,
1676-
TomlFileProvider::new(Some("FOUNDRY_CONFIG"), c.__root.0.join(Config::FILE_NAME))
1677-
.cached(),
1678-
profile.clone(),
1679-
);
1680-
1681-
// merge environment variables
1682-
figment = figment
1683-
.merge(
1684-
Env::prefixed("DAPP_")
1685-
.ignore(&["REMAPPINGS", "LIBRARIES", "FFI", "FS_PERMISSIONS"])
1686-
.global(),
1687-
)
1688-
.merge(
1689-
Env::prefixed("DAPP_TEST_")
1690-
.ignore(&["CACHE", "FUZZ_RUNS", "DEPTH", "FFI", "FS_PERMISSIONS"])
1691-
.global(),
1692-
)
1693-
.merge(DappEnvCompatProvider)
1694-
.merge(EtherscanEnvProvider::default())
1695-
.merge(
1696-
Env::prefixed("FOUNDRY_")
1697-
.ignore(&["PROFILE", "REMAPPINGS", "LIBRARIES", "FFI", "FS_PERMISSIONS"])
1698-
.map(|key| {
1699-
let key = key.as_str();
1700-
if Config::STANDALONE_SECTIONS.iter().any(|section| {
1701-
key.starts_with(&format!("{}_", section.to_ascii_uppercase()))
1702-
}) {
1703-
key.replacen('_', ".", 1).into()
1704-
} else {
1705-
key.into()
1706-
}
1707-
})
1708-
.global(),
1709-
)
1710-
.select(profile.clone());
1741+
fn from(c: Config) -> Figment {
1742+
c.to_figment(FigmentProviders::All)
1743+
}
1744+
}
17111745

1712-
// we try to merge remappings after we've merged all other providers, this prevents
1713-
// redundant fs lookups to determine the default remappings that are eventually updated by
1714-
// other providers, like the toml file
1715-
let remappings = RemappingsProvider {
1716-
auto_detect_remappings: figment
1717-
.extract_inner::<bool>("auto_detect_remappings")
1718-
.unwrap_or(true),
1719-
lib_paths: figment
1720-
.extract_inner::<Vec<PathBuf>>("libs")
1721-
.map(Cow::Owned)
1722-
.unwrap_or_else(|_| Cow::Borrowed(&c.libs)),
1723-
root: &c.__root.0,
1724-
remappings: figment.extract_inner::<Vec<Remapping>>("remappings"),
1725-
};
1726-
let merge = figment.merge(remappings);
1746+
/// Determines what providers should be used when loading the [Figment] for a [Config]
1747+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
1748+
pub enum FigmentProviders {
1749+
/// Include all providers
1750+
#[default]
1751+
All,
1752+
/// Only include necessary providers that are useful for cast commands
1753+
///
1754+
/// This will exclude more expensive providers such as remappings
1755+
Cast,
1756+
}
17271757

1728-
// normalize defaults
1729-
let merge = c.normalize_defaults(merge);
1758+
impl FigmentProviders {
1759+
/// Returns true if all providers should be included
1760+
pub const fn is_all(&self) -> bool {
1761+
matches!(self, Self::All)
1762+
}
17301763

1731-
Figment::from(c).merge(merge).select(profile)
1764+
/// Returns true if this is the cast preset
1765+
pub const fn is_cast(&self) -> bool {
1766+
matches!(self, Self::Cast)
17321767
}
17331768
}
17341769

crates/config/src/macros.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,16 @@ macro_rules! merge_impl_figment_convert {
184184
}
185185

186186
/// A macro to implement converters from a type to [`Config`] and [`figment::Figment`]
187+
///
188+
/// Via [Config::to_figment](crate::Config::to_figment) and the
189+
/// [Cast](crate::FigmentProviders::Cast) profile.
187190
#[macro_export]
188191
macro_rules! impl_figment_convert_cast {
189192
($name:ty) => {
190193
impl<'a> From<&'a $name> for $crate::figment::Figment {
191194
fn from(args: &'a $name) -> Self {
192-
$crate::Config::figment_with_root($crate::find_project_root_path(None).unwrap())
195+
$crate::Config::with_root($crate::find_project_root_path(None).unwrap())
196+
.to_figment($crate::FigmentProviders::Cast)
193197
.merge(args)
194198
}
195199
}

0 commit comments

Comments
 (0)