From ea0938549bbf432d61281ee22ec79b2c596216f9 Mon Sep 17 00:00:00 2001 From: Florian Albertz Date: Sun, 19 Jan 2020 15:13:42 +0100 Subject: [PATCH] feat: remove anyhow and use custom error types --- Cargo.toml | 1 - src/content/read.rs | 18 ++-- src/content/rm.rs | 8 +- src/content/write.rs | 41 ++++++--- src/errors.rs | 54 ++++++++++- src/get.rs | 208 +++++-------------------------------------- src/index.rs | 22 +++-- src/lib.rs | 18 ++-- src/put.rs | 94 ++++--------------- src/rm.rs | 62 ++++--------- 10 files changed, 166 insertions(+), 360 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1b6ef09..4b968da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ serde_derive = "1.0.102" walkdir = "2.2.9" either = "1.5.3" async-std = { version = "1.0.1", features = ["unstable"] } -anyhow = "1.0.19" thiserror = "1.0.5" futures = "0.3.1" diff --git a/src/content/read.rs b/src/content/read.rs index 304d243..6bd3913 100644 --- a/src/content/read.rs +++ b/src/content/read.rs @@ -3,12 +3,12 @@ use std::path::Path; use std::pin::Pin; use std::task::{Context, Poll}; -use anyhow::Result; use async_std; use futures::prelude::*; use ssri::{Algorithm, Integrity, IntegrityChecker}; use crate::content::path; +use crate::errors::{Internal, Result}; pub struct Reader { fd: File, @@ -55,7 +55,7 @@ impl AsyncReader { pub fn open(cache: &Path, sri: Integrity) -> Result { let cpath = path::content_path(&cache, &sri); Ok(Reader { - fd: File::open(cpath)?, + fd: File::open(cpath).to_internal()?, checker: IntegrityChecker::new(sri), }) } @@ -63,37 +63,37 @@ pub fn open(cache: &Path, sri: Integrity) -> Result { pub async fn open_async(cache: &Path, sri: Integrity) -> Result { let cpath = path::content_path(&cache, &sri); Ok(AsyncReader { - fd: async_std::fs::File::open(cpath).await?, + fd: async_std::fs::File::open(cpath).await.to_internal()?, checker: IntegrityChecker::new(sri), }) } pub fn read(cache: &Path, sri: &Integrity) -> Result> { let cpath = path::content_path(&cache, &sri); - let ret = fs::read(&cpath)?; + let ret = fs::read(&cpath).to_internal()?; sri.check(&ret)?; Ok(ret) } pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result> { let cpath = path::content_path(&cache, &sri); - let ret = async_std::fs::read(&cpath).await?; + let ret = async_std::fs::read(&cpath).await.to_internal()?; sri.check(&ret)?; Ok(ret) } pub fn copy(cache: &Path, sri: &Integrity, to: &Path) -> Result { let cpath = path::content_path(&cache, &sri); - let ret = fs::copy(&cpath, to)?; - let data = fs::read(cpath)?; + let ret = fs::copy(&cpath, to).to_internal()?; + let data = fs::read(cpath).to_internal()?; sri.check(data)?; Ok(ret) } pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result { let cpath = path::content_path(&cache, &sri); - let ret = async_std::fs::copy(&cpath, to).await?; - let data = async_std::fs::read(cpath).await?; + let ret = async_std::fs::copy(&cpath, to).await.to_internal()?; + let data = async_std::fs::read(cpath).await.to_internal()?; sri.check(data)?; Ok(ret) } diff --git a/src/content/rm.rs b/src/content/rm.rs index ec99ae0..5b85f0d 100644 --- a/src/content/rm.rs +++ b/src/content/rm.rs @@ -1,18 +1,20 @@ use std::fs; use std::path::Path; -use anyhow::Result; use async_std::fs as afs; use ssri::Integrity; use crate::content::path; +use crate::errors::{Internal, Result}; pub fn rm(cache: &Path, sri: &Integrity) -> Result<()> { - fs::remove_file(path::content_path(&cache, &sri))?; + fs::remove_file(path::content_path(&cache, &sri)).to_internal()?; Ok(()) } pub async fn rm_async(cache: &Path, sri: &Integrity) -> Result<()> { - afs::remove_file(path::content_path(&cache, &sri)).await?; + afs::remove_file(path::content_path(&cache, &sri)) + .await + .to_internal()?; Ok(()) } diff --git a/src/content/write.rs b/src/content/write.rs index e002dd8..80825b8 100644 --- a/src/content/write.rs +++ b/src/content/write.rs @@ -4,7 +4,6 @@ use std::path::{Path, PathBuf}; use std::pin::Pin; use std::sync::Mutex; -use anyhow::Result; use async_std::fs as afs; use async_std::future::Future; use async_std::task::{self, Context, JoinHandle, Poll}; @@ -14,6 +13,7 @@ use ssri::{Algorithm, Integrity, IntegrityOpts}; use tempfile::NamedTempFile; use crate::content::path; +use crate::errors::{Internal, Result}; pub struct Writer { cache: PathBuf, @@ -26,11 +26,14 @@ impl Writer { let cache_path = cache.to_path_buf(); let mut tmp_path = cache_path.clone(); tmp_path.push("tmp"); - DirBuilder::new().recursive(true).create(&tmp_path)?; + DirBuilder::new() + .recursive(true) + .create(&tmp_path) + .to_internal()?; Ok(Writer { cache: cache_path, builder: IntegrityOpts::new().algorithm(algo), - tmpfile: NamedTempFile::new_in(tmp_path)?, + tmpfile: NamedTempFile::new_in(tmp_path).to_internal()?, }) } @@ -40,8 +43,9 @@ impl Writer { DirBuilder::new() .recursive(true) // Safe unwrap. cpath always has multiple segments - .create(cpath.parent().unwrap())?; - self.tmpfile.persist(cpath)?; + .create(cpath.parent().unwrap()) + .to_internal()?; + self.tmpfile.persist(cpath).to_internal()?; Ok(sri) } } @@ -87,11 +91,14 @@ impl AsyncWriter { afs::DirBuilder::new() .recursive(true) .create(&tmp_path) - .await?; + .await + .to_internal()?; Ok(AsyncWriter(Mutex::new(State::Idle(Some(Inner { cache: cache_path, builder: IntegrityOpts::new().algorithm(algo), - tmpfile: task::spawn_blocking(|| NamedTempFile::new_in(tmp_path)).await?, + tmpfile: task::spawn_blocking(|| NamedTempFile::new_in(tmp_path)) + .await + .to_internal()?, buf: vec![], last_op: None, }))))) @@ -101,7 +108,7 @@ impl AsyncWriter { // NOTE: How do I even get access to `inner` safely??? // let inner = ???; // Blocking, but should be a very fast op. - futures::future::poll_fn(|cx| { + Ok(futures::future::poll_fn(|cx| { let state = &mut *self.0.lock().unwrap(); loop { @@ -121,12 +128,18 @@ impl AsyncWriter { // Safe unwrap. cpath always has multiple segments .create(cpath.parent().unwrap()) .await - .map_err(anyhow::Error::new); + .with_context(|| { + format!( + "building directory {} failed", + cpath.parent().unwrap().display() + ) + }); if res.is_err() { let _ = s.send(res.map(|_| sri)); } else { - let res = tmpfile.persist(cpath); - let res = res.map_err(anyhow::Error::new); + let res = tmpfile.persist(cpath).with_context(|| { + String::from("persisting tempfile failed") + }); let _ = s.send(res.map(|_| sri)); } State::Idle(None) @@ -141,8 +154,10 @@ impl AsyncWriter { } }) .map(|opt| opt.ok_or_else(|| io_error("file closed"))) - .await? - .await? + .await + .to_internal()? + .await + .to_internal()??) } } diff --git a/src/errors.rs b/src/errors.rs index c2759dc..1eef7ff 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,8 +1,35 @@ use std::path::PathBuf; -use ssri::Integrity; use thiserror::Error; +#[derive(Error, Debug)] +#[error("{source}\n\n {}", context.join("\n "))] +pub struct InternalError { + source: Box, + context: Vec, +} + +pub trait Internal { + fn to_internal(self) -> InternalResult; + fn with_context String>(self, f: F) -> InternalResult; +} + +impl Internal for std::result::Result { + fn to_internal(self) -> InternalResult { + self.map_err(|e| InternalError { + source: Box::new(e), + context: Vec::new(), + }) + } + + fn with_context String>(self, f: F) -> InternalResult { + self.map_err(|e| InternalError { + source: Box::new(e), + context: vec![f()], + }) + } +} + /// Error type returned by all API calls. #[derive(Error, Debug)] pub enum Error { @@ -10,10 +37,29 @@ pub enum Error { /// lookup. #[error("Entry not found for key {1:?} in cache {0:?}")] EntryNotFound(PathBuf, String), - /// Returned when an integrity check has failed. - #[error("Integrity check failed.\n\tWanted: {0}\n\tActual: {1}")] - IntegrityError(Integrity, Integrity), + /// Returned when a size check has failed. #[error("Size check failed.\n\tWanted: {0}\n\tActual: {1}")] SizeError(usize, usize), + + /// Returned when an integrity check has failed. + #[error(transparent)] + IntegrityError { + #[from] + /// The underlying error + source: ssri::Error, + }, + + /// Returned if an internal (e.g. io) operation has failed. + #[error(transparent)] + InternalError { + #[from] + /// The underlying error + source: InternalError, + }, } + +/// The result type returned by calls to this library +pub type Result = std::result::Result; + +pub type InternalResult = std::result::Result; diff --git a/src/get.rs b/src/get.rs index d10c551..625ab0d 100644 --- a/src/get.rs +++ b/src/get.rs @@ -5,11 +5,10 @@ use std::task::{Context as TaskContext, Poll}; use futures::prelude::*; -use anyhow::{Context, Result}; use ssri::{Algorithm, Integrity}; use crate::content::read; -use crate::errors::Error; +use crate::errors::{Error, Result}; use crate::index::{self, Metadata}; // --------- @@ -47,22 +46,19 @@ impl Reader { /// ```no_run /// use async_std::prelude::*; /// use async_attributes; - /// use anyhow::Result; /// /// #[async_attributes::main] - /// async fn main() -> Result<()> { + /// async fn main() -> cacache::Result<()> { /// let mut fd = cacache::Reader::open("./my-cache", "my-key").await?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str).await?; + /// fd.read_to_string(&mut str).await.expect("Failed to read to string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) /// } /// ``` pub fn check(self) -> Result { - self.reader - .check() - .context("Cache read data verification check failed.") + self.reader.check() } /// Opens a new file handle into the cache, looking it up in the index using /// `key`. @@ -71,13 +67,12 @@ impl Reader { /// ```no_run /// use async_std::prelude::*; /// use async_attributes; - /// use anyhow::Result; /// /// #[async_attributes::main] - /// async fn main() -> Result<()> { + /// async fn main() -> cacache::Result<()> { /// let mut fd = cacache::Reader::open("./my-cache", "my-key").await?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str).await?; + /// fd.read_to_string(&mut str).await.expect("Failed to read to string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) @@ -104,14 +99,13 @@ impl Reader { /// ```no_run /// use async_std::prelude::*; /// use async_attributes; - /// use anyhow::Result; /// /// #[async_attributes::main] - /// async fn main() -> Result<()> { + /// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "key", b"hello world").await?; /// let mut fd = cacache::Reader::open_hash("./my-cache", sri).await?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str).await?; + /// fd.read_to_string(&mut str).await.expect("Failed to read to string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) @@ -134,10 +128,9 @@ impl Reader { /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let data: Vec = cacache::read("./my-cache", "my-key").await?; /// Ok(()) /// } @@ -157,36 +150,6 @@ where } } -/// Reads the entire contents of a cache file into a string, looking the -/// data up by key. -/// -/// ## Example -/// ```no_run -/// use async_std::prelude::*; -/// use async_attributes; -/// use anyhow::Result; -/// -/// #[async_attributes::main] -/// async fn main() -> Result<()> { -/// let str: String = cacache::read_to_string("./my-cache", "my-key").await?; -/// Ok(()) -/// } -/// ``` -pub async fn read_to_string(cache: P, key: K) -> Result -where - P: AsRef, - K: AsRef, -{ - if let Some(entry) = index::find_async(cache.as_ref(), key.as_ref()).await? { - read_hash_to_string(cache, &entry.integrity).await - } else { - Err(Error::EntryNotFound( - cache.as_ref().to_path_buf(), - key.as_ref().into(), - ))? - } -} - /// Reads the entire contents of a cache file into a bytes vector, looking the /// data up by its content address. /// @@ -194,10 +157,9 @@ where /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let data: Vec = cacache::read_hash("./my-cache", &sri).await?; /// Ok(()) @@ -210,31 +172,6 @@ where Ok(read::read_async(cache.as_ref(), sri).await?) } -/// Reads the entire contents of a cache file into a string, looking the -/// data up by its content address. -/// -/// ## Example -/// ```no_run -/// use async_std::prelude::*; -/// use async_attributes; -/// use anyhow::Result; -/// -/// #[async_attributes::main] -/// async fn main() -> Result<()> { -/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; -/// let str: String = cacache::read_hash_to_string("./my-cache", &sri).await?; -/// Ok(()) -/// } -/// ``` -pub async fn read_hash_to_string

(cache: P, sri: &Integrity) -> Result -where - P: AsRef, -{ - Ok(String::from_utf8( - read::read_async(cache.as_ref(), sri).await?, - )?) -} - /// Copies cache data to a specified location. Returns the number of bytes /// copied. /// @@ -242,10 +179,9 @@ where /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// cacache::copy("./my-cache", "my-key", "./data.txt").await?; /// Ok(()) /// } @@ -273,10 +209,9 @@ where /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "my-key", b"hello world").await?; /// cacache::copy_hash("./my-cache", &sri, "./data.txt").await?; /// Ok(()) @@ -336,22 +271,19 @@ impl SyncReader { /// /// ## Example /// ```no_run - /// use anyhow::Result; /// use std::io::Read; /// - /// fn main() -> Result<()> { + /// fn main() -> cacache::Result<()> { /// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str)?; + /// fd.read_to_string(&mut str).expect("Failed to read to string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) /// } /// ``` pub fn check(self) -> Result { - self.reader - .check() - .context("Cache read data verification check failed.") + self.reader.check() } /// Opens a new synchronous file handle into the cache, looking it up in the @@ -359,13 +291,12 @@ impl SyncReader { /// /// ## Example /// ```no_run - /// use anyhow::Result; /// use std::io::Read; /// - /// fn main() -> Result<()> { + /// fn main() -> cacache::Result<()> { /// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str)?; + /// fd.read_to_string(&mut str).expect("Failed to parse string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) @@ -390,14 +321,13 @@ impl SyncReader { /// /// ## Example /// ```no_run - /// use anyhow::Result; /// use std::io::Read; /// - /// fn main() -> Result<()> { + /// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "key", b"hello world")?; /// let mut fd = cacache::SyncReader::open_hash("./my-cache", sri)?; /// let mut str = String::new(); - /// fd.read_to_string(&mut str)?; + /// fd.read_to_string(&mut str).expect("Failed to read to string"); /// // Remember to check that the data you got was correct! /// fd.check()?; /// Ok(()) @@ -418,10 +348,9 @@ impl SyncReader { /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let data = cacache::read_sync("./my-cache", "my-key")?; /// Ok(()) /// } @@ -441,42 +370,14 @@ where } } -/// Reads the entire contents of a cache file synchronously into a string, -/// looking the data up by key. -/// -/// ## Example -/// ```no_run -/// use anyhow::Result; -/// use std::io::Read; -/// -/// fn main() -> Result<()> { -/// let str: String = cacache::read_to_string_sync("./my-cache", "my-key")?; -/// Ok(()) -/// } -/// ``` -pub fn read_to_string_sync(cache: P, key: K) -> Result -where - P: AsRef, - K: AsRef, -{ - if let Some(entry) = index::find(cache.as_ref(), key.as_ref())? { - read_hash_to_string_sync(cache, &entry.integrity) - } else { - Err(Error::EntryNotFound( - cache.as_ref().to_path_buf(), - key.as_ref().into(), - ))? - } -} /// Reads the entire contents of a cache file synchronously into a bytes /// vector, looking the data up by its content address. /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let data = cacache::read_hash_sync("./my-cache", &sri)?; /// Ok(()) @@ -489,36 +390,14 @@ where Ok(read::read(cache.as_ref(), sri)?) } -/// Reads the entire contents of a cache file synchronously into a string, -/// looking the data up by its content address. -/// -/// ## Example -/// ```no_run -/// use anyhow::Result; -/// use std::io::Read; -/// -/// fn main() -> Result<()> { -/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; -/// let data = cacache::read_hash_sync("./my-cache", &sri)?; -/// Ok(()) -/// } -/// ``` -pub fn read_hash_to_string_sync

(cache: P, sri: &Integrity) -> Result -where - P: AsRef, -{ - Ok(String::from_utf8(read::read(cache.as_ref(), sri)?)?) -} - /// Copies a cache entry by key to a specified location. Returns the number of /// bytes copied. /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// cacache::copy_sync("./my-cache", "my-key", "./my-hello.txt")?; /// Ok(()) /// } @@ -544,10 +423,9 @@ where /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// cacache::copy_hash_sync("./my-cache", &sri, "./my-hello.txt")?; /// Ok(()) @@ -651,16 +529,6 @@ mod tests { assert_eq!(data, b"hello world"); } - #[async_attributes::test] - async fn test_read_to_string() { - let tmp = tempfile::tempdir().unwrap(); - let dir = tmp.path().to_owned(); - crate::write(&dir, "my-key", "hello world").await.unwrap(); - - let data = crate::read_to_string(&dir, "my-key").await.unwrap(); - assert_eq!(data, "hello world"); - } - #[async_attributes::test] async fn test_read_hash() { let tmp = tempfile::tempdir().unwrap(); @@ -671,16 +539,6 @@ mod tests { assert_eq!(data, b"hello world"); } - #[async_attributes::test] - async fn test_read_hash_to_string() { - let tmp = tempfile::tempdir().unwrap(); - let dir = tmp.path().to_owned(); - let sri = crate::write(&dir, "my-key", "hello world").await.unwrap(); - - let data = crate::read_hash_to_string(&dir, &sri).await.unwrap(); - assert_eq!(data, "hello world"); - } - #[test] fn test_read_sync() { let tmp = tempfile::tempdir().unwrap(); @@ -691,16 +549,6 @@ mod tests { assert_eq!(data, b"hello world"); } - #[test] - fn test_read_to_string_sync() { - let tmp = tempfile::tempdir().unwrap(); - let dir = tmp.path().to_owned(); - crate::write_sync(&dir, "my-key", "hello world").unwrap(); - - let data = crate::read_to_string_sync(&dir, "my-key").unwrap(); - assert_eq!(data, "hello world"); - } - #[test] fn test_read_hash_sync() { let tmp = tempfile::tempdir().unwrap(); @@ -711,16 +559,6 @@ mod tests { assert_eq!(data, b"hello world"); } - #[test] - fn test_read_hash_to_string_sync() { - let tmp = tempfile::tempdir().unwrap(); - let dir = tmp.path().to_owned(); - let sri = crate::write_sync(&dir, "my-key", "hello world").unwrap(); - - let data = crate::read_hash_to_string_sync(&dir, &sri).unwrap(); - assert_eq!(data, "hello world"); - } - #[async_attributes::test] async fn test_copy() { let tmp = tempfile::tempdir().unwrap(); diff --git a/src/index.rs b/src/index.rs index 95b62ba..21bace8 100644 --- a/src/index.rs +++ b/src/index.rs @@ -5,7 +5,6 @@ use std::io::{ErrorKind, Write}; use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; -use anyhow::{Context, Result}; use async_std::fs as afs; use async_std::io::BufReader; use digest::Digest; @@ -20,6 +19,7 @@ use sha2::Sha256; use ssri::Integrity; use walkdir::WalkDir; +use crate::errors::{Internal, InternalResult, Result}; use crate::put::WriteOpts; const INDEX_VERSION: &str = "5"; @@ -88,7 +88,8 @@ pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result { let out = format!("\n{}\t{}", hash_entry(&stringified), stringified); buck.write_all(out.as_bytes()) .with_context(|| format!("Failed to write to index bucket at {:?}", bucket))?; - buck.flush()?; + buck.flush() + .with_context(|| format!("Failed to flush bucket at {:?}", bucket))?; Ok(opts .sri .or_else(|| "sha1-deadbeef".parse::().ok()) @@ -125,7 +126,9 @@ pub async fn insert_async<'a>(cache: &'a Path, key: &'a str, opts: WriteOpts) -> buck.write_all(out.as_bytes()) .await .with_context(|| format!("Failed to write to index bucket at {:?}", bucket))?; - buck.flush().await?; + buck.flush() + .await + .with_context(|| format!("Failed to flush bucket at {:?}", bucket))?; Ok(opts .sri .or_else(|| "sha1-deadbeef".parse::().ok()) @@ -223,7 +226,8 @@ pub fn ls(cache: &Path) -> impl Iterator> { WalkDir::new(cache.join(format!("index-v{}", INDEX_VERSION))) .into_iter() .map(|bucket| { - let bucket = bucket?; + let bucket = bucket.to_internal()?; + if bucket.file_type().is_dir() { return Ok(Vec::new()); } @@ -281,13 +285,13 @@ fn now() -> u128 { .as_millis() } -fn bucket_entries(bucket: &Path) -> Result> { +fn bucket_entries(bucket: &Path) -> InternalResult> { use std::io::{BufRead, BufReader}; fs::File::open(bucket) .map(|file| { BufReader::new(file) .lines() - .filter_map(Result::ok) + .filter_map(std::result::Result::ok) .filter_map(|entry| { let entry_str = match entry.split('\t').collect::>()[..] { [hash, entry_str] if hash_entry(entry_str) == hash => entry_str, @@ -302,19 +306,19 @@ fn bucket_entries(bucket: &Path) -> Result> { if err.kind() == ErrorKind::NotFound { Ok(Vec::new()) } else { - Err(err)? + Err(err).to_internal()? } }) } -async fn bucket_entries_async(bucket: &Path) -> Result> { +async fn bucket_entries_async(bucket: &Path) -> InternalResult> { let file_result = afs::File::open(bucket).await; let file; if let Err(err) = file_result { if err.kind() == ErrorKind::NotFound { return Ok(Vec::new()); } - return Err(err.into()); + return Err(err).to_internal()?; } else { file = file_result.unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index 7e5fb18..7b59638 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,10 +35,9 @@ //! //! ```no_run //! use async_attributes; -//! use anyhow::Result; //! //! #[async_attributes::main] -//! async fn main() -> Result<()> { +//! async fn main() -> cacache::Result<()> { //! // Data goes in... //! cacache::write("./my-cache", "key", b"hello").await?; //! @@ -60,10 +59,9 @@ //! //! ```no_run //! use async_attributes; -//! use anyhow::Result; //! //! #[async_attributes::main] -//! async fn main() -> Result<()> { +//! async fn main() -> cacache::Result<()> { //! // Data goes in... //! let sri = cacache::write("./my-cache", "key", b"hello").await?; //! @@ -81,15 +79,14 @@ //! an API reminiscent of `std::fs::OpenOptions`: //! //! ```no_run -//! use anyhow::Result; //! use async_attributes; //! use async_std::prelude::*; //! //! #[async_attributes::main] -//! async fn main() -> Result<()> { +//! async fn main() -> cacache::Result<()> { //! let mut fd = cacache::Writer::create("./my-cache", "key").await?; //! for _ in 0..10 { -//! fd.write_all(b"very large data").await?; +//! fd.write_all(b"very large data").await.expect("Failed to write to cache"); //! } //! // Data is only committed to the cache after you do `fd.commit()`! //! let sri = fd.commit().await?; @@ -97,7 +94,7 @@ //! //! let mut fd = cacache::Reader::open("./my-cache", "key").await?; //! let mut buf = String::new(); -//! fd.read_to_string(&mut buf).await?; +//! fd.read_to_string(&mut buf).await.expect("Failed to read to string"); //! //! // Make sure to call `.check()` when you're done! It makes sure that what //! // you just read is actually valid. `cacache` always verifies the data @@ -117,8 +114,7 @@ //! application, you probably want to use these instead. //! //! ```no_run -//! use anyhow::Result; -//! fn main() -> Result<()> { +//! fn main() -> cacache::Result<()> { //! cacache::write_sync("./my-cache", "key", b"my-data").unwrap(); //! let data = cacache::read_sync("./my-cache", "key").unwrap(); //! assert_eq!(data, b"my-data"); @@ -139,7 +135,7 @@ mod ls; mod put; mod rm; -pub use errors::Error; +pub use errors::{Error, Result}; pub use index::Metadata; pub use get::*; diff --git a/src/put.rs b/src/put.rs index 9b7efeb..54ebb73 100644 --- a/src/put.rs +++ b/src/put.rs @@ -5,12 +5,11 @@ use std::pin::Pin; use futures::prelude::*; -use anyhow::{Context, Result}; use serde_json::Value; use ssri::{Algorithm, Integrity}; use crate::content::write; -use crate::errors::Error; +use crate::errors::{Error, Internal, Result}; use crate::index; use std::task::{Context as TaskContext, Poll}; @@ -20,10 +19,9 @@ use std::task::{Context as TaskContext, Poll}; /// ## Example /// ```no_run /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// cacache::write("./my-cache", "my-key", b"hello").await?; /// Ok(()) /// } @@ -42,13 +40,7 @@ where cache.as_ref() ) })?; - writer.commit().await.with_context(|| { - format!( - "Failed to write to commit data for key {} for cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) + writer.commit().await } /// A reference to an open file writing to the cache. @@ -85,12 +77,11 @@ impl Writer { /// ```no_run /// use async_attributes; /// use async_std::prelude::*; - /// use anyhow::Result; /// /// #[async_attributes::main] - /// async fn main() -> Result<()> { + /// async fn main() -> cacache::Result<()> { /// let mut fd = cacache::Writer::create("./my-cache", "my-key").await?; - /// fd.write_all(b"hello world").await?; + /// fd.write_all(b"hello world").await.expect("Failed to write to cache"); /// // Data is not saved into the cache until you commit it. /// fd.commit().await?; /// Ok(()) @@ -105,13 +96,6 @@ impl Writer { .algorithm(Algorithm::Sha256) .open(cache.as_ref(), key.as_ref()) .await - .with_context(|| { - format!( - "Failed to open a write handle for key {} for cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) } /// Closes the Writer handle and writes content and index entries. Also @@ -121,39 +105,20 @@ impl Writer { pub async fn commit(mut self) -> Result { let key = self.key; let cache = self.cache; - let writer_sri = self.writer.close().await.with_context(|| { - format!( - "Failed to properly close save file data for key {} in cache at {:?}", - key, cache - ) - })?; + let writer_sri = self.writer.close().await?; if let Some(sri) = &self.opts.sri { if sri.matches(&writer_sri).is_none() { - return Err(Error::IntegrityError(sri.clone(), writer_sri)).with_context(|| { - format!( - "Failed to verify data integrity while inserting {} into cache at {:?}", - key, cache - ) - })?; + return Err(ssri::Error::IntegrityCheckError(sri.clone(), writer_sri))?; } } else { self.opts.sri = Some(writer_sri); } if let Some(size) = self.opts.size { if size != self.written { - return Err(Error::SizeError(size, self.written)).with_context(|| { - format!("A size was passed in but the value inserted into {} could not be verified for cache at {:?}", key, cache) - })?; + return Err(Error::SizeError(size, self.written)); } } - index::insert_async(&cache, &key, self.opts) - .await - .with_context(|| { - format!( - "Failed to write index entry for {} in cache at {:?}", - key, cache - ) - }) + index::insert_async(&cache, &key, self.opts).await } } @@ -161,10 +126,9 @@ impl Writer { /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let data = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// Ok(()) /// } @@ -183,13 +147,7 @@ where cache.as_ref() ) })?; - writer.commit().with_context(|| { - format!( - "Failed to write to commit data for key {} for cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) + writer.commit() } /// Builder for options and flags for opening a new cache file to write data into. @@ -304,12 +262,11 @@ impl SyncWriter { /// /// ## Example /// ```no_run - /// use anyhow::Result; /// use std::io::prelude::*; /// - /// fn main() -> Result<()> { + /// fn main() -> cacache::Result<()> { /// let mut fd = cacache::SyncWriter::create("./my-cache", "my-key")?; - /// fd.write_all(b"hello world")?; + /// fd.write_all(b"hello world").expect("Failed to write to cache"); /// // Data is not saved into the cache until you commit it. /// fd.commit()?; /// Ok(()) @@ -323,13 +280,6 @@ impl SyncWriter { WriteOpts::new() .algorithm(Algorithm::Sha256) .open_sync(cache.as_ref(), key.as_ref()) - .with_context(|| { - format!( - "Failed to open a write handle for key {} for cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) } /// Closes the Writer handle and writes content and index entries. Also @@ -348,29 +298,17 @@ impl SyncWriter { if let Some(sri) = &self.opts.sri { // TODO - ssri should have a .matches method if sri.matches(&writer_sri).is_none() { - return Err(Error::IntegrityError(sri.clone(), writer_sri)).with_context(|| { - format!( - "Failed to verify data integrity while inserting {} into cache at {:?}", - key, cache - ) - })?; + return Err(ssri::Error::IntegrityCheckError(sri.clone(), writer_sri))?; } } else { self.opts.sri = Some(writer_sri); } if let Some(size) = self.opts.size { if size != self.written { - return Err(Error::SizeError(size, self.written)).with_context(|| { - format!("A size was passed in but the value inserted into {} could not be verified for cache at {:?}", key, cache) - })?; + return Err(Error::SizeError(size, self.written))?; } } - index::insert(&cache, &key, self.opts).with_context(|| { - format!( - "Failed to write index entry for {} in cache at {:?}", - key, cache - ) - }) + index::insert(&cache, &key, self.opts) } } diff --git a/src/rm.rs b/src/rm.rs index 87026c0..675a15b 100644 --- a/src/rm.rs +++ b/src/rm.rs @@ -4,10 +4,10 @@ use std::path::Path; use async_std::fs as afs; -use anyhow::{Context, Result}; use ssri::Integrity; use crate::content::rm; +use crate::errors::{Internal, Result}; use crate::index; /// Removes an individual index metadata entry. The associated content will be @@ -17,10 +17,9 @@ use crate::index; /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// /// cacache::remove("./my-cache", "my-key").await?; @@ -39,15 +38,7 @@ where P: AsRef, K: AsRef, { - index::delete_async(cache.as_ref(), key.as_ref()) - .await - .with_context(|| { - format!( - "Failed to delete cache entry for {} in cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) + index::delete_async(cache.as_ref(), key.as_ref()).await } /// Removes an individual content entry. Any index entries pointing to this @@ -57,10 +48,9 @@ where /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// /// cacache::remove_hash("./my-cache", &sri).await?; @@ -76,13 +66,7 @@ where /// } /// ``` pub async fn remove_hash>(cache: P, sri: &Integrity) -> Result<()> { - rm::rm_async(cache.as_ref(), &sri).await.with_context(|| { - format!( - "Failed to remove content under {} in cache at {:?}", - sri.to_string(), - cache.as_ref() - ) - }) + Ok(rm::rm_async(cache.as_ref(), &sri).await?) } /// Removes entire contents of the cache, including temporary files, the entry @@ -92,10 +76,9 @@ pub async fn remove_hash>(cache: P, sri: &Integrity) -> Result<() /// ```no_run /// use async_std::prelude::*; /// use async_attributes; -/// use anyhow::Result; /// /// #[async_attributes::main] -/// async fn main() -> Result<()> { +/// async fn main() -> cacache::Result<()> { /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// /// cacache::clear("./my-cache").await?; @@ -109,9 +92,9 @@ pub async fn remove_hash>(cache: P, sri: &Integrity) -> Result<() /// } /// ``` pub async fn clear>(cache: P) -> Result<()> { - for entry in cache.as_ref().read_dir()? { + for entry in cache.as_ref().read_dir().to_internal()? { if let Ok(entry) = entry { - afs::remove_dir_all(entry.path()).await?; + afs::remove_dir_all(entry.path()).await.to_internal()?; } } Ok(()) @@ -122,10 +105,9 @@ pub async fn clear>(cache: P) -> Result<()> { /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// /// cacache::remove_sync("./my-cache", "my-key")?; @@ -144,13 +126,7 @@ where P: AsRef, K: AsRef, { - index::delete(cache.as_ref(), key.as_ref()).with_context(|| { - format!( - "Failed to delete cache entry for {} in cache at {:?}", - key.as_ref(), - cache.as_ref() - ) - }) + index::delete(cache.as_ref(), key.as_ref()) } /// Removes an individual content entry synchronously. Any index entries @@ -158,10 +134,9 @@ where /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// /// cacache::remove_hash_sync("./my-cache", &sri)?; @@ -177,13 +152,7 @@ where /// } /// ``` pub fn remove_hash_sync>(cache: P, sri: &Integrity) -> Result<()> { - rm::rm(cache.as_ref(), &sri).with_context(|| { - format!( - "Failed to remove content under {} in cache at {:?}", - sri.to_string(), - cache.as_ref() - ) - }) + Ok(rm::rm(cache.as_ref(), &sri)?) } /// Removes entire contents of the cache synchronously, including temporary @@ -191,10 +160,9 @@ pub fn remove_hash_sync>(cache: P, sri: &Integrity) -> Result<()> /// /// ## Example /// ```no_run -/// use anyhow::Result; /// use std::io::Read; /// -/// fn main() -> Result<()> { +/// fn main() -> cacache::Result<()> { /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// /// cacache::clear_sync("./my-cache")?; @@ -208,9 +176,9 @@ pub fn remove_hash_sync>(cache: P, sri: &Integrity) -> Result<()> /// } /// ``` pub fn clear_sync>(cache: P) -> Result<()> { - for entry in cache.as_ref().read_dir()? { + for entry in cache.as_ref().read_dir().to_internal()? { if let Ok(entry) = entry { - fs::remove_dir_all(entry.path())?; + fs::remove_dir_all(entry.path()).to_internal()?; } } Ok(())