feat(config): support for fallback to previous config version
This commit is contained in:
parent
a44cff8011
commit
bec679efc9
1 changed files with 57 additions and 3 deletions
|
|
@ -162,6 +162,7 @@ pub trait ConfigSet {
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
system_path: Option<PathBuf>,
|
system_path: Option<PathBuf>,
|
||||||
user_path: Option<PathBuf>,
|
user_path: Option<PathBuf>,
|
||||||
|
previous: Option<Box<Config>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that the name is relative and doesn't contain . or ..
|
/// Check that the name is relative and doesn't contain . or ..
|
||||||
|
|
@ -180,9 +181,13 @@ fn sanitize_name(name: &str) -> Result<&Path, Error> {
|
||||||
impl Config {
|
impl Config {
|
||||||
/// Get a system config for the given name and config version
|
/// Get a system config for the given name and config version
|
||||||
pub fn system(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn system(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::system_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn system_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
let path = sanitize_name(name)?.join(format!("v{version}"));
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(path);
|
let system_path = xdg::BaseDirectories::with_prefix("cosmic").find_data_file(&path);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let system_path =
|
let system_path =
|
||||||
|
|
@ -192,6 +197,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path,
|
system_path,
|
||||||
user_path: None,
|
user_path: None,
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::system_inner(name, version - 1, false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,6 +211,10 @@ impl Config {
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
// Use folder at XDG config/name for config storage, return Config if successful
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||||
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::new_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
|
|
||||||
|
|
@ -223,15 +239,29 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path,
|
system_path,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::new_inner(name, version - 1, false).ok().map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get config for the given application name and config version and custom path.
|
/// Get config for the given application name and config version and custom path.
|
||||||
pub fn with_custom_path(name: &str, version: u64, custom_path: PathBuf) -> Result<Self, Error> {
|
pub fn with_custom_path(name: &str, version: u64, custom_path: PathBuf) -> Result<Self, Error> {
|
||||||
|
Self::with_custom_path_inner(name, version, custom_path, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_custom_path_inner(
|
||||||
|
name: &str,
|
||||||
|
version: u64,
|
||||||
|
custom_path: PathBuf,
|
||||||
|
look_for_previous: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{version}"));
|
let path = sanitize_name(name)?.join(format!("v{version}"));
|
||||||
|
|
||||||
let mut user_path = custom_path;
|
let mut user_path = custom_path.clone();
|
||||||
user_path.push("cosmic");
|
user_path.push("cosmic");
|
||||||
user_path.push(path);
|
user_path.push(path);
|
||||||
// Create new configuration directory if not found.
|
// Create new configuration directory if not found.
|
||||||
|
|
@ -241,6 +271,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path: None,
|
system_path: None,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::with_custom_path_inner(name, version - 1, custom_path.clone(), false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,6 +287,10 @@ impl Config {
|
||||||
// Use folder at XDG config/name for config storage, return Config if successful
|
// Use folder at XDG config/name for config storage, return Config if successful
|
||||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||||
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
||||||
|
Self::new_state_inner(name, version, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_state_inner(name: &str, version: u64, look_for_previous: bool) -> Result<Self, Error> {
|
||||||
// Look for [name]/v[version]
|
// Look for [name]/v[version]
|
||||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
|
|
||||||
|
|
@ -263,6 +304,13 @@ impl Config {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
system_path: None,
|
system_path: None,
|
||||||
user_path: Some(user_path),
|
user_path: Some(user_path),
|
||||||
|
previous: if version > 1 && look_for_previous {
|
||||||
|
Self::new_state_inner(name, version - 1, false)
|
||||||
|
.ok()
|
||||||
|
.map(Box::new)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,7 +421,13 @@ impl ConfigGet for Config {
|
||||||
Ok(ron::from_str(&data)?)
|
Ok(ron::from_str(&data)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => Err(Error::NotFound),
|
_ => {
|
||||||
|
if let Some(previous) = self.previous.as_ref() {
|
||||||
|
previous.get_local(key)
|
||||||
|
} else {
|
||||||
|
Err(Error::NotFound)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue