forked from NotAShelf/beer
config: warn on unknown keys instead of dropping them silently
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Id06a7e2c96cfdcb69a21fa0416d988696a6a6964
This commit is contained in:
parent
5a9242b53f
commit
27a509362b
3 changed files with 57 additions and 11 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -42,6 +42,7 @@ dependencies = [
|
||||||
"pound",
|
"pound",
|
||||||
"rustix",
|
"rustix",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_ignored",
|
||||||
"smithay-client-toolkit",
|
"smithay-client-toolkit",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
@ -488,6 +489,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_ignored"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ rustix = { version = "1.1.4", features = [
|
||||||
"fs",
|
"fs",
|
||||||
] }
|
] }
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
|
serde_ignored = "0.1.12"
|
||||||
smithay-client-toolkit = "0.20.0"
|
smithay-client-toolkit = "0.20.0"
|
||||||
thiserror = "2.0.18"
|
thiserror = "2.0.18"
|
||||||
toml = "0.9"
|
toml = "0.9"
|
||||||
|
|
|
||||||
|
|
@ -195,19 +195,32 @@ impl Config {
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Self::default();
|
return Self::default();
|
||||||
}
|
}
|
||||||
match std::fs::read_to_string(&path) {
|
let text = match std::fs::read_to_string(&path) {
|
||||||
Ok(text) => match toml::from_str(&text) {
|
Ok(text) => text,
|
||||||
Ok(config) => {
|
|
||||||
tracing::info!("loaded config from {}", path.display());
|
|
||||||
config
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tracing::warn!("config {}: {err}; using defaults", path.display());
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!("read config {}: {err}; using defaults", path.display());
|
tracing::warn!("read config {}: {err}; using defaults", path.display());
|
||||||
|
return Self::default();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Deserialize through serde_ignored so a typo'd key (`font-sze`) is
|
||||||
|
// reported instead of silently dropped, while still loading: unknown
|
||||||
|
// keys stay tolerated, keeping forward-compatibility with newer configs.
|
||||||
|
let de = match toml::Deserializer::parse(&text) {
|
||||||
|
Ok(de) => de,
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!("config {}: {err}; using defaults", path.display());
|
||||||
|
return Self::default();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match serde_ignored::deserialize(de, |key| {
|
||||||
|
tracing::warn!("config {}: unknown key `{key}` ignored", path.display());
|
||||||
|
}) {
|
||||||
|
Ok(config) => {
|
||||||
|
tracing::info!("loaded config from {}", path.display());
|
||||||
|
config
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!("config {}: {err}; using defaults", path.display());
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -253,4 +266,25 @@ mod tests {
|
||||||
assert_eq!(c.main.term, "beer");
|
assert_eq!(c.main.term, "beer");
|
||||||
assert_eq!(c.scrollback.lines, 10_000);
|
assert_eq!(c.scrollback.lines, 10_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_keys_are_reported_but_still_load() {
|
||||||
|
let toml = r##"
|
||||||
|
[main]
|
||||||
|
font-sze = 14
|
||||||
|
font = "JetBrains Mono"
|
||||||
|
|
||||||
|
[made-up]
|
||||||
|
x = 1
|
||||||
|
"##;
|
||||||
|
let mut unknown = Vec::new();
|
||||||
|
let de = toml::Deserializer::parse(toml).unwrap();
|
||||||
|
let c: Config =
|
||||||
|
serde_ignored::deserialize(de, |key| unknown.push(key.to_string())).unwrap();
|
||||||
|
// The typo and the bogus table are both surfaced...
|
||||||
|
assert!(unknown.iter().any(|k| k == "main.font-sze"), "{unknown:?}");
|
||||||
|
assert!(unknown.iter().any(|k| k == "made-up"), "{unknown:?}");
|
||||||
|
// ...yet the valid key still loaded.
|
||||||
|
assert_eq!(c.main.font, "JetBrains Mono");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue