dot_over/overlays/
repository.rs

1use std::path::PathBuf;
2
3use globset::GlobBuilder;
4use serde::Serialize;
5use walkdir::WalkDir;
6
7use anyhow::Result;
8
9use super::overlay::Overlay;
10use super::pattern;
11
12/// Manage all overlays
13#[derive(Debug, Default, Serialize, Clone)]
14pub struct Repository {
15    /// Repository root directory
16    pub root: PathBuf,
17}
18
19// impl std::fmt::Display for Repository {
20//     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21//         std::fmt::Display::fmt(&self.root.display(), f)
22//     }
23// }
24
25impl Repository {
26    pub fn new(root: PathBuf) -> Self {
27        Self { root }
28    }
29
30    /// Returns a list of all overlays in the repository
31    pub fn overlays(&self) -> Result<Vec<Overlay>> {
32        let glob = GlobBuilder::new(&pattern())
33            .literal_separator(true)
34            .build()?
35            .compile_matcher();
36
37        let mut dirs: Vec<PathBuf> = WalkDir::new(&self.root)
38            .into_iter()
39            .filter_map(Result::ok)
40            .filter(|e| glob.is_match(e.path().strip_prefix(&self.root).ok().unwrap()))
41            .map(|e| e.path().parent().unwrap().to_path_buf())
42            .collect();
43
44        dirs.sort();
45
46        Ok(dirs
47            .iter()
48            .enumerate()
49            .filter_map(|(idx, dir)| match dirs.get(idx + 1) {
50                Some(next) if next.starts_with(dir) => None,
51                _ => Some(Overlay::new(self, dir).expect("failed")),
52            })
53            .collect())
54    }
55
56    /// Get a repository by its name/relative path
57    pub fn get(&self, name: &str) -> Result<Overlay> {
58        let root = self.root.join(name);
59        let overlay = Overlay::new(self, &root)?;
60        Ok(overlay)
61    }
62}