make origin store errors be actual errors, and implement a mock
This commit is contained in:
parent
696c92a292
commit
be84742e94
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -451,6 +451,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"tempdir",
|
"tempdir",
|
||||||
|
"thiserror",
|
||||||
"trust-dns-client",
|
"trust-dns-client",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -19,3 +19,4 @@ serde = { version = "1.0.162", features = [ "derive" ]}
|
|||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
trust-dns-client = "0.22.0"
|
trust-dns-client = "0.22.0"
|
||||||
mockall = "0.11.4"
|
mockall = "0.11.4"
|
||||||
|
thiserror = "1.0.40"
|
||||||
|
@ -7,54 +7,42 @@ pub struct Limits {
|
|||||||
// TODO storage limits
|
// TODO storage limits
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum ReadFileIntoError {
|
pub enum ReadFileIntoError {
|
||||||
|
#[error("file not found")]
|
||||||
FileNotFound,
|
FileNotFound,
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(Box<dyn Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Error + 'static> From<E> for ReadFileIntoError {
|
#[derive(thiserror::Error, Debug)]
|
||||||
fn from(e: E) -> ReadFileIntoError {
|
|
||||||
ReadFileIntoError::Unexpected(Box::from(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum SyncError {
|
pub enum SyncError {
|
||||||
|
#[error("invalid url")]
|
||||||
InvalidURL,
|
InvalidURL,
|
||||||
|
|
||||||
|
#[error("invalid branch name")]
|
||||||
InvalidBranchName,
|
InvalidBranchName,
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(Box<dyn Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Error + 'static> From<E> for SyncError {
|
#[derive(thiserror::Error, Debug)]
|
||||||
fn from(e: E) -> SyncError {
|
|
||||||
SyncError::Unexpected(Box::from(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum GetError {
|
pub enum GetError {
|
||||||
|
#[error("not found")]
|
||||||
NotFound,
|
NotFound,
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
Unexpected(Box<dyn Error>),
|
Unexpected(Box<dyn Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Error + 'static> From<E> for GetError {
|
#[derive(thiserror::Error, Debug)]
|
||||||
fn from(e: E) -> GetError {
|
|
||||||
GetError::Unexpected(Box::from(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum AllDescrsError {
|
pub enum AllDescrsError {
|
||||||
|
#[error(transparent)]
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[automock]
|
#[automock]
|
||||||
pub trait Origin {
|
pub trait Origin {
|
||||||
fn descr(&self) -> &Descr;
|
fn descr(&self) -> &Descr;
|
||||||
@ -80,15 +68,37 @@ pub trait Store<'a> {
|
|||||||
fn all_descrs(&'a self) -> AllDescrsResult<Self::AllDescrsIter>;
|
fn all_descrs(&'a self) -> AllDescrsResult<Self::AllDescrsIter>;
|
||||||
}
|
}
|
||||||
|
|
||||||
//mockall::mock! {
|
pub struct MockStore<SyncFn, GetFn, AllDescrsFn>
|
||||||
// pub MyStore {}
|
where
|
||||||
// impl<'a> Store<'a> for MyStore {
|
SyncFn: Fn(&Descr, Limits) -> Result<(), SyncError>,
|
||||||
// type AllDescrsIter = Vec<AllDescrsResult<Descr>>;
|
GetFn: Fn(Descr) -> Result<Box<dyn Origin>, GetError>,
|
||||||
// fn sync(&'a self, descr: &Descr, limits: Limits) -> Result<(), SyncError>;
|
AllDescrsFn: Fn() -> AllDescrsResult<Vec<AllDescrsResult<Descr>>>,
|
||||||
// fn get(&'a self, descr: Descr) -> Result<Box<dyn Origin>, GetError>;
|
{
|
||||||
// fn all_descrs(&'a self) -> AllDescrsResult<<self::MockMyStore as self::Store<'a>>::AllDescrsIter>;
|
pub sync_fn: SyncFn,
|
||||||
// }
|
pub get_fn: GetFn,
|
||||||
//}
|
pub all_descrs_fn: AllDescrsFn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, SyncFn, GetFn, AllDescrsFn> Store<'a> for MockStore<SyncFn, GetFn, AllDescrsFn>
|
||||||
|
where
|
||||||
|
SyncFn: Fn(&Descr, Limits) -> Result<(), SyncError>,
|
||||||
|
GetFn: Fn(Descr) -> Result<Box<dyn Origin>, GetError>,
|
||||||
|
AllDescrsFn: Fn() -> AllDescrsResult<Vec<AllDescrsResult<Descr>>>,
|
||||||
|
{
|
||||||
|
type AllDescrsIter = Vec<AllDescrsResult<Descr>>;
|
||||||
|
|
||||||
|
fn sync(&'a self, descr: &Descr, limits: Limits) -> Result<(), SyncError> {
|
||||||
|
(self.sync_fn)(descr, limits)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(&'a self, descr: Descr) -> Result<Box<dyn Origin>, GetError> {
|
||||||
|
(self.get_fn)(descr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_descrs(&'a self) -> AllDescrsResult<Self::AllDescrsIter> {
|
||||||
|
(self.all_descrs_fn)()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub mod git {
|
pub mod git {
|
||||||
|
|
||||||
@ -117,13 +127,18 @@ pub mod git {
|
|||||||
|
|
||||||
let file_object = self
|
let file_object = self
|
||||||
.repo
|
.repo
|
||||||
.find_object(self.tree_object_id)?
|
.find_object(self.tree_object_id)
|
||||||
.peel_to_tree()?
|
.map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))?
|
||||||
.lookup_entry_by_path(clean_path)?
|
.peel_to_tree()
|
||||||
|
.map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))?
|
||||||
|
.lookup_entry_by_path(clean_path)
|
||||||
|
.map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))?
|
||||||
.ok_or(ReadFileIntoError::FileNotFound)?
|
.ok_or(ReadFileIntoError::FileNotFound)?
|
||||||
.object()?;
|
.object()
|
||||||
|
.map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
into.write_all(file_object.data.as_ref())?;
|
into.write_all(file_object.data.as_ref())
|
||||||
|
.map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -167,7 +182,7 @@ 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)?;
|
fs::create_dir_all(repo_path).map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
let Descr::Git { url, branch_name } = descr;
|
let Descr::Git { url, branch_name } = descr;
|
||||||
|
|
||||||
@ -186,30 +201,37 @@ pub mod git {
|
|||||||
|
|
||||||
// Check to make sure the branch name exists
|
// Check to make sure the branch name exists
|
||||||
// TODO if this fails we should delete repo_path
|
// TODO if this fails we should delete repo_path
|
||||||
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 repo_path
|
// TODO if this fails we should delete repo_path
|
||||||
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)?;
|
let repo = gix::open(repo_path).map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
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)
|
||||||
.prepare_fetch(Discard, Default::default())?
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
|
||||||
.receive(Discard, should_interrupt)?;
|
.prepare_fetch(Discard, Default::default())
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?
|
||||||
|
.receive(Discard, should_interrupt)
|
||||||
|
.map_err(|e| SyncError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -222,19 +244,23 @@ pub mod git {
|
|||||||
|
|
||||||
fs::read_dir(&repo_path).map_err(|e| match e.kind() {
|
fs::read_dir(&repo_path).map_err(|e| match e.kind() {
|
||||||
io::ErrorKind::NotFound => GetError::NotFound,
|
io::ErrorKind::NotFound => GetError::NotFound,
|
||||||
_ => e.into(),
|
_ => GetError::Unexpected(Box::from(e)),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let repo = gix::open(&repo_path)?;
|
let repo = gix::open(&repo_path).map_err(|e| GetError::Unexpected(Box::from(e)))?;
|
||||||
|
|
||||||
let commit_object_id = repo
|
let commit_object_id = repo
|
||||||
.find_reference(&self.branch_ref(branch_name))?
|
.find_reference(&self.branch_ref(branch_name))
|
||||||
.peel_to_id_in_place()?
|
.map_err(|e| GetError::Unexpected(Box::from(e)))?
|
||||||
|
.peel_to_id_in_place()
|
||||||
|
.map_err(|e| GetError::Unexpected(Box::from(e)))?
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let tree_object_id = repo
|
let tree_object_id = repo
|
||||||
.find_object(commit_object_id)?
|
.find_object(commit_object_id)
|
||||||
.try_to_commit_ref()?
|
.map_err(|e| GetError::Unexpected(Box::from(e)))?
|
||||||
|
.try_to_commit_ref()
|
||||||
|
.map_err(|e| GetError::Unexpected(Box::from(e)))?
|
||||||
.tree();
|
.tree();
|
||||||
|
|
||||||
return Ok(Box::from(Origin {
|
return Ok(Box::from(Origin {
|
||||||
@ -245,9 +271,13 @@ pub mod git {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn all_descrs(&'a self) -> AllDescrsResult<Self::AllDescrsIter> {
|
fn all_descrs(&'a self) -> AllDescrsResult<Self::AllDescrsIter> {
|
||||||
Ok(Box::from(fs::read_dir(&self.dir_path)?.map(
|
Ok(Box::from(
|
||||||
|
fs::read_dir(&self.dir_path)
|
||||||
|
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))?
|
||||||
|
.map(
|
||||||
|dir_entry_res: io::Result<fs::DirEntry>| -> AllDescrsResult<Descr> {
|
|dir_entry_res: io::Result<fs::DirEntry>| -> AllDescrsResult<Descr> {
|
||||||
let descr_id: String = dir_entry_res?
|
let descr_id: String = dir_entry_res
|
||||||
|
.map_err(|e| AllDescrsError::Unexpected(Box::from(e)))?
|
||||||
.file_name()
|
.file_name()
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
@ -259,13 +289,16 @@ pub mod git {
|
|||||||
|
|
||||||
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)
|
||||||
},
|
},
|
||||||
)))
|
),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user