spotify_cli/storage/
paths.rs

1use std::path::PathBuf;
2use thiserror::Error;
3
4use crate::constants::{APP_DIR_NAME, CONFIG_FILENAME, TOKEN_FILENAME};
5
6#[derive(Debug, Error)]
7pub enum PathError {
8    #[error("Could not determine home directory")]
9    NoHomeDir,
10}
11
12pub fn config_dir() -> Result<PathBuf, PathError> {
13    #[cfg(target_os = "windows")]
14    {
15        dirs::config_dir()
16            .map(|p| p.join(APP_DIR_NAME))
17            .ok_or(PathError::NoHomeDir)
18    }
19
20    #[cfg(not(target_os = "windows"))]
21    {
22        // Use XDG (~/.config) for both Linux and macOS
23        dirs::home_dir()
24            .map(|p| p.join(".config").join(APP_DIR_NAME))
25            .ok_or(PathError::NoHomeDir)
26    }
27}
28
29pub fn config_file() -> Result<PathBuf, PathError> {
30    config_dir().map(|p| p.join(CONFIG_FILENAME))
31}
32
33pub fn token_file() -> Result<PathBuf, PathError> {
34    config_dir().map(|p| p.join(TOKEN_FILENAME))
35}
36
37pub fn socket_file() -> Result<PathBuf, PathError> {
38    config_dir().map(|p| p.join("daemon.sock"))
39}
40
41pub fn pid_file() -> Result<PathBuf, PathError> {
42    config_dir().map(|p| p.join("daemon.pid"))
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn config_dir_ends_with_app_name() {
51        let dir = config_dir().unwrap();
52        assert!(dir.ends_with(APP_DIR_NAME));
53    }
54
55    #[test]
56    fn config_file_is_toml() {
57        let path = config_file().unwrap();
58        assert_eq!(path.extension().unwrap(), "toml");
59    }
60
61    #[test]
62    fn token_file_is_json() {
63        let path = token_file().unwrap();
64        assert_eq!(path.extension().unwrap(), "json");
65    }
66
67    #[cfg(not(target_os = "windows"))]
68    #[test]
69    fn unix_uses_xdg_config() {
70        let dir = config_dir().unwrap();
71        assert!(dir.to_string_lossy().contains(".config"));
72    }
73}