Skip to content

Commit ccc1068

Browse files
committed
feat(cosmic_config): add ConfigGet::get_{local,system_default}
Required by pop-os/cosmic-settings#975 to a modify a config containing a HashMap which is used to partially-override the system default config in the compositor.
1 parent 0b7e234 commit ccc1068

File tree

1 file changed

+46
-14
lines changed

1 file changed

+46
-14
lines changed

cosmic-config/src/lib.rs

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub enum Error {
3333
Io(std::io::Error),
3434
NoConfigDirectory,
3535
Notify(notify::Error),
36+
NotFound,
3637
Ron(ron::Error),
3738
RonSpanned(ron::error::SpannedError),
3839
GetKey(String, std::io::Error),
@@ -46,6 +47,7 @@ impl fmt::Display for Error {
4647
Self::Io(err) => err.fmt(f),
4748
Self::NoConfigDirectory => write!(f, "cosmic config directory not found"),
4849
Self::Notify(err) => err.fmt(f),
50+
Self::NotFound => write!(f, "cosmic config key not configured"),
4951
Self::Ron(err) => err.fmt(f),
5052
Self::RonSpanned(err) => err.fmt(f),
5153
Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err),
@@ -55,6 +57,15 @@ impl fmt::Display for Error {
5557

5658
impl std::error::Error for Error {}
5759

60+
impl Error {
61+
/// Whether the reason for the missing config is caused by an error.
62+
///
63+
/// Useful for determining if it is appropriate to log as an error.
64+
pub fn is_err(&self) -> bool {
65+
matches!(self, Self::NoConfigDirectory | Self::NotFound)
66+
}
67+
}
68+
5869
impl From<atomicwrites::Error<std::io::Error>> for Error {
5970
fn from(f: atomicwrites::Error<std::io::Error>) -> Self {
6071
Self::AtomicWrites(f)
@@ -87,7 +98,15 @@ impl From<ron::error::SpannedError> for Error {
8798

8899
pub trait ConfigGet {
89100
/// Get a configuration value
101+
///
102+
/// Fallback to the system default if a local user override is not defined.
90103
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
104+
105+
/// Get a locally-defined configuration value from the user's local config.
106+
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
107+
108+
/// Get the system-defined default configuration value.
109+
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
91110
}
92111

93112
pub trait ConfigSet {
@@ -216,7 +235,7 @@ impl Config {
216235
}
217236

218237
// Start a transaction (to set multiple configs at the same time)
219-
pub fn transaction<'a>(&'a self) -> ConfigTransaction<'a> {
238+
pub fn transaction(&self) -> ConfigTransaction {
220239
ConfigTransaction {
221240
config: self,
222241
updates: Mutex::new(Vec::new()),
@@ -288,6 +307,7 @@ impl Config {
288307
Ok(system_path.join(sanitize_name(key)?))
289308
}
290309

310+
/// Get the path of the key in the user's local config directory.
291311
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
292312
let Some(user_path) = self.user_path.as_ref() else {
293313
return Err(Error::NoConfigDirectory);
@@ -300,22 +320,34 @@ impl Config {
300320
impl ConfigGet for Config {
301321
//TODO: check for transaction
302322
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
323+
match self.get_local(key) {
324+
Ok(value) => Ok(value),
325+
Err(Error::NotFound) => self.get_system_default(key),
326+
Err(why) => Err(why),
327+
}
328+
}
329+
330+
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
303331
// If key path exists
304-
let key_path = self.key_path(key);
305-
let data = match key_path {
306-
Ok(key_path) if key_path.is_file() => {
332+
match self.key_path(key)? {
333+
key_path if key_path.is_file() => {
307334
// Load user override
308-
fs::read_to_string(key_path).map_err(|err| Error::GetKey(key.to_string(), err))?
309-
}
310-
_ => {
311-
// Load system default
312-
let default_path = self.default_path(key)?;
313-
fs::read_to_string(default_path)
314-
.map_err(|err| Error::GetKey(key.to_string(), err))?
335+
let data = fs::read_to_string(key_path)
336+
.map_err(|err| Error::GetKey(key.to_string(), err))?;
337+
338+
Ok(ron::from_str(&data)?)
315339
}
316-
};
317-
let t = ron::from_str(&data)?;
318-
Ok(t)
340+
341+
_ => Err(Error::NotFound),
342+
}
343+
}
344+
345+
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
346+
// Load system default
347+
let default_path = self.default_path(key)?;
348+
let data =
349+
fs::read_to_string(default_path).map_err(|err| Error::GetKey(key.to_string(), err))?;
350+
Ok(ron::from_str(&data)?)
319351
}
320352
}
321353

0 commit comments

Comments
 (0)