refactor errors in store.rs

This commit is contained in:
Brian Picciano 2023-05-07 14:33:22 +02:00
parent a7d5819a78
commit 71dcc94e29

View File

@ -8,10 +8,17 @@ use super::Descr;
pub struct Limits {} pub struct Limits {}
#[derive(Debug)] #[derive(Debug)]
pub enum AllDescrsError { pub enum WriteFileError {
FileNotFound,
Unexpected(Box<dyn Error>), Unexpected(Box<dyn Error>),
} }
impl<E: Error + 'static> From<E> for WriteFileError {
fn from(e: E) -> WriteFileError {
WriteFileError::Unexpected(Box::from(e))
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum SyncError { pub enum SyncError {
InvalidURL, InvalidURL,
@ -19,12 +26,25 @@ pub enum SyncError {
Unexpected(Box<dyn Error>), Unexpected(Box<dyn Error>),
} }
impl<E: Error + 'static> From<E> for SyncError {
fn from(e: E) -> SyncError {
SyncError::Unexpected(Box::from(e))
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum WriteFileError { pub enum AllDescrsError {
FileNotFound,
Unexpected(Box<dyn Error>), Unexpected(Box<dyn Error>),
} }
impl<E: Error + 'static> From<E> for AllDescrsError {
fn from(e: E) -> AllDescrsError {
AllDescrsError::Unexpected(Box::from(e))
}
}
type AllDescrsResult<T> = Result<T, AllDescrsError>;
pub trait Store { pub trait Store {
fn write_file<W>(&self, descr: &Descr, path: &str, into: &mut W) -> Result<(), WriteFileError> fn write_file<W>(&self, descr: &Descr, path: &str, into: &mut W) -> Result<(), WriteFileError>
where where
@ -32,9 +52,7 @@ pub trait Store {
fn sync(&self, descr: &Descr, limits: Limits) -> Result<(), SyncError>; fn sync(&self, descr: &Descr, limits: Limits) -> Result<(), SyncError>;
fn all_descrs( fn all_descrs(&self) -> AllDescrsResult<Box<dyn Iterator<Item = AllDescrsResult<Descr>> + '_>>;
&self,
) -> Result<Box<dyn Iterator<Item = Result<Descr, AllDescrsError>> + '_>, AllDescrsError>;
} }
pub mod git { pub mod git {
@ -43,24 +61,8 @@ pub mod git {
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::{fs, io}; use std::{fs, io};
use gix::clone::Error as gixCloneErr;
use gix::progress::Discard; use gix::progress::Discard;
// Catching error from gix::prepare_clone_bare
impl From<gixCloneErr> for SyncError {
fn from(e: gixCloneErr) -> SyncError {
match e {
gixCloneErr::Init(gix::init::Error::InvalidBranchName { .. }) => {
SyncError::InvalidBranchName
}
gixCloneErr::UrlParse(_) | gixCloneErr::CanonicalizeUrl { .. } => {
SyncError::InvalidURL
}
_ => SyncError::Unexpected(Box::from(e)),
}
}
}
pub struct Store<'a> { pub struct Store<'a> {
dir_path: &'a Path, dir_path: &'a Path,
} }
@ -93,47 +95,51 @@ pub mod git {
// if the path doesn't exist then use the gix clone feature to clone it into the // if the path doesn't exist then use the gix clone feature to clone it into the
// directory. // directory.
if fs::read_dir(repo_path).is_err() { if fs::read_dir(repo_path).is_err() {
fs::create_dir_all(repo_path).map_err(|e| SyncError::Unexpected(Box::from(e)))?; fs::create_dir_all(repo_path)?;
let Descr::Git { url, branch_name } = descr; let Descr::Git { url, branch_name } = descr;
let (repo, _) = gix::prepare_clone_bare(url.clone(), repo_path)? use gix::clone::Error as gixCloneErr;
let (repo, _) = gix::prepare_clone_bare(url.clone(), repo_path)
.map_err(|e| match e {
gixCloneErr::Init(gix::init::Error::InvalidBranchName { .. }) => {
SyncError::InvalidBranchName
}
gixCloneErr::UrlParse(_) | gixCloneErr::CanonicalizeUrl { .. } => {
SyncError::InvalidURL
}
_ => SyncError::Unexpected(Box::from(e)),
})?
.fetch_only(Discard, should_interrupt) .fetch_only(Discard, should_interrupt)
.map_err(|_| SyncError::InvalidURL)?; .map_err(|_| SyncError::InvalidURL)?;
// Check to make sure the branch name exists // Check to make sure the branch name exists
// TODO if this fails we should delete the whole repo // TODO if this fails we should delete the whole repo
repo.try_find_reference(&Self::branch_ref(branch_name)) repo.try_find_reference(&Self::branch_ref(branch_name))?
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
.ok_or(SyncError::InvalidBranchName)?; .ok_or(SyncError::InvalidBranchName)?;
// Add the descr to the repo directory, so we can know the actual descr later // Add the descr to the repo directory, so we can know the actual descr later
// TODO if this fails we should delete the whole repo // TODO if this fails we should delete the whole repo
let descr_file = fs::File::create(self.descr_file_path(descr.id().as_ref())) let descr_file = fs::File::create(self.descr_file_path(descr.id().as_ref()))?;
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
serde_json::to_writer(descr_file, &descr) serde_json::to_writer(descr_file, &descr)?;
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
return Ok(()); return Ok(());
} }
let direction = gix::remote::Direction::Fetch; let direction = gix::remote::Direction::Fetch;
let repo = gix::open(repo_path).map_err(|e| SyncError::Unexpected(Box::from(e)))?; let repo = gix::open(repo_path)?;
let remote = repo let remote = repo
.find_default_remote(direction) .find_default_remote(direction)
.ok_or_else(|| SyncError::Unexpected(Box::from("no default configured")))? .ok_or_else(|| SyncError::Unexpected(Box::from("no default configured")))??;
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
remote remote
.connect(direction) .connect(direction)?
.map_err(|e| SyncError::Unexpected(Box::from(e)))? .prepare_fetch(Discard, Default::default())?
.prepare_fetch(Discard, Default::default()) .receive(Discard, should_interrupt)?;
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
.receive(Discard, should_interrupt)
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
Ok(()) Ok(())
} }
@ -154,69 +160,51 @@ pub mod git {
let mut clean_path = Path::new(path); let mut clean_path = Path::new(path);
clean_path = clean_path.strip_prefix("/").unwrap_or(clean_path); clean_path = clean_path.strip_prefix("/").unwrap_or(clean_path);
let repo = let repo = gix::open(repo_path)?;
gix::open(repo_path).map_err(|e| WriteFileError::Unexpected(Box::from(e)))?;
let commit_object_id = repo let commit_object_id = repo.find_reference(branch_ref)?.peel_to_id_in_place()?;
.find_reference(branch_ref)
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?
.peel_to_id_in_place()
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?;
let tree_object_id = repo let tree_object_id = repo
.find_object(commit_object_id) .find_object(commit_object_id)?
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))? .try_to_commit_ref()?
.try_to_commit_ref()
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?
.tree(); .tree();
let file_object = repo let file_object = repo
.find_object(tree_object_id) .find_object(tree_object_id)?
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))? .peel_to_tree()?
.peel_to_tree() .lookup_entry_by_path(clean_path)?
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?
.lookup_entry_by_path(clean_path)
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?
.ok_or(WriteFileError::FileNotFound)? .ok_or(WriteFileError::FileNotFound)?
.object() .object()?;
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?;
into.write_all(file_object.data.as_ref()) into.write_all(file_object.data.as_ref())?;
.map_err(|e| WriteFileError::Unexpected(Box::from(e)))?;
Ok(()) Ok(())
} }
fn all_descrs( fn all_descrs(
&self, &self,
) -> Result<Box<dyn Iterator<Item = Result<Descr, AllDescrsError>> + '_>, AllDescrsError> ) -> AllDescrsResult<Box<dyn Iterator<Item = AllDescrsResult<Descr>> + '_>> {
{ let inner_iter = fs::read_dir(self.dir_path)?.map(
let inner_iter = fs::read_dir(self.dir_path) |dir_entry_res: io::Result<fs::DirEntry>| -> Result<Descr, AllDescrsError> {
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))? let descr_id: String = dir_entry_res?
.map( .file_name()
|dir_entry_res: io::Result<fs::DirEntry>| -> Result<Descr, AllDescrsError> { .to_str()
let descr_id: String = dir_entry_res .ok_or_else(|| {
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))? AllDescrsError::Unexpected(Box::from(
.file_name() "couldn't convert os string to &str",
.to_str() ))
.ok_or_else(|| { })?
AllDescrsError::Unexpected(Box::from( .into();
"couldn't convert os string to &str",
))
})?
.into();
let descr_file_path = self.descr_file_path(descr_id.as_ref()); let descr_file_path = self.descr_file_path(descr_id.as_ref());
let descr_file = fs::File::open(descr_file_path) let descr_file = fs::File::open(descr_file_path)?;
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))?;
let descr = serde_json::from_reader(descr_file) let descr = serde_json::from_reader(descr_file)?;
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))?;
Ok(descr) Ok(descr)
}, },
); );
Ok(Box::from(inner_iter)) Ok(Box::from(inner_iter))
} }