heroforge_core/repo/builders/
files.rs1use crate::error::{FossilError, Result};
4use crate::repo::{FileInfo, Repository};
5
6#[derive(Clone)]
8enum QueryTarget {
9 Trunk,
10 Branch(String),
11 Tag(String),
12 Commit(String),
13}
14
15pub struct FilesBuilder<'a> {
17 repo: &'a Repository,
18}
19
20impl<'a> FilesBuilder<'a> {
21 pub(crate) fn new(repo: &'a Repository) -> Self {
22 Self { repo }
23 }
24
25 pub fn on_trunk(self) -> FileQuery<'a> {
27 FileQuery {
28 repo: self.repo,
29 target: QueryTarget::Trunk,
30 directory: None,
31 }
32 }
33
34 pub fn on_branch(self, name: &str) -> FileQuery<'a> {
36 FileQuery {
37 repo: self.repo,
38 target: QueryTarget::Branch(name.to_string()),
39 directory: None,
40 }
41 }
42
43 pub fn at_tag(self, name: &str) -> FileQuery<'a> {
45 FileQuery {
46 repo: self.repo,
47 target: QueryTarget::Tag(name.to_string()),
48 directory: None,
49 }
50 }
51
52 pub fn at_commit(self, hash: &str) -> FileQuery<'a> {
54 FileQuery {
55 repo: self.repo,
56 target: QueryTarget::Commit(hash.to_string()),
57 directory: None,
58 }
59 }
60}
61
62pub struct FileQuery<'a> {
64 repo: &'a Repository,
65 target: QueryTarget,
66 directory: Option<String>,
67}
68
69impl<'a> FileQuery<'a> {
70 fn resolve_hash(&self) -> Result<String> {
72 match &self.target {
73 QueryTarget::Trunk => {
74 let tip = self.repo.database().get_trunk_tip()?;
75 self.repo.database().get_hash_by_rid(tip)
76 }
77 QueryTarget::Branch(name) => {
78 let tip = self.repo.database().get_branch_tip(name)?;
79 self.repo.database().get_hash_by_rid(tip)
80 }
81 QueryTarget::Tag(name) => self.repo.get_tag_checkin_internal(name),
82 QueryTarget::Commit(hash) => Ok(hash.clone()),
83 }
84 }
85
86 pub fn in_dir(mut self, dir: &str) -> Self {
88 self.directory = Some(dir.to_string());
89 self
90 }
91
92 pub fn list(&self) -> Result<Vec<FileInfo>> {
94 let hash = self.resolve_hash()?;
95 if let Some(dir) = &self.directory {
96 self.repo.list_directory_internal(&hash, dir)
97 } else {
98 self.repo.list_files_internal(&hash)
99 }
100 }
101
102 pub fn find(&self, pattern: &str) -> Result<Vec<FileInfo>> {
104 let hash = self.resolve_hash()?;
105 self.repo.find_files_internal(&hash, pattern)
106 }
107
108 pub fn read(&self, path: &str) -> Result<Vec<u8>> {
110 let hash = self.resolve_hash()?;
111 self.repo.read_file_internal(&hash, path)
112 }
113
114 pub fn read_string(&self, path: &str) -> Result<String> {
116 let content = self.read(path)?;
117 String::from_utf8(content).map_err(|e| FossilError::InvalidArtifact(e.to_string()))
118 }
119
120 pub fn subdirs(&self, dir: &str) -> Result<Vec<String>> {
122 let hash = self.resolve_hash()?;
123 self.repo.list_subdirs_internal(&hash, dir)
124 }
125}