Skip to main content

tar_install/
paths.rs

1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::env;
4use std::path::PathBuf;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "kebab-case")]
8pub enum InstallScope {
9    User,
10    System,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct InstallTargets {
15    pub scope: InstallScope,
16    pub app_id: String,
17    pub command_name: String,
18    pub app_dir: PathBuf,
19    pub command_path: PathBuf,
20    pub desktop_path: PathBuf,
21    pub icon_dir: PathBuf,
22    pub state_path: PathBuf,
23}
24
25pub fn home_dir() -> Result<PathBuf> {
26    env::var_os("HOME")
27        .map(PathBuf::from)
28        .context("HOME is not set; cannot resolve user install directories")
29}
30
31fn xdg_data_home() -> Result<PathBuf> {
32    Ok(env::var_os("XDG_DATA_HOME")
33        .map(PathBuf::from)
34        .unwrap_or(home_dir()?.join(".local/share")))
35}
36
37fn xdg_state_home() -> Result<PathBuf> {
38    Ok(env::var_os("XDG_STATE_HOME")
39        .map(PathBuf::from)
40        .unwrap_or(home_dir()?.join(".local/state")))
41}
42
43pub fn targets(scope: InstallScope, app_id: &str, command_name: &str) -> Result<InstallTargets> {
44    let cleaned_id = crate::recipe::sanitize_id(app_id);
45    let cleaned_cmd = crate::recipe::sanitize_command(command_name);
46
47    let t = match scope {
48        InstallScope::User => {
49            let data = xdg_data_home()?;
50            let state = xdg_state_home()?;
51            InstallTargets {
52                scope,
53                app_id: cleaned_id.clone(),
54                command_name: cleaned_cmd.clone(),
55                app_dir: data.join("tarapp/apps").join(&cleaned_id),
56                command_path: home_dir()?.join(".local/bin").join(&cleaned_cmd),
57                desktop_path: data.join("applications").join(format!("{}.desktop", cleaned_id)),
58                icon_dir: data.join("icons/hicolor/256x256/apps"),
59                state_path: state.join("tarapp/apps.json"),
60            }
61        }
62        InstallScope::System => InstallTargets {
63            scope,
64            app_id: cleaned_id.clone(),
65            command_name: cleaned_cmd.clone(),
66            app_dir: PathBuf::from("/opt").join(&cleaned_id),
67            command_path: PathBuf::from("/usr/local/bin").join(&cleaned_cmd),
68            desktop_path: PathBuf::from("/usr/share/applications").join(format!("{}.desktop", cleaned_id)),
69            icon_dir: PathBuf::from("/usr/share/icons/hicolor/256x256/apps"),
70            state_path: PathBuf::from("/var/lib/tarapp/apps.json"),
71        },
72    };
73
74    Ok(t)
75}