improv(cosmic-config): remove hardcoded paths
This commit changes the hardcoded /usr/share paths in cosmic-config to become performed via XDG lookups using the `xdg` crate. This allows the installed files to be discovered on non-FHS Linux, e.g. NixOS. Hardcoded /var/lib/ is removed entirely because 1. nothing installs to it yet (only user of new_state is cosmic_bg currently and it does not install to /var/lib) 2. it's intended for system states, not template for user state. 3. it's not part of XDG spec. On Windows the known folder crate is used. Signed-off-by: Gary Guo <gary@garyguo.net>
This commit is contained in:
parent
912e8b0a44
commit
3aef16bf9e
2 changed files with 59 additions and 59 deletions
|
|
@ -10,7 +10,6 @@ macro = ["cosmic-config-derive"]
|
||||||
subscription = ["iced_futures"]
|
subscription = ["iced_futures"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# For redox support
|
|
||||||
zbus = { version = "3.14.1", default-features = false, optional = true }
|
zbus = { version = "3.14.1", default-features = false, optional = true }
|
||||||
atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" }
|
atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" }
|
||||||
calloop = { version = "0.12.2", optional = true }
|
calloop = { version = "0.12.2", optional = true }
|
||||||
|
|
@ -24,3 +23,9 @@ iced_futures = { path = "../iced/futures/", default-features = false, optional =
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings", branch = "cosmic-settings-daemon", optional = true }
|
cosmic-settings-daemon = { git = "https://github.com/pop-os/dbus-settings-bindings", branch = "cosmic-settings-daemon", optional = true }
|
||||||
futures-util = { version = "0.3", optional = true }
|
futures-util = { version = "0.3", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
xdg = "2.1"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
known-folders = "1.1.0"
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,23 @@ pub trait ConfigSet {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
system_path: PathBuf,
|
system_path: Option<PathBuf>,
|
||||||
user_path: PathBuf,
|
user_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check that the name is relative and doesn't contain . or ..
|
||||||
|
fn sanitize_name(name: &str) -> Result<&Path, Error> {
|
||||||
|
let path = Path::new(name);
|
||||||
|
if path
|
||||||
|
.components()
|
||||||
|
.all(|x| matches!(x, std::path::Component::Normal(_)))
|
||||||
|
{
|
||||||
|
Ok(path)
|
||||||
|
} else {
|
||||||
|
Err(Error::InvalidName(name.to_owned()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// Get the config for the libcosmic toolkit
|
/// Get the config for the libcosmic toolkit
|
||||||
pub fn libcosmic() -> Result<Self, Error> {
|
pub fn libcosmic() -> Result<Self, Error> {
|
||||||
|
|
@ -108,33 +121,34 @@ 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> {
|
||||||
// Get libcosmic system defaults path
|
// Look for [name]/v[version]
|
||||||
//TODO: support non-UNIX OS
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
let cosmic_system_path = Path::new("/usr/share/cosmic");
|
|
||||||
// Append [name]/v[version]
|
// Search data file, which provides default (e.g. /usr/share)
|
||||||
let system_path = cosmic_system_path.join(name).join(format!("v{}", version));
|
#[cfg(unix)]
|
||||||
|
let system_path = xdg::BaseDirectories::with_prefix("cosmic")
|
||||||
|
.map_err(std::io::Error::from)?
|
||||||
|
.find_data_file(&path);
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
let system_path =
|
||||||
|
known_folders::get_known_folder_path(known_folders::KnownFolder::ProgramFilesCommon)
|
||||||
|
.map(|x| x.join("COSMIC").join(&path));
|
||||||
|
|
||||||
// Get libcosmic user configuration directory
|
// Get libcosmic user configuration directory
|
||||||
let cosmic_user_path = dirs::config_dir()
|
let cosmic_user_path = dirs::config_dir()
|
||||||
.ok_or(Error::NoConfigDirectory)?
|
.ok_or(Error::NoConfigDirectory)?
|
||||||
.join("cosmic");
|
.join("cosmic");
|
||||||
// Append [name]/v[version]
|
|
||||||
let user_path = cosmic_user_path.join(name).join(format!("v{}", version));
|
|
||||||
|
|
||||||
// If the app paths are children of the cosmic paths
|
let user_path = cosmic_user_path.join(path);
|
||||||
if system_path.starts_with(&cosmic_system_path) && user_path.starts_with(&cosmic_user_path)
|
// Create new configuration directory if not found.
|
||||||
{
|
fs::create_dir_all(&user_path)?;
|
||||||
// Create app user path
|
|
||||||
fs::create_dir_all(&user_path)?;
|
// Return Config
|
||||||
// Return Config
|
Ok(Self {
|
||||||
Ok(Self {
|
system_path,
|
||||||
system_path,
|
user_path,
|
||||||
user_path,
|
})
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// Return error for invalid name
|
|
||||||
Err(Error::InvalidName(name.to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get state for the given application name and config version. State is meant to be used to
|
/// Get state for the given application name and config version. State is meant to be used to
|
||||||
|
|
@ -143,33 +157,22 @@ 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> {
|
||||||
// Get libcosmic system defaults path
|
// Look for [name]/v[version]
|
||||||
//TODO: support non-UNIX OS
|
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||||
let cosmic_system_path = Path::new("/var/lib/cosmic");
|
|
||||||
// Append [name]/v[version]
|
|
||||||
let system_path = cosmic_system_path.join(name).join(format!("v{}", version));
|
|
||||||
|
|
||||||
// Get libcosmic user configuration directory
|
// Get libcosmic user state directory
|
||||||
let cosmic_user_path = dirs::state_dir()
|
let cosmic_user_path = dirs::state_dir()
|
||||||
.ok_or(Error::NoConfigDirectory)?
|
.ok_or(Error::NoConfigDirectory)?
|
||||||
.join("cosmic");
|
.join("cosmic");
|
||||||
// Append [name]/v[version]
|
|
||||||
let user_path = cosmic_user_path.join(name).join(format!("v{}", version));
|
|
||||||
|
|
||||||
// If the app paths are children of the cosmic paths
|
let user_path = cosmic_user_path.join(path);
|
||||||
if system_path.starts_with(&cosmic_system_path) && user_path.starts_with(&cosmic_user_path)
|
// Create new state directory if not found.
|
||||||
{
|
fs::create_dir_all(&user_path)?;
|
||||||
// Create app user path
|
|
||||||
fs::create_dir_all(&user_path)?;
|
Ok(Self {
|
||||||
// Return Config
|
system_path: None,
|
||||||
Ok(Self {
|
user_path,
|
||||||
system_path,
|
})
|
||||||
user_path,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// Return error for invalid name
|
|
||||||
Err(Error::InvalidName(name.to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a transaction (to set multiple configs at the same time)
|
// Start a transaction (to set multiple configs at the same time)
|
||||||
|
|
@ -238,23 +241,15 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_path(&self, key: &str) -> Result<PathBuf, Error> {
|
fn default_path(&self, key: &str) -> Result<PathBuf, Error> {
|
||||||
let default_path = self.system_path.join(key);
|
let Some(system_path) = self.system_path.as_ref() else {
|
||||||
// Ensure key path is a direct child of config directory
|
return Err(Error::NoConfigDirectory);
|
||||||
if default_path.parent() == Some(&self.system_path) {
|
};
|
||||||
Ok(default_path)
|
|
||||||
} else {
|
Ok(system_path.join(sanitize_name(key)?))
|
||||||
Err(Error::InvalidName(key.to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
||||||
let key_path = self.user_path.join(key);
|
Ok(self.user_path.join(sanitize_name(key)?))
|
||||||
// Ensure key path is a direct child of config directory
|
|
||||||
if key_path.parent() == Some(&self.user_path) {
|
|
||||||
Ok(key_path)
|
|
||||||
} else {
|
|
||||||
Err(Error::InvalidName(key.to_string()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue