use crate::error::{FossilError, Result};
use crate::repo::{FileInfo, Repository};
#[derive(Clone)]
enum QueryTarget {
Trunk,
Branch(String),
Tag(String),
Commit(String),
}
pub struct FilesBuilder<'a> {
repo: &'a Repository,
}
impl<'a> FilesBuilder<'a> {
pub(crate) fn new(repo: &'a Repository) -> Self {
Self { repo }
}
pub fn on_trunk(self) -> FileQuery<'a> {
FileQuery {
repo: self.repo,
target: QueryTarget::Trunk,
directory: None,
}
}
pub fn on_branch(self, name: &str) -> FileQuery<'a> {
FileQuery {
repo: self.repo,
target: QueryTarget::Branch(name.to_string()),
directory: None,
}
}
pub fn at_tag(self, name: &str) -> FileQuery<'a> {
FileQuery {
repo: self.repo,
target: QueryTarget::Tag(name.to_string()),
directory: None,
}
}
pub fn at_commit(self, hash: &str) -> FileQuery<'a> {
FileQuery {
repo: self.repo,
target: QueryTarget::Commit(hash.to_string()),
directory: None,
}
}
}
pub struct FileQuery<'a> {
repo: &'a Repository,
target: QueryTarget,
directory: Option<String>,
}
impl<'a> FileQuery<'a> {
fn resolve_hash(&self) -> Result<String> {
match &self.target {
QueryTarget::Trunk => {
let tip = self.repo.database().get_trunk_tip()?;
self.repo.database().get_hash_by_rid(tip)
}
QueryTarget::Branch(name) => {
let tip = self.repo.database().get_branch_tip(name)?;
self.repo.database().get_hash_by_rid(tip)
}
QueryTarget::Tag(name) => self.repo.get_tag_checkin_internal(name),
QueryTarget::Commit(hash) => Ok(hash.clone()),
}
}
pub fn in_dir(mut self, dir: &str) -> Self {
self.directory = Some(dir.to_string());
self
}
pub fn list(&self) -> Result<Vec<FileInfo>> {
let hash = self.resolve_hash()?;
if let Some(dir) = &self.directory {
self.repo.list_directory_internal(&hash, dir)
} else {
self.repo.list_files_internal(&hash)
}
}
pub fn find(&self, pattern: &str) -> Result<Vec<FileInfo>> {
let hash = self.resolve_hash()?;
self.repo.find_files_internal(&hash, pattern)
}
pub fn read(&self, path: &str) -> Result<Vec<u8>> {
let hash = self.resolve_hash()?;
self.repo.read_file_internal(&hash, path)
}
pub fn read_string(&self, path: &str) -> Result<String> {
let content = self.read(path)?;
String::from_utf8(content).map_err(|e| FossilError::InvalidArtifact(e.to_string()))
}
pub fn subdirs(&self, dir: &str) -> Result<Vec<String>> {
let hash = self.resolve_hash()?;
self.repo.list_subdirs_internal(&hash, dir)
}
}