From be84742e94e464de7a8eb7be3ddb3b66b121c820 Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Tue, 9 May 2023 13:40:49 +0200 Subject: [PATCH] make origin store errors be actual errors, and implement a mock --- Cargo.lock | 1 + Cargo.toml | 1 + src/origin/store.rs | 181 ++++++++++++++++++++++++++------------------ 3 files changed, 109 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96406d1..33560bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,6 +451,7 @@ dependencies = [ "serde_json", "sha2", "tempdir", + "thiserror", "trust-dns-client", ] diff --git a/Cargo.toml b/Cargo.toml index 60dd9a1..9393b48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ serde = { version = "1.0.162", features = [ "derive" ]} serde_json = "1.0.96" trust-dns-client = "0.22.0" mockall = "0.11.4" +thiserror = "1.0.40" diff --git a/src/origin/store.rs b/src/origin/store.rs index 675bce3..02156cb 100644 --- a/src/origin/store.rs +++ b/src/origin/store.rs @@ -7,54 +7,42 @@ pub struct Limits { // TODO storage limits } -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] pub enum ReadFileIntoError { + #[error("file not found")] FileNotFound, + + #[error(transparent)] Unexpected(Box), } -impl From for ReadFileIntoError { - fn from(e: E) -> ReadFileIntoError { - ReadFileIntoError::Unexpected(Box::from(e)) - } -} - -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] pub enum SyncError { + #[error("invalid url")] InvalidURL, + + #[error("invalid branch name")] InvalidBranchName, + + #[error(transparent)] Unexpected(Box), } -impl From for SyncError { - fn from(e: E) -> SyncError { - SyncError::Unexpected(Box::from(e)) - } -} - -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] pub enum GetError { + #[error("not found")] NotFound, + + #[error(transparent)] Unexpected(Box), } -impl From for GetError { - fn from(e: E) -> GetError { - GetError::Unexpected(Box::from(e)) - } -} - -#[derive(Debug)] +#[derive(thiserror::Error, Debug)] pub enum AllDescrsError { + #[error(transparent)] Unexpected(Box), } -impl From for AllDescrsError { - fn from(e: E) -> AllDescrsError { - AllDescrsError::Unexpected(Box::from(e)) - } -} - #[automock] pub trait Origin { fn descr(&self) -> &Descr; @@ -80,15 +68,37 @@ pub trait Store<'a> { fn all_descrs(&'a self) -> AllDescrsResult; } -//mockall::mock! { -// pub MyStore {} -// impl<'a> Store<'a> for MyStore { -// type AllDescrsIter = Vec>; -// fn sync(&'a self, descr: &Descr, limits: Limits) -> Result<(), SyncError>; -// fn get(&'a self, descr: Descr) -> Result, GetError>; -// fn all_descrs(&'a self) -> AllDescrsResult<>::AllDescrsIter>; -// } -//} +pub struct MockStore +where + SyncFn: Fn(&Descr, Limits) -> Result<(), SyncError>, + GetFn: Fn(Descr) -> Result, GetError>, + AllDescrsFn: Fn() -> AllDescrsResult>>, +{ + pub sync_fn: SyncFn, + pub get_fn: GetFn, + pub all_descrs_fn: AllDescrsFn, +} + +impl<'a, SyncFn, GetFn, AllDescrsFn> Store<'a> for MockStore +where + SyncFn: Fn(&Descr, Limits) -> Result<(), SyncError>, + GetFn: Fn(Descr) -> Result, GetError>, + AllDescrsFn: Fn() -> AllDescrsResult>>, +{ + type AllDescrsIter = Vec>; + + fn sync(&'a self, descr: &Descr, limits: Limits) -> Result<(), SyncError> { + (self.sync_fn)(descr, limits) + } + + fn get(&'a self, descr: Descr) -> Result, GetError> { + (self.get_fn)(descr) + } + + fn all_descrs(&'a self) -> AllDescrsResult { + (self.all_descrs_fn)() + } +} pub mod git { @@ -117,13 +127,18 @@ pub mod git { let file_object = self .repo - .find_object(self.tree_object_id)? - .peel_to_tree()? - .lookup_entry_by_path(clean_path)? + .find_object(self.tree_object_id) + .map_err(|e| ReadFileIntoError::Unexpected(Box::from(e)))? + .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)? - .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(()) } @@ -167,7 +182,7 @@ pub mod git { // if the path doesn't exist then use the gix clone feature to clone it into the // directory. 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; @@ -186,30 +201,37 @@ pub mod git { // Check to make sure the branch name exists // 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)?; // Add the descr to the repo directory, so we can know the actual descr later // 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(()); } 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 .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 - .connect(direction)? - .prepare_fetch(Discard, Default::default())? - .receive(Discard, should_interrupt)?; + .connect(direction) + .map_err(|e| SyncError::Unexpected(Box::from(e)))? + .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(()) } @@ -222,19 +244,23 @@ pub mod git { fs::read_dir(&repo_path).map_err(|e| match e.kind() { 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 - .find_reference(&self.branch_ref(branch_name))? - .peel_to_id_in_place()? + .find_reference(&self.branch_ref(branch_name)) + .map_err(|e| GetError::Unexpected(Box::from(e)))? + .peel_to_id_in_place() + .map_err(|e| GetError::Unexpected(Box::from(e)))? .detach(); let tree_object_id = repo - .find_object(commit_object_id)? - .try_to_commit_ref()? + .find_object(commit_object_id) + .map_err(|e| GetError::Unexpected(Box::from(e)))? + .try_to_commit_ref() + .map_err(|e| GetError::Unexpected(Box::from(e)))? .tree(); return Ok(Box::from(Origin { @@ -245,27 +271,34 @@ pub mod git { } fn all_descrs(&'a self) -> AllDescrsResult { - Ok(Box::from(fs::read_dir(&self.dir_path)?.map( - |dir_entry_res: io::Result| -> AllDescrsResult { - let descr_id: String = dir_entry_res? - .file_name() - .to_str() - .ok_or_else(|| { - AllDescrsError::Unexpected(Box::from( - "couldn't convert os string to &str", - )) - })? - .into(); + Ok(Box::from( + fs::read_dir(&self.dir_path) + .map_err(|e| AllDescrsError::Unexpected(Box::from(e)))? + .map( + |dir_entry_res: io::Result| -> AllDescrsResult { + let descr_id: String = dir_entry_res + .map_err(|e| AllDescrsError::Unexpected(Box::from(e)))? + .file_name() + .to_str() + .ok_or_else(|| { + AllDescrsError::Unexpected(Box::from( + "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) + }, + ), + )) } }