Compare commits

..

2 Commits

Author SHA1 Message Date
c29e37c03e fix: use XDG data directory as default storage location
Changes default from ~/.keep to /keep
(e.g. ~/.local/share/keep on Linux). Uses dirs::data_dir() which
respects XDG_DATA_HOME environment variable.
2026-03-17 15:37:25 -03:00
28c3deaeca fix: expand tilde (~) in config file paths to home directory
Applies to dir, import_data_file, and all server certificate/secret file
paths. Uses existing dirs crate for home directory resolution.
2026-03-17 15:32:30 -03:00

View File

@@ -4,7 +4,7 @@ use dirs;
use log::{debug, error}; use log::{debug, error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize, Default)] #[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
@@ -542,6 +542,25 @@ impl Settings {
settings.export_filename_format = args.item.export_filename_format.clone(); settings.export_filename_format = args.item.export_filename_format.clone();
settings.import_data_file = args.item.import_data_file.clone(); settings.import_data_file = args.item.import_data_file.clone();
// Expand ~ in all path fields
settings.dir = Settings::expand_tilde(&settings.dir);
settings.import_data_file = settings
.import_data_file
.as_ref()
.map(|p| Settings::expand_tilde(p));
if let Some(ref mut server) = settings.server {
server.password_file = server
.password_file
.as_ref()
.map(|p| Settings::expand_tilde(p));
server.jwt_secret_file = server
.jwt_secret_file
.as_ref()
.map(|p| Settings::expand_tilde(p));
server.cert_file = server.cert_file.as_ref().map(|p| Settings::expand_tilde(p));
server.key_file = server.key_file.as_ref().map(|p| Settings::expand_tilde(p));
}
debug!("CONFIG: Final settings: {settings:?}"); debug!("CONFIG: Final settings: {settings:?}");
Ok(settings) Ok(settings)
} }
@@ -554,14 +573,32 @@ impl Settings {
pub fn default_dir() -> anyhow::Result<PathBuf> { pub fn default_dir() -> anyhow::Result<PathBuf> {
let mut path = let mut path =
dirs::home_dir().ok_or_else(|| anyhow::anyhow!("No home directory found"))?; dirs::data_dir().ok_or_else(|| anyhow::anyhow!("No data directory found"))?;
path.push(".keep"); path.push("keep");
if !path.exists() { if !path.exists() {
std::fs::create_dir_all(&path)?; std::fs::create_dir_all(&path)?;
} }
Ok(path) Ok(path)
} }
/// Expand a leading `~` in a path to the user's home directory.
///
/// Returns the path unchanged if it doesn't start with `~` or if the
/// home directory cannot be determined.
fn expand_tilde(path: &Path) -> PathBuf {
let path_str = path.to_string_lossy();
if let Some(rest) = path_str.strip_prefix("~/") {
if let Some(home) = dirs::home_dir() {
return home.join(rest);
}
} else if path_str == "~" {
if let Some(home) = dirs::home_dir() {
return home;
}
}
path.to_path_buf()
}
/// Get server password from password_file or directly from config if configured /// Get server password from password_file or directly from config if configured
pub fn get_server_password(&self) -> Result<Option<String>> { pub fn get_server_password(&self) -> Result<Option<String>> {
if let Some(server) = &self.server { if let Some(server) = &self.server {
@@ -753,3 +790,35 @@ impl Settings {
.collect() .collect()
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn test_expand_tilde_with_slash() {
let home = dirs::home_dir().unwrap();
let result = Settings::expand_tilde(Path::new("~/foo/bar"));
assert_eq!(result, home.join("foo/bar"));
}
#[test]
fn test_expand_tilde_bare() {
let home = dirs::home_dir().unwrap();
let result = Settings::expand_tilde(Path::new("~"));
assert_eq!(result, home);
}
#[test]
fn test_expand_tilde_absolute() {
let result = Settings::expand_tilde(Path::new("/etc/keep"));
assert_eq!(result, PathBuf::from("/etc/keep"));
}
#[test]
fn test_expand_tilde_relative() {
let result = Settings::expand_tilde(Path::new("foo/bar"));
assert_eq!(result, PathBuf::from("foo/bar"));
}
}