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"]
|
||||
|
||||
[dependencies]
|
||||
# For redox support
|
||||
zbus = { version = "3.14.1", default-features = false, optional = true }
|
||||
atomicwrites = { git = "https://github.com/jackpot51/rust-atomicwrites" }
|
||||
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"
|
||||
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 }
|
||||
|
||||
[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)]
|
||||
pub struct Config {
|
||||
system_path: PathBuf,
|
||||
system_path: Option<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 {
|
||||
/// Get the config for the libcosmic toolkit
|
||||
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
|
||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||
pub fn new(name: &str, version: u64) -> Result<Self, Error> {
|
||||
// Get libcosmic system defaults path
|
||||
//TODO: support non-UNIX OS
|
||||
let cosmic_system_path = Path::new("/usr/share/cosmic");
|
||||
// Append [name]/v[version]
|
||||
let system_path = cosmic_system_path.join(name).join(format!("v{}", version));
|
||||
// Look for [name]/v[version]
|
||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||
|
||||
// Search data file, which provides default (e.g. /usr/share)
|
||||
#[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
|
||||
let cosmic_user_path = dirs::config_dir()
|
||||
.ok_or(Error::NoConfigDirectory)?
|
||||
.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
|
||||
if system_path.starts_with(&cosmic_system_path) && user_path.starts_with(&cosmic_user_path)
|
||||
{
|
||||
// Create app user path
|
||||
fs::create_dir_all(&user_path)?;
|
||||
// Return Config
|
||||
Ok(Self {
|
||||
system_path,
|
||||
user_path,
|
||||
})
|
||||
} else {
|
||||
// Return error for invalid name
|
||||
Err(Error::InvalidName(name.to_string()))
|
||||
}
|
||||
let user_path = cosmic_user_path.join(path);
|
||||
// Create new configuration directory if not found.
|
||||
fs::create_dir_all(&user_path)?;
|
||||
|
||||
// Return Config
|
||||
Ok(Self {
|
||||
system_path,
|
||||
user_path,
|
||||
})
|
||||
}
|
||||
|
||||
/// 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
|
||||
//TODO: fallbacks for flatpak (HOST_XDG_CONFIG_HOME, xdg-desktop settings proxy)
|
||||
pub fn new_state(name: &str, version: u64) -> Result<Self, Error> {
|
||||
// Get libcosmic system defaults path
|
||||
//TODO: support non-UNIX OS
|
||||
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));
|
||||
// Look for [name]/v[version]
|
||||
let path = sanitize_name(name)?.join(format!("v{}", version));
|
||||
|
||||
// Get libcosmic user configuration directory
|
||||
// Get libcosmic user state directory
|
||||
let cosmic_user_path = dirs::state_dir()
|
||||
.ok_or(Error::NoConfigDirectory)?
|
||||
.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
|
||||
if system_path.starts_with(&cosmic_system_path) && user_path.starts_with(&cosmic_user_path)
|
||||
{
|
||||
// Create app user path
|
||||
fs::create_dir_all(&user_path)?;
|
||||
// Return Config
|
||||
Ok(Self {
|
||||
system_path,
|
||||
user_path,
|
||||
})
|
||||
} else {
|
||||
// Return error for invalid name
|
||||
Err(Error::InvalidName(name.to_string()))
|
||||
}
|
||||
let user_path = cosmic_user_path.join(path);
|
||||
// Create new state directory if not found.
|
||||
fs::create_dir_all(&user_path)?;
|
||||
|
||||
Ok(Self {
|
||||
system_path: None,
|
||||
user_path,
|
||||
})
|
||||
}
|
||||
|
||||
// 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> {
|
||||
let default_path = self.system_path.join(key);
|
||||
// Ensure key path is a direct child of config directory
|
||||
if default_path.parent() == Some(&self.system_path) {
|
||||
Ok(default_path)
|
||||
} else {
|
||||
Err(Error::InvalidName(key.to_string()))
|
||||
}
|
||||
let Some(system_path) = self.system_path.as_ref() else {
|
||||
return Err(Error::NoConfigDirectory);
|
||||
};
|
||||
|
||||
Ok(system_path.join(sanitize_name(key)?))
|
||||
}
|
||||
|
||||
fn key_path(&self, key: &str) -> Result<PathBuf, Error> {
|
||||
let key_path = self.user_path.join(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()))
|
||||
}
|
||||
Ok(self.user_path.join(sanitize_name(key)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue