Skip to main content

upstream_rs/utils/
static_paths.rs

1use dirs;
2use std::path::PathBuf;
3
4/// Root directories for the application
5pub struct AppDirs {
6    pub user_dir: PathBuf,
7    pub config_dir: PathBuf,
8    pub data_dir: PathBuf,
9    pub metadata_dir: PathBuf,
10}
11
12impl Default for AppDirs {
13    fn default() -> Self {
14        Self::new()
15    }
16}
17
18impl AppDirs {
19    pub fn new() -> Self {
20        let user_dir = dirs::home_dir().unwrap();
21        let config_dir = dirs::config_dir().unwrap().join("upstream");
22
23        let data_dir = user_dir.join(".upstream");
24        let metadata_dir = data_dir.join("metadata");
25
26        Self {
27            user_dir,
28            config_dir,
29            data_dir,
30            metadata_dir,
31        }
32    }
33}
34
35/// Paths to configuration and metadata files
36pub struct ConfigPaths {
37    pub config_file: PathBuf,
38    pub packages_file: PathBuf,
39    pub paths_file: PathBuf,
40}
41
42impl ConfigPaths {
43    pub fn new(dirs: &AppDirs) -> Self {
44        Self {
45            config_file: dirs.config_dir.join("config.toml"),
46            packages_file: dirs.metadata_dir.join("packages.json"),
47            paths_file: dirs.metadata_dir.join("paths.sh"),
48        }
49    }
50}
51
52/// Directories where packages are installed
53pub struct InstallPaths {
54    pub appimages_dir: PathBuf,
55    pub binaries_dir: PathBuf,
56    pub archives_dir: PathBuf,
57}
58
59impl InstallPaths {
60    pub fn new(dirs: &AppDirs) -> Self {
61        Self {
62            appimages_dir: dirs.data_dir.join("appimages"),
63            binaries_dir: dirs.data_dir.join("binaries"),
64            archives_dir: dirs.data_dir.join("archives"),
65        }
66    }
67}
68
69/// Paths for system integration (symlinks, XDG dirs)
70pub struct IntegrationPaths {
71    pub symlinks_dir: PathBuf,
72    pub xdg_applications_dir: PathBuf,
73    pub icons_dir: PathBuf,
74}
75
76impl IntegrationPaths {
77    pub fn new(dirs: &AppDirs) -> Self {
78        Self {
79            symlinks_dir: dirs.data_dir.join("symlinks"),
80            icons_dir: dirs.data_dir.join("icons"),
81            xdg_applications_dir: dirs.user_dir.join(".local/share/applications"),
82        }
83    }
84}
85
86/// Convenience wrapper that holds all path types
87pub struct UpstreamPaths {
88    pub dirs: AppDirs,
89    pub config: ConfigPaths,
90    pub install: InstallPaths,
91    pub integration: IntegrationPaths,
92}
93
94impl Default for UpstreamPaths {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100impl UpstreamPaths {
101    pub fn new() -> Self {
102        let dirs = AppDirs::new();
103        Self {
104            config: ConfigPaths::new(&dirs),
105            install: InstallPaths::new(&dirs),
106            integration: IntegrationPaths::new(&dirs),
107            dirs,
108        }
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::UpstreamPaths;
115
116    #[test]
117    fn upstream_paths_are_composed_from_base_directories() {
118        let paths = UpstreamPaths::new();
119
120        assert_eq!(
121            paths.config.config_file,
122            paths.dirs.config_dir.join("config.toml")
123        );
124        assert_eq!(
125            paths.config.packages_file,
126            paths.dirs.metadata_dir.join("packages.json")
127        );
128        assert_eq!(
129            paths.install.binaries_dir,
130            paths.dirs.data_dir.join("binaries")
131        );
132        assert_eq!(
133            paths.integration.symlinks_dir,
134            paths.dirs.data_dir.join("symlinks")
135        );
136    }
137}