feat(cosmic_config): add ConfigGet::get_{local,system_default}
Required by https://github.com/pop-os/cosmic-settings/pull/975 to a modify a config containing a HashMap which is used to partially-override the system default config in the compositor.
This commit is contained in:
parent
0b7e23444a
commit
ccc1068d9f
1 changed files with 46 additions and 14 deletions
|
|
@ -33,6 +33,7 @@ pub enum Error {
|
||||||
Io(std::io::Error),
|
Io(std::io::Error),
|
||||||
NoConfigDirectory,
|
NoConfigDirectory,
|
||||||
Notify(notify::Error),
|
Notify(notify::Error),
|
||||||
|
NotFound,
|
||||||
Ron(ron::Error),
|
Ron(ron::Error),
|
||||||
RonSpanned(ron::error::SpannedError),
|
RonSpanned(ron::error::SpannedError),
|
||||||
GetKey(String, std::io::Error),
|
GetKey(String, std::io::Error),
|
||||||
|
|
@ -46,6 +47,7 @@ impl fmt::Display for Error {
|
||||||
Self::Io(err) => err.fmt(f),
|
Self::Io(err) => err.fmt(f),
|
||||||
Self::NoConfigDirectory => write!(f, "cosmic config directory not found"),
|
Self::NoConfigDirectory => write!(f, "cosmic config directory not found"),
|
||||||
Self::Notify(err) => err.fmt(f),
|
Self::Notify(err) => err.fmt(f),
|
||||||
|
Self::NotFound => write!(f, "cosmic config key not configured"),
|
||||||
Self::Ron(err) => err.fmt(f),
|
Self::Ron(err) => err.fmt(f),
|
||||||
Self::RonSpanned(err) => err.fmt(f),
|
Self::RonSpanned(err) => err.fmt(f),
|
||||||
Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err),
|
Self::GetKey(key, err) => write!(f, "failed to get key '{}': {}", key, err),
|
||||||
|
|
@ -55,6 +57,15 @@ impl fmt::Display for Error {
|
||||||
|
|
||||||
impl std::error::Error for Error {}
|
impl std::error::Error for Error {}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
/// Whether the reason for the missing config is caused by an error.
|
||||||
|
///
|
||||||
|
/// Useful for determining if it is appropriate to log as an error.
|
||||||
|
pub fn is_err(&self) -> bool {
|
||||||
|
matches!(self, Self::NoConfigDirectory | Self::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<atomicwrites::Error<std::io::Error>> for Error {
|
impl From<atomicwrites::Error<std::io::Error>> for Error {
|
||||||
fn from(f: atomicwrites::Error<std::io::Error>) -> Self {
|
fn from(f: atomicwrites::Error<std::io::Error>) -> Self {
|
||||||
Self::AtomicWrites(f)
|
Self::AtomicWrites(f)
|
||||||
|
|
@ -87,7 +98,15 @@ impl From<ron::error::SpannedError> for Error {
|
||||||
|
|
||||||
pub trait ConfigGet {
|
pub trait ConfigGet {
|
||||||
/// Get a configuration value
|
/// Get a configuration value
|
||||||
|
///
|
||||||
|
/// Fallback to the system default if a local user override is not defined.
|
||||||
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
||||||
|
|
||||||
|
/// Get a locally-defined configuration value from the user's local config.
|
||||||
|
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
||||||
|
|
||||||
|
/// Get the system-defined default configuration value.
|
||||||
|
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ConfigSet {
|
pub trait ConfigSet {
|
||||||
|
|
@ -216,7 +235,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a transaction (to set multiple configs at the same time)
|
// Start a transaction (to set multiple configs at the same time)
|
||||||
pub fn transaction<'a>(&'a self) -> ConfigTransaction<'a> {
|
pub fn transaction(&self) -> ConfigTransaction {
|
||||||
ConfigTransaction {
|
ConfigTransaction {
|
||||||
config: self,
|
config: self,
|
||||||
updates: Mutex::new(Vec::new()),
|
updates: Mutex::new(Vec::new()),
|
||||||
|
|
@ -288,6 +307,7 @@ impl Config {
|
||||||
Ok(system_path.join(sanitize_name(key)?))
|
Ok(system_path.join(sanitize_name(key)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the path of the key in the user's local config directory.
|
||||||
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
||||||
let Some(user_path) = self.user_path.as_ref() else {
|
let Some(user_path) = self.user_path.as_ref() else {
|
||||||
return Err(Error::NoConfigDirectory);
|
return Err(Error::NoConfigDirectory);
|
||||||
|
|
@ -300,22 +320,34 @@ impl Config {
|
||||||
impl ConfigGet for Config {
|
impl ConfigGet for Config {
|
||||||
//TODO: check for transaction
|
//TODO: check for transaction
|
||||||
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
||||||
|
match self.get_local(key) {
|
||||||
|
Ok(value) => Ok(value),
|
||||||
|
Err(Error::NotFound) => self.get_system_default(key),
|
||||||
|
Err(why) => Err(why),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_local<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
||||||
// If key path exists
|
// If key path exists
|
||||||
let key_path = self.key_path(key);
|
match self.key_path(key)? {
|
||||||
let data = match key_path {
|
key_path if key_path.is_file() => {
|
||||||
Ok(key_path) if key_path.is_file() => {
|
|
||||||
// Load user override
|
// Load user override
|
||||||
fs::read_to_string(key_path).map_err(|err| Error::GetKey(key.to_string(), err))?
|
let data = fs::read_to_string(key_path)
|
||||||
|
.map_err(|err| Error::GetKey(key.to_string(), err))?;
|
||||||
|
|
||||||
|
Ok(ron::from_str(&data)?)
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
// Load system default
|
_ => Err(Error::NotFound),
|
||||||
let default_path = self.default_path(key)?;
|
}
|
||||||
fs::read_to_string(default_path)
|
}
|
||||||
.map_err(|err| Error::GetKey(key.to_string(), err))?
|
|
||||||
}
|
fn get_system_default<T: DeserializeOwned>(&self, key: &str) -> Result<T, Error> {
|
||||||
};
|
// Load system default
|
||||||
let t = ron::from_str(&data)?;
|
let default_path = self.default_path(key)?;
|
||||||
Ok(t)
|
let data =
|
||||||
|
fs::read_to_string(default_path).map_err(|err| Error::GetKey(key.to_string(), err))?;
|
||||||
|
Ok(ron::from_str(&data)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue