Skip to content

Commit 8b7db3a

Browse files
authored
feat(config): toml inheritance support (#11284)
1 parent 7238131 commit 8b7db3a

File tree

4 files changed

+1321
-8
lines changed

4 files changed

+1321
-8
lines changed

crates/config/src/extend.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use std::collections::HashMap;
2+
3+
use serde::{Deserialize, Serialize};
4+
5+
/// Strategy for extending configuration from a base file.
6+
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
7+
#[serde(rename_all = "kebab-case")]
8+
pub enum ExtendStrategy {
9+
/// Uses `admerge` figment strategy.
10+
/// Arrays are concatenated (base elements + local elements).
11+
/// Other values are replaced (local values override base values).
12+
#[default]
13+
ExtendArrays,
14+
15+
/// Uses `merge` figment strategy.
16+
/// Arrays are replaced entirely (local arrays replace base arrays).
17+
/// Other values are replaced (local values override base values).
18+
ReplaceArrays,
19+
20+
/// Throws an error if any of the keys in the inherited toml file are also in `foundry.toml`.
21+
NoCollision,
22+
}
23+
24+
/// Configuration for extending from a base file.
25+
///
26+
/// Supports two formats:
27+
/// - String: `extends = "base.toml"`
28+
/// - Object: `extends = { path = "base.toml", strategy = "no-collision" }`
29+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
30+
#[serde(untagged)]
31+
pub enum Extends {
32+
/// Simple string path to base file
33+
Path(String),
34+
/// Detailed configuration with path and strategy
35+
Config(ExtendConfig),
36+
}
37+
38+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
39+
pub struct ExtendConfig {
40+
pub path: String,
41+
#[serde(default)]
42+
pub strategy: Option<ExtendStrategy>,
43+
}
44+
45+
impl Extends {
46+
/// Get the path to the base file
47+
pub fn path(&self) -> &str {
48+
match self {
49+
Self::Path(path) => path,
50+
Self::Config(config) => &config.path,
51+
}
52+
}
53+
54+
/// Get the strategy to use for extending
55+
pub fn strategy(&self) -> ExtendStrategy {
56+
match self {
57+
Self::Path(_) => ExtendStrategy::default(),
58+
Self::Config(config) => config.strategy.unwrap_or_default(),
59+
}
60+
}
61+
}
62+
63+
// -- HELPERS -----------------------------------------------------------------
64+
65+
// Helper structs to only extract the 'extends' field and its strategy from the profiles
66+
#[derive(Deserialize, Default)]
67+
pub(crate) struct ExtendsPartialConfig {
68+
#[serde(default)]
69+
pub profile: Option<HashMap<String, ExtendsHelper>>,
70+
}
71+
72+
#[derive(Deserialize, Default)]
73+
pub(crate) struct ExtendsHelper {
74+
#[serde(default)]
75+
pub extends: Option<Extends>,
76+
}

0 commit comments

Comments
 (0)