aboutsummaryrefslogtreecommitdiff
path: root/mling/src/namespace_manager.rs
blob: d5176ddc60f6d730a9a1da67bc0fcbcd607cc9b8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::path::PathBuf;

use just_fmt::kebab_case;

#[must_use]
pub fn list_namespaces(
    show_trusted: bool,
    show_untrusted: bool,
    show_untagged: bool,
) -> Vec<String> {
    let wdir = working_dir();
    if !wdir.exists() {
        return Vec::new();
    }

    let mut namespaces = Vec::new();
    let Ok(entries) = std::fs::read_dir(&wdir) else {
        return Vec::new();
    };
    for entry in entries {
        let Ok(entry) = entry else {
            continue;
        };
        let path = entry.path();
        if path.is_dir()
            && let Some(name) = path.file_name()
            && let Some(name_str) = name.to_str()
        {
            // Skip directories starting with a dot
            if name_str.starts_with('.') {
                continue;
            }
            let namespace = name_str.to_string();
            let is_trusted = is_trusted_namespace(namespace.clone());
            let is_untrusted = is_untrusted_namespace(namespace.clone());
            let is_untagged = is_untagged_namespace(namespace.clone());

            if (show_trusted && is_trusted)
                || (show_untrusted && is_untrusted)
                || (show_untagged && is_untagged)
            {
                namespaces.push(namespace);
            }
        }
    }

    namespaces
}

pub fn set_namespace_trusted(namespace: String, trusted: bool) {
    let ndir = namespace_dir(namespace);
    let trusted_file = ndir.join("TRUSTED");
    let untrusted_file = ndir.join("UNTRUSTED");

    if trusted {
        // Create TRUSTED file and remove UNTRUSTED if it exists
        let _ = std::fs::write(&trusted_file, "");
        let _ = std::fs::remove_file(&untrusted_file);
    } else {
        // Create UNTRUSTED file and remove TRUSTED if it exists
        let _ = std::fs::write(&untrusted_file, "");
        let _ = std::fs::remove_file(&trusted_file);
    }
}

pub fn remove_namespace(namespace: String) {
    let ndir = namespace_dir(namespace);
    if ndir.exists() {
        let _ = std::fs::remove_dir_all(&ndir);
    }
}

/// Returns the mingling data directory.
///
/// # Panics
///
/// Panics if the platform's data directory cannot be determined.
#[must_use]
pub fn working_dir() -> PathBuf {
    dirs::data_dir().unwrap().join("mingling")
}

#[must_use]
pub fn namespace_dir(namespace: String) -> PathBuf {
    working_dir().join(kebab_case!(namespace))
}

#[must_use]
pub fn is_untrusted_namespace(namespace: String) -> bool {
    let untrusted_file = namespace_dir(namespace).join("UNTRUSTED");
    untrusted_file.exists()
}

#[must_use]
pub fn is_trusted_namespace(namespace: String) -> bool {
    let trusted = namespace_dir(namespace).join("TRUSTED");
    trusted.exists()
}

#[must_use]
pub fn is_untagged_namespace(namespace: String) -> bool {
    let ndir = namespace_dir(namespace);
    let trusted = ndir.join("TRUSTED");
    let untrusted = ndir.join("UNTRUSTED");
    !trusted.exists() && !untrusted.exists()
}

#[must_use]
pub fn bin_dir(namespace: String) -> PathBuf {
    namespace_dir(namespace).join("bin")
}

#[must_use]
pub fn comp_dir(namespace: String) -> PathBuf {
    namespace_dir(namespace).join("comp")
}

#[must_use]
pub fn exe_path(namespace: String, bin_name_without_ext: String) -> PathBuf {
    if cfg!(target_os = "windows") {
        bin_dir(namespace).join(bin_name_without_ext + ".exe")
    } else {
        bin_dir(namespace).join(bin_name_without_ext)
    }
}