1use std::path::PathBuf;
4
5use globset::{GlobBuilder, GlobSetBuilder};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum FileKind {
10 File,
12 Directory,
14 Symlink,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum EntryOrigin {
21 Primary,
23 Recovered,
25}
26
27#[derive(Debug, Clone)]
29pub struct FileEntry {
30 pub rel_path: String,
33 pub abs_path: PathBuf,
35 pub kind: FileKind,
37 pub origin: EntryOrigin,
39}
40
41#[derive(Debug, Clone)]
43pub struct FileTree {
44 pub root: PathBuf,
46 pub entries: Vec<FileEntry>,
48}
49
50impl FileTree {
51 #[must_use]
53 pub fn entry(&self, rel_path: &str) -> Option<&FileEntry> {
54 self.entries
55 .binary_search_by(|e| e.rel_path.as_str().cmp(rel_path))
56 .ok()
57 .and_then(|i| self.entries.get(i))
58 }
59
60 #[must_use]
62 pub fn entries_with_origin(&self, origin: EntryOrigin) -> Vec<&FileEntry> {
63 self.entries.iter().filter(|e| e.origin == origin).collect()
64 }
65
66 pub fn glob(
73 &self,
74 pattern: &str,
75 case_sensitive: bool,
76 ) -> Result<Vec<&FileEntry>, globset::Error> {
77 let glob = GlobBuilder::new(pattern)
78 .case_insensitive(!case_sensitive)
79 .literal_separator(false)
80 .build()?;
81 let mut builder = GlobSetBuilder::new();
82 let _ = builder.add(glob);
83 let set = builder.build()?;
84 Ok(self
85 .entries
86 .iter()
87 .filter(|e| set.is_match(&e.rel_path))
88 .collect())
89 }
90}