Skip to main content

speakers_core/
paths.rs

1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result};
4
5const APP_NAME: &str = "speakers";
6const LEGACY_APP_NAME: &str = "speake-rs";
7
8fn home_dir() -> PathBuf {
9    std::env::var("HOME")
10        .map(PathBuf::from)
11        .unwrap_or_else(|_| PathBuf::from("."))
12}
13
14pub fn config_home() -> PathBuf {
15    std::env::var("XDG_CONFIG_HOME")
16        .map(PathBuf::from)
17        .unwrap_or_else(|_| home_dir().join(".config"))
18}
19
20pub fn data_home() -> PathBuf {
21    std::env::var("XDG_DATA_HOME")
22        .map(PathBuf::from)
23        .unwrap_or_else(|_| home_dir().join(".local/share"))
24}
25
26pub fn runtime_home() -> PathBuf {
27    std::env::var("XDG_RUNTIME_DIR")
28        .map(PathBuf::from)
29        .unwrap_or_else(|_| PathBuf::from("/tmp"))
30}
31
32pub fn app_config_dir() -> PathBuf {
33    config_home().join(APP_NAME)
34}
35
36pub fn app_data_dir() -> PathBuf {
37    data_home().join(APP_NAME)
38}
39
40pub fn app_runtime_dir() -> PathBuf {
41    runtime_home().join(APP_NAME)
42}
43
44pub fn legacy_app_config_dir() -> PathBuf {
45    config_home().join(LEGACY_APP_NAME)
46}
47
48pub fn legacy_app_data_dir() -> PathBuf {
49    data_home().join(LEGACY_APP_NAME)
50}
51
52pub fn config_path() -> PathBuf {
53    app_config_dir().join("config.toml")
54}
55
56pub fn legacy_config_path() -> PathBuf {
57    legacy_app_config_dir().join("config.toml")
58}
59
60pub fn existing_config_path() -> Option<PathBuf> {
61    let current = config_path();
62    if current.exists() {
63        return Some(current);
64    }
65
66    let legacy = legacy_config_path();
67    legacy.exists().then_some(legacy)
68}
69
70pub fn socket_path() -> PathBuf {
71    app_runtime_dir().join("daemon.sock")
72}
73
74pub fn pid_path() -> PathBuf {
75    app_runtime_dir().join("daemon.pid")
76}
77
78pub fn profiles_dir() -> PathBuf {
79    app_data_dir().join("voices")
80}
81
82pub fn legacy_profiles_dir() -> PathBuf {
83    legacy_app_data_dir().join("voices")
84}
85
86pub fn ensure_parent(path: &Path) -> Result<()> {
87    let parent = path
88        .parent()
89        .with_context(|| format!("path has no parent: {}", path.display()))?;
90    std::fs::create_dir_all(parent)
91        .with_context(|| format!("failed to create directory: {}", parent.display()))
92}
93
94pub fn ensure_runtime_dir() -> Result<PathBuf> {
95    let dir = app_runtime_dir();
96    std::fs::create_dir_all(&dir)
97        .with_context(|| format!("failed to create runtime dir: {}", dir.display()))?;
98    Ok(dir)
99}
100
101pub fn ensure_profiles_dir() -> Result<PathBuf> {
102    let dir = profiles_dir();
103    std::fs::create_dir_all(&dir)
104        .with_context(|| format!("failed to create profiles dir: {}", dir.display()))?;
105    Ok(dir)
106}