Skip to main content

asimov_directory/fs/
module_directory.rs

1// This is free and unencumbered software released into the public domain.
2
3use super::{ModuleManifestIterator, ModuleNameIterator, StateDirectory};
4use alloc::format;
5use camino::{Utf8Path, Utf8PathBuf};
6use derive_more::Display;
7use std::{
8    io::{Error, ErrorKind, Result},
9    path::Path,
10};
11
12/// A module directory stored on a file system (e.g., `$HOME/.asimov/modules/`).
13#[derive(Debug, Display)]
14#[display("ModuleDirectory({:?})", path)]
15pub struct ModuleDirectory {
16    pub(crate) path: Utf8PathBuf,
17}
18
19impl AsRef<Utf8PathBuf> for ModuleDirectory {
20    fn as_ref(&self) -> &Utf8PathBuf {
21        &self.path
22    }
23}
24
25impl ModuleDirectory {
26    /// Opens the default module directory in the user's home directory.
27    ///
28    /// On Unix platforms, including macOS and Linux, this is `$HOME/.asimov/modules/`.
29    pub fn home() -> Result<Self> {
30        StateDirectory::home().map(|base_dir| base_dir.modules())?
31    }
32
33    /// Opens a module directory from a file system path.
34    pub fn open(path: impl AsRef<Path>) -> Result<Self> {
35        let path = path.as_ref();
36        if !path.exists() {
37            std::fs::create_dir_all(path)?;
38        }
39        let path = Utf8PathBuf::from_path_buf(path.to_path_buf()).map_err(|e| {
40            Error::new(
41                ErrorKind::InvalidFilename,
42                format!("failed to open non-UTF-8 path: {}", e.display()),
43            )
44        })?;
45        Ok(ModuleDirectory { path })
46    }
47
48    pub async fn iter_enabled(&self) -> Result<ModuleNameIterator> {
49        ModuleNameIterator::new(self.join("enabled")).await
50    }
51
52    pub async fn iter_installed(&self) -> Result<ModuleNameIterator> {
53        ModuleNameIterator::new(self.join("installed")).await
54    }
55
56    pub async fn iter_manifests(&self) -> Result<ModuleManifestIterator> {
57        ModuleManifestIterator::new(self.join("installed")).await
58    }
59
60    pub fn join(&self, path: impl AsRef<Utf8Path>) -> Utf8PathBuf {
61        self.path.join(path.as_ref())
62    }
63
64    pub fn as_str(&self) -> &str {
65        self.path.as_str()
66    }
67}
68
69impl AsRef<str> for ModuleDirectory {
70    fn as_ref(&self) -> &str {
71        self.path.as_str()
72    }
73}
74
75impl AsRef<Path> for ModuleDirectory {
76    fn as_ref(&self) -> &Path {
77        self.path.as_std_path()
78    }
79}
80
81#[cfg(feature = "camino")]
82impl AsRef<Utf8Path> for ModuleDirectory {
83    fn as_ref(&self) -> &Utf8Path {
84        self.path.as_path()
85    }
86}
87
88impl crate::ModuleDirectory for ModuleDirectory {
89    fn is_installed(&self, _module_name: impl AsRef<str>) -> bool {
90        false // TODO
91    }
92
93    fn is_enabled(&self, _module_name: impl AsRef<str>) -> bool {
94        false // TODO
95    }
96}