feat: remove anyhow and use custom error types

This commit is contained in:
Florian Albertz 2020-01-19 15:13:42 +01:00
parent a746fc0216
commit ea0938549b
10 changed files with 166 additions and 360 deletions

View File

@ -29,7 +29,6 @@ serde_derive = "1.0.102"
walkdir = "2.2.9" walkdir = "2.2.9"
either = "1.5.3" either = "1.5.3"
async-std = { version = "1.0.1", features = ["unstable"] } async-std = { version = "1.0.1", features = ["unstable"] }
anyhow = "1.0.19"
thiserror = "1.0.5" thiserror = "1.0.5"
futures = "0.3.1" futures = "0.3.1"

View File

@ -3,12 +3,12 @@ use std::path::Path;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use anyhow::Result;
use async_std; use async_std;
use futures::prelude::*; use futures::prelude::*;
use ssri::{Algorithm, Integrity, IntegrityChecker}; use ssri::{Algorithm, Integrity, IntegrityChecker};
use crate::content::path; use crate::content::path;
use crate::errors::{Internal, Result};
pub struct Reader { pub struct Reader {
fd: File, fd: File,
@ -55,7 +55,7 @@ impl AsyncReader {
pub fn open(cache: &Path, sri: Integrity) -> Result<Reader> { pub fn open(cache: &Path, sri: Integrity) -> Result<Reader> {
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
Ok(Reader { Ok(Reader {
fd: File::open(cpath)?, fd: File::open(cpath).to_internal()?,
checker: IntegrityChecker::new(sri), checker: IntegrityChecker::new(sri),
}) })
} }
@ -63,37 +63,37 @@ pub fn open(cache: &Path, sri: Integrity) -> Result<Reader> {
pub async fn open_async(cache: &Path, sri: Integrity) -> Result<AsyncReader> { pub async fn open_async(cache: &Path, sri: Integrity) -> Result<AsyncReader> {
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
Ok(AsyncReader { Ok(AsyncReader {
fd: async_std::fs::File::open(cpath).await?, fd: async_std::fs::File::open(cpath).await.to_internal()?,
checker: IntegrityChecker::new(sri), checker: IntegrityChecker::new(sri),
}) })
} }
pub fn read(cache: &Path, sri: &Integrity) -> Result<Vec<u8>> { pub fn read(cache: &Path, sri: &Integrity) -> Result<Vec<u8>> {
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
let ret = fs::read(&cpath)?; let ret = fs::read(&cpath).to_internal()?;
sri.check(&ret)?; sri.check(&ret)?;
Ok(ret) Ok(ret)
} }
pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result<Vec<u8>> { pub async fn read_async<'a>(cache: &'a Path, sri: &'a Integrity) -> Result<Vec<u8>> {
let cpath = path::content_path(&cache, &sri); 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)?; sri.check(&ret)?;
Ok(ret) Ok(ret)
} }
pub fn copy(cache: &Path, sri: &Integrity, to: &Path) -> Result<u64> { pub fn copy(cache: &Path, sri: &Integrity, to: &Path) -> Result<u64> {
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
let ret = fs::copy(&cpath, to)?; let ret = fs::copy(&cpath, to).to_internal()?;
let data = fs::read(cpath)?; let data = fs::read(cpath).to_internal()?;
sri.check(data)?; sri.check(data)?;
Ok(ret) Ok(ret)
} }
pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result<u64> { pub async fn copy_async<'a>(cache: &'a Path, sri: &'a Integrity, to: &'a Path) -> Result<u64> {
let cpath = path::content_path(&cache, &sri); let cpath = path::content_path(&cache, &sri);
let ret = async_std::fs::copy(&cpath, to).await?; let ret = async_std::fs::copy(&cpath, to).await.to_internal()?;
let data = async_std::fs::read(cpath).await?; let data = async_std::fs::read(cpath).await.to_internal()?;
sri.check(data)?; sri.check(data)?;
Ok(ret) Ok(ret)
} }

View File

@ -1,18 +1,20 @@
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use anyhow::Result;
use async_std::fs as afs; use async_std::fs as afs;
use ssri::Integrity; use ssri::Integrity;
use crate::content::path; use crate::content::path;
use crate::errors::{Internal, Result};
pub fn rm(cache: &Path, sri: &Integrity) -> 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(()) Ok(())
} }
pub async fn rm_async(cache: &Path, sri: &Integrity) -> Result<()> { 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(()) Ok(())
} }

View File

@ -4,7 +4,6 @@ use std::path::{Path, PathBuf};
use std::pin::Pin; use std::pin::Pin;
use std::sync::Mutex; use std::sync::Mutex;
use anyhow::Result;
use async_std::fs as afs; use async_std::fs as afs;
use async_std::future::Future; use async_std::future::Future;
use async_std::task::{self, Context, JoinHandle, Poll}; use async_std::task::{self, Context, JoinHandle, Poll};
@ -14,6 +13,7 @@ use ssri::{Algorithm, Integrity, IntegrityOpts};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use crate::content::path; use crate::content::path;
use crate::errors::{Internal, Result};
pub struct Writer { pub struct Writer {
cache: PathBuf, cache: PathBuf,
@ -26,11 +26,14 @@ impl Writer {
let cache_path = cache.to_path_buf(); let cache_path = cache.to_path_buf();
let mut tmp_path = cache_path.clone(); let mut tmp_path = cache_path.clone();
tmp_path.push("tmp"); tmp_path.push("tmp");
DirBuilder::new().recursive(true).create(&tmp_path)?; DirBuilder::new()
.recursive(true)
.create(&tmp_path)
.to_internal()?;
Ok(Writer { Ok(Writer {
cache: cache_path, cache: cache_path,
builder: IntegrityOpts::new().algorithm(algo), 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() DirBuilder::new()
.recursive(true) .recursive(true)
// Safe unwrap. cpath always has multiple segments // Safe unwrap. cpath always has multiple segments
.create(cpath.parent().unwrap())?; .create(cpath.parent().unwrap())
self.tmpfile.persist(cpath)?; .to_internal()?;
self.tmpfile.persist(cpath).to_internal()?;
Ok(sri) Ok(sri)
} }
} }
@ -87,11 +91,14 @@ impl AsyncWriter {
afs::DirBuilder::new() afs::DirBuilder::new()
.recursive(true) .recursive(true)
.create(&tmp_path) .create(&tmp_path)
.await?; .await
.to_internal()?;
Ok(AsyncWriter(Mutex::new(State::Idle(Some(Inner { Ok(AsyncWriter(Mutex::new(State::Idle(Some(Inner {
cache: cache_path, cache: cache_path,
builder: IntegrityOpts::new().algorithm(algo), 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![], buf: vec![],
last_op: None, last_op: None,
}))))) })))))
@ -101,7 +108,7 @@ impl AsyncWriter {
// NOTE: How do I even get access to `inner` safely??? // NOTE: How do I even get access to `inner` safely???
// let inner = ???; // let inner = ???;
// Blocking, but should be a very fast op. // 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(); let state = &mut *self.0.lock().unwrap();
loop { loop {
@ -121,12 +128,18 @@ impl AsyncWriter {
// Safe unwrap. cpath always has multiple segments // Safe unwrap. cpath always has multiple segments
.create(cpath.parent().unwrap()) .create(cpath.parent().unwrap())
.await .await
.map_err(anyhow::Error::new); .with_context(|| {
format!(
"building directory {} failed",
cpath.parent().unwrap().display()
)
});
if res.is_err() { if res.is_err() {
let _ = s.send(res.map(|_| sri)); let _ = s.send(res.map(|_| sri));
} else { } else {
let res = tmpfile.persist(cpath); let res = tmpfile.persist(cpath).with_context(|| {
let res = res.map_err(anyhow::Error::new); String::from("persisting tempfile failed")
});
let _ = s.send(res.map(|_| sri)); let _ = s.send(res.map(|_| sri));
} }
State::Idle(None) State::Idle(None)
@ -141,8 +154,10 @@ impl AsyncWriter {
} }
}) })
.map(|opt| opt.ok_or_else(|| io_error("file closed"))) .map(|opt| opt.ok_or_else(|| io_error("file closed")))
.await? .await
.await? .to_internal()?
.await
.to_internal()??)
} }
} }

View File

@ -1,8 +1,35 @@
use std::path::PathBuf; use std::path::PathBuf;
use ssri::Integrity;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)]
#[error("{source}\n\n {}", context.join("\n "))]
pub struct InternalError {
source: Box<dyn std::error::Error + Send + Sync>,
context: Vec<String>,
}
pub trait Internal<T> {
fn to_internal(self) -> InternalResult<T>;
fn with_context<F: FnOnce() -> String>(self, f: F) -> InternalResult<T>;
}
impl<T, E: 'static + std::error::Error + Send + Sync> Internal<T> for std::result::Result<T, E> {
fn to_internal(self) -> InternalResult<T> {
self.map_err(|e| InternalError {
source: Box::new(e),
context: Vec::new(),
})
}
fn with_context<F: FnOnce() -> String>(self, f: F) -> InternalResult<T> {
self.map_err(|e| InternalError {
source: Box::new(e),
context: vec![f()],
})
}
}
/// Error type returned by all API calls. /// Error type returned by all API calls.
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum Error { pub enum Error {
@ -10,10 +37,29 @@ pub enum Error {
/// lookup. /// lookup.
#[error("Entry not found for key {1:?} in cache {0:?}")] #[error("Entry not found for key {1:?} in cache {0:?}")]
EntryNotFound(PathBuf, String), 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. /// Returned when a size check has failed.
#[error("Size check failed.\n\tWanted: {0}\n\tActual: {1}")] #[error("Size check failed.\n\tWanted: {0}\n\tActual: {1}")]
SizeError(usize, usize), 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<T> = std::result::Result<T, Error>;
pub type InternalResult<T> = std::result::Result<T, InternalError>;

View File

@ -5,11 +5,10 @@ use std::task::{Context as TaskContext, Poll};
use futures::prelude::*; use futures::prelude::*;
use anyhow::{Context, Result};
use ssri::{Algorithm, Integrity}; use ssri::{Algorithm, Integrity};
use crate::content::read; use crate::content::read;
use crate::errors::Error; use crate::errors::{Error, Result};
use crate::index::{self, Metadata}; use crate::index::{self, Metadata};
// --------- // ---------
@ -47,22 +46,19 @@ impl Reader {
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[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 fd = cacache::Reader::open("./my-cache", "my-key").await?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
pub fn check(self) -> Result<Algorithm> { pub fn check(self) -> Result<Algorithm> {
self.reader self.reader.check()
.check()
.context("Cache read data verification check failed.")
} }
/// Opens a new file handle into the cache, looking it up in the index using /// Opens a new file handle into the cache, looking it up in the index using
/// `key`. /// `key`.
@ -71,13 +67,12 @@ impl Reader {
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[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 fd = cacache::Reader::open("./my-cache", "my-key").await?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
@ -104,14 +99,13 @@ impl Reader {
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "key", b"hello world").await?; /// let sri = cacache::write("./my-cache", "key", b"hello world").await?;
/// let mut fd = cacache::Reader::open_hash("./my-cache", sri).await?; /// let mut fd = cacache::Reader::open_hash("./my-cache", sri).await?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
@ -134,10 +128,9 @@ impl Reader {
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let data: Vec<u8> = cacache::read("./my-cache", "my-key").await?; /// let data: Vec<u8> = cacache::read("./my-cache", "my-key").await?;
/// Ok(()) /// 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<P, K>(cache: P, key: K) -> Result<String>
where
P: AsRef<Path>,
K: AsRef<str>,
{
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 /// Reads the entire contents of a cache file into a bytes vector, looking the
/// data up by its content address. /// data up by its content address.
/// ///
@ -194,10 +157,9 @@ where
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// let data: Vec<u8> = cacache::read_hash("./my-cache", &sri).await?; /// let data: Vec<u8> = cacache::read_hash("./my-cache", &sri).await?;
/// Ok(()) /// Ok(())
@ -210,31 +172,6 @@ where
Ok(read::read_async(cache.as_ref(), sri).await?) 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<P>(cache: P, sri: &Integrity) -> Result<String>
where
P: AsRef<Path>,
{
Ok(String::from_utf8(
read::read_async(cache.as_ref(), sri).await?,
)?)
}
/// Copies cache data to a specified location. Returns the number of bytes /// Copies cache data to a specified location. Returns the number of bytes
/// copied. /// copied.
/// ///
@ -242,10 +179,9 @@ where
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// cacache::copy("./my-cache", "my-key", "./data.txt").await?; /// cacache::copy("./my-cache", "my-key", "./data.txt").await?;
/// Ok(()) /// Ok(())
/// } /// }
@ -273,10 +209,9 @@ where
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello world").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello world").await?;
/// cacache::copy_hash("./my-cache", &sri, "./data.txt").await?; /// cacache::copy_hash("./my-cache", &sri, "./data.txt").await?;
/// Ok(()) /// Ok(())
@ -336,22 +271,19 @@ impl SyncReader {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?; /// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
pub fn check(self) -> Result<Algorithm> { pub fn check(self) -> Result<Algorithm> {
self.reader self.reader.check()
.check()
.context("Cache read data verification check failed.")
} }
/// Opens a new synchronous file handle into the cache, looking it up in the /// Opens a new synchronous file handle into the cache, looking it up in the
@ -359,13 +291,12 @@ impl SyncReader {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?; /// let mut fd = cacache::SyncReader::open("./my-cache", "my-key")?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
@ -390,14 +321,13 @@ impl SyncReader {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "key", b"hello world")?; /// let sri = cacache::write_sync("./my-cache", "key", b"hello world")?;
/// let mut fd = cacache::SyncReader::open_hash("./my-cache", sri)?; /// let mut fd = cacache::SyncReader::open_hash("./my-cache", sri)?;
/// let mut str = String::new(); /// 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! /// // Remember to check that the data you got was correct!
/// fd.check()?; /// fd.check()?;
/// Ok(()) /// Ok(())
@ -418,10 +348,9 @@ impl SyncReader {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let data = cacache::read_sync("./my-cache", "my-key")?; /// let data = cacache::read_sync("./my-cache", "my-key")?;
/// Ok(()) /// 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<P, K>(cache: P, key: K) -> Result<String>
where
P: AsRef<Path>,
K: AsRef<str>,
{
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 /// Reads the entire contents of a cache file synchronously into a bytes
/// vector, looking the data up by its content address. /// vector, looking the data up by its content address.
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// let data = cacache::read_hash_sync("./my-cache", &sri)?; /// let data = cacache::read_hash_sync("./my-cache", &sri)?;
/// Ok(()) /// Ok(())
@ -489,36 +390,14 @@ where
Ok(read::read(cache.as_ref(), sri)?) 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<P>(cache: P, sri: &Integrity) -> Result<String>
where
P: AsRef<Path>,
{
Ok(String::from_utf8(read::read(cache.as_ref(), sri)?)?)
}
/// Copies a cache entry by key to a specified location. Returns the number of /// Copies a cache entry by key to a specified location. Returns the number of
/// bytes copied. /// bytes copied.
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// cacache::copy_sync("./my-cache", "my-key", "./my-hello.txt")?; /// cacache::copy_sync("./my-cache", "my-key", "./my-hello.txt")?;
/// Ok(()) /// Ok(())
/// } /// }
@ -544,10 +423,9 @@ where
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// cacache::copy_hash_sync("./my-cache", &sri, "./my-hello.txt")?; /// cacache::copy_hash_sync("./my-cache", &sri, "./my-hello.txt")?;
/// Ok(()) /// Ok(())
@ -651,16 +529,6 @@ mod tests {
assert_eq!(data, b"hello world"); 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_attributes::test]
async fn test_read_hash() { async fn test_read_hash() {
let tmp = tempfile::tempdir().unwrap(); let tmp = tempfile::tempdir().unwrap();
@ -671,16 +539,6 @@ mod tests {
assert_eq!(data, b"hello world"); 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] #[test]
fn test_read_sync() { fn test_read_sync() {
let tmp = tempfile::tempdir().unwrap(); let tmp = tempfile::tempdir().unwrap();
@ -691,16 +549,6 @@ mod tests {
assert_eq!(data, b"hello world"); 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] #[test]
fn test_read_hash_sync() { fn test_read_hash_sync() {
let tmp = tempfile::tempdir().unwrap(); let tmp = tempfile::tempdir().unwrap();
@ -711,16 +559,6 @@ mod tests {
assert_eq!(data, b"hello world"); 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_attributes::test]
async fn test_copy() { async fn test_copy() {
let tmp = tempfile::tempdir().unwrap(); let tmp = tempfile::tempdir().unwrap();

View File

@ -5,7 +5,6 @@ use std::io::{ErrorKind, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::{Context, Result};
use async_std::fs as afs; use async_std::fs as afs;
use async_std::io::BufReader; use async_std::io::BufReader;
use digest::Digest; use digest::Digest;
@ -20,6 +19,7 @@ use sha2::Sha256;
use ssri::Integrity; use ssri::Integrity;
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::errors::{Internal, InternalResult, Result};
use crate::put::WriteOpts; use crate::put::WriteOpts;
const INDEX_VERSION: &str = "5"; const INDEX_VERSION: &str = "5";
@ -88,7 +88,8 @@ pub fn insert(cache: &Path, key: &str, opts: WriteOpts) -> Result<Integrity> {
let out = format!("\n{}\t{}", hash_entry(&stringified), stringified); let out = format!("\n{}\t{}", hash_entry(&stringified), stringified);
buck.write_all(out.as_bytes()) buck.write_all(out.as_bytes())
.with_context(|| format!("Failed to write to index bucket at {:?}", bucket))?; .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 Ok(opts
.sri .sri
.or_else(|| "sha1-deadbeef".parse::<Integrity>().ok()) .or_else(|| "sha1-deadbeef".parse::<Integrity>().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()) buck.write_all(out.as_bytes())
.await .await
.with_context(|| format!("Failed to write to index bucket at {:?}", bucket))?; .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 Ok(opts
.sri .sri
.or_else(|| "sha1-deadbeef".parse::<Integrity>().ok()) .or_else(|| "sha1-deadbeef".parse::<Integrity>().ok())
@ -223,7 +226,8 @@ pub fn ls(cache: &Path) -> impl Iterator<Item = Result<Metadata>> {
WalkDir::new(cache.join(format!("index-v{}", INDEX_VERSION))) WalkDir::new(cache.join(format!("index-v{}", INDEX_VERSION)))
.into_iter() .into_iter()
.map(|bucket| { .map(|bucket| {
let bucket = bucket?; let bucket = bucket.to_internal()?;
if bucket.file_type().is_dir() { if bucket.file_type().is_dir() {
return Ok(Vec::new()); return Ok(Vec::new());
} }
@ -281,13 +285,13 @@ fn now() -> u128 {
.as_millis() .as_millis()
} }
fn bucket_entries(bucket: &Path) -> Result<Vec<SerializableMetadata>> { fn bucket_entries(bucket: &Path) -> InternalResult<Vec<SerializableMetadata>> {
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
fs::File::open(bucket) fs::File::open(bucket)
.map(|file| { .map(|file| {
BufReader::new(file) BufReader::new(file)
.lines() .lines()
.filter_map(Result::ok) .filter_map(std::result::Result::ok)
.filter_map(|entry| { .filter_map(|entry| {
let entry_str = match entry.split('\t').collect::<Vec<&str>>()[..] { let entry_str = match entry.split('\t').collect::<Vec<&str>>()[..] {
[hash, entry_str] if hash_entry(entry_str) == hash => entry_str, [hash, entry_str] if hash_entry(entry_str) == hash => entry_str,
@ -302,19 +306,19 @@ fn bucket_entries(bucket: &Path) -> Result<Vec<SerializableMetadata>> {
if err.kind() == ErrorKind::NotFound { if err.kind() == ErrorKind::NotFound {
Ok(Vec::new()) Ok(Vec::new())
} else { } else {
Err(err)? Err(err).to_internal()?
} }
}) })
} }
async fn bucket_entries_async(bucket: &Path) -> Result<Vec<SerializableMetadata>> { async fn bucket_entries_async(bucket: &Path) -> InternalResult<Vec<SerializableMetadata>> {
let file_result = afs::File::open(bucket).await; let file_result = afs::File::open(bucket).await;
let file; let file;
if let Err(err) = file_result { if let Err(err) = file_result {
if err.kind() == ErrorKind::NotFound { if err.kind() == ErrorKind::NotFound {
return Ok(Vec::new()); return Ok(Vec::new());
} }
return Err(err.into()); return Err(err).to_internal()?;
} else { } else {
file = file_result.unwrap(); file = file_result.unwrap();
} }

View File

@ -35,10 +35,9 @@
//! //!
//! ```no_run //! ```no_run
//! use async_attributes; //! use async_attributes;
//! use anyhow::Result;
//! //!
//! #[async_attributes::main] //! #[async_attributes::main]
//! async fn main() -> Result<()> { //! async fn main() -> cacache::Result<()> {
//! // Data goes in... //! // Data goes in...
//! cacache::write("./my-cache", "key", b"hello").await?; //! cacache::write("./my-cache", "key", b"hello").await?;
//! //!
@ -60,10 +59,9 @@
//! //!
//! ```no_run //! ```no_run
//! use async_attributes; //! use async_attributes;
//! use anyhow::Result;
//! //!
//! #[async_attributes::main] //! #[async_attributes::main]
//! async fn main() -> Result<()> { //! async fn main() -> cacache::Result<()> {
//! // Data goes in... //! // Data goes in...
//! let sri = cacache::write("./my-cache", "key", b"hello").await?; //! let sri = cacache::write("./my-cache", "key", b"hello").await?;
//! //!
@ -81,15 +79,14 @@
//! an API reminiscent of `std::fs::OpenOptions`: //! an API reminiscent of `std::fs::OpenOptions`:
//! //!
//! ```no_run //! ```no_run
//! use anyhow::Result;
//! use async_attributes; //! use async_attributes;
//! use async_std::prelude::*; //! use async_std::prelude::*;
//! //!
//! #[async_attributes::main] //! #[async_attributes::main]
//! async fn main() -> Result<()> { //! async fn main() -> cacache::Result<()> {
//! let mut fd = cacache::Writer::create("./my-cache", "key").await?; //! let mut fd = cacache::Writer::create("./my-cache", "key").await?;
//! for _ in 0..10 { //! 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()`! //! // Data is only committed to the cache after you do `fd.commit()`!
//! let sri = fd.commit().await?; //! let sri = fd.commit().await?;
@ -97,7 +94,7 @@
//! //!
//! let mut fd = cacache::Reader::open("./my-cache", "key").await?; //! let mut fd = cacache::Reader::open("./my-cache", "key").await?;
//! let mut buf = String::new(); //! 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 //! // 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 //! // you just read is actually valid. `cacache` always verifies the data
@ -117,8 +114,7 @@
//! application, you probably want to use these instead. //! application, you probably want to use these instead.
//! //!
//! ```no_run //! ```no_run
//! use anyhow::Result; //! fn main() -> cacache::Result<()> {
//! fn main() -> Result<()> {
//! cacache::write_sync("./my-cache", "key", b"my-data").unwrap(); //! cacache::write_sync("./my-cache", "key", b"my-data").unwrap();
//! let data = cacache::read_sync("./my-cache", "key").unwrap(); //! let data = cacache::read_sync("./my-cache", "key").unwrap();
//! assert_eq!(data, b"my-data"); //! assert_eq!(data, b"my-data");
@ -139,7 +135,7 @@ mod ls;
mod put; mod put;
mod rm; mod rm;
pub use errors::Error; pub use errors::{Error, Result};
pub use index::Metadata; pub use index::Metadata;
pub use get::*; pub use get::*;

View File

@ -5,12 +5,11 @@ use std::pin::Pin;
use futures::prelude::*; use futures::prelude::*;
use anyhow::{Context, Result};
use serde_json::Value; use serde_json::Value;
use ssri::{Algorithm, Integrity}; use ssri::{Algorithm, Integrity};
use crate::content::write; use crate::content::write;
use crate::errors::Error; use crate::errors::{Error, Internal, Result};
use crate::index; use crate::index;
use std::task::{Context as TaskContext, Poll}; use std::task::{Context as TaskContext, Poll};
@ -20,10 +19,9 @@ use std::task::{Context as TaskContext, Poll};
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// cacache::write("./my-cache", "my-key", b"hello").await?; /// cacache::write("./my-cache", "my-key", b"hello").await?;
/// Ok(()) /// Ok(())
/// } /// }
@ -42,13 +40,7 @@ where
cache.as_ref() cache.as_ref()
) )
})?; })?;
writer.commit().await.with_context(|| { writer.commit().await
format!(
"Failed to write to commit data for key {} for cache at {:?}",
key.as_ref(),
cache.as_ref()
)
})
} }
/// A reference to an open file writing to the cache. /// A reference to an open file writing to the cache.
@ -85,12 +77,11 @@ impl Writer {
/// ```no_run /// ```no_run
/// use async_attributes; /// use async_attributes;
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let mut fd = cacache::Writer::create("./my-cache", "my-key").await?; /// 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. /// // Data is not saved into the cache until you commit it.
/// fd.commit().await?; /// fd.commit().await?;
/// Ok(()) /// Ok(())
@ -105,13 +96,6 @@ impl Writer {
.algorithm(Algorithm::Sha256) .algorithm(Algorithm::Sha256)
.open(cache.as_ref(), key.as_ref()) .open(cache.as_ref(), key.as_ref())
.await .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 /// Closes the Writer handle and writes content and index entries. Also
@ -121,39 +105,20 @@ impl Writer {
pub async fn commit(mut self) -> Result<Integrity> { pub async fn commit(mut self) -> Result<Integrity> {
let key = self.key; let key = self.key;
let cache = self.cache; let cache = self.cache;
let writer_sri = self.writer.close().await.with_context(|| { let writer_sri = self.writer.close().await?;
format!(
"Failed to properly close save file data for key {} in cache at {:?}",
key, cache
)
})?;
if let Some(sri) = &self.opts.sri { if let Some(sri) = &self.opts.sri {
if sri.matches(&writer_sri).is_none() { if sri.matches(&writer_sri).is_none() {
return Err(Error::IntegrityError(sri.clone(), writer_sri)).with_context(|| { return Err(ssri::Error::IntegrityCheckError(sri.clone(), writer_sri))?;
format!(
"Failed to verify data integrity while inserting {} into cache at {:?}",
key, cache
)
})?;
} }
} else { } else {
self.opts.sri = Some(writer_sri); self.opts.sri = Some(writer_sri);
} }
if let Some(size) = self.opts.size { if let Some(size) = self.opts.size {
if size != self.written { if size != self.written {
return Err(Error::SizeError(size, self.written)).with_context(|| { return Err(Error::SizeError(size, self.written));
format!("A size was passed in but the value inserted into {} could not be verified for cache at {:?}", key, cache)
})?;
} }
} }
index::insert_async(&cache, &key, self.opts) index::insert_async(&cache, &key, self.opts).await
.await
.with_context(|| {
format!(
"Failed to write index entry for {} in cache at {:?}",
key, cache
)
})
} }
} }
@ -161,10 +126,9 @@ impl Writer {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let data = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let data = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// Ok(()) /// Ok(())
/// } /// }
@ -183,13 +147,7 @@ where
cache.as_ref() cache.as_ref()
) )
})?; })?;
writer.commit().with_context(|| { writer.commit()
format!(
"Failed to write to commit data for key {} for cache at {:?}",
key.as_ref(),
cache.as_ref()
)
})
} }
/// Builder for options and flags for opening a new cache file to write data into. /// Builder for options and flags for opening a new cache file to write data into.
@ -304,12 +262,11 @@ impl SyncWriter {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::prelude::*; /// use std::io::prelude::*;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let mut fd = cacache::SyncWriter::create("./my-cache", "my-key")?; /// 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. /// // Data is not saved into the cache until you commit it.
/// fd.commit()?; /// fd.commit()?;
/// Ok(()) /// Ok(())
@ -323,13 +280,6 @@ impl SyncWriter {
WriteOpts::new() WriteOpts::new()
.algorithm(Algorithm::Sha256) .algorithm(Algorithm::Sha256)
.open_sync(cache.as_ref(), key.as_ref()) .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 /// Closes the Writer handle and writes content and index entries. Also
@ -348,29 +298,17 @@ impl SyncWriter {
if let Some(sri) = &self.opts.sri { if let Some(sri) = &self.opts.sri {
// TODO - ssri should have a .matches method // TODO - ssri should have a .matches method
if sri.matches(&writer_sri).is_none() { if sri.matches(&writer_sri).is_none() {
return Err(Error::IntegrityError(sri.clone(), writer_sri)).with_context(|| { return Err(ssri::Error::IntegrityCheckError(sri.clone(), writer_sri))?;
format!(
"Failed to verify data integrity while inserting {} into cache at {:?}",
key, cache
)
})?;
} }
} else { } else {
self.opts.sri = Some(writer_sri); self.opts.sri = Some(writer_sri);
} }
if let Some(size) = self.opts.size { if let Some(size) = self.opts.size {
if size != self.written { if size != self.written {
return Err(Error::SizeError(size, self.written)).with_context(|| { return Err(Error::SizeError(size, self.written))?;
format!("A size was passed in but the value inserted into {} could not be verified for cache at {:?}", key, cache)
})?;
} }
} }
index::insert(&cache, &key, self.opts).with_context(|| { index::insert(&cache, &key, self.opts)
format!(
"Failed to write index entry for {} in cache at {:?}",
key, cache
)
})
} }
} }

View File

@ -4,10 +4,10 @@ use std::path::Path;
use async_std::fs as afs; use async_std::fs as afs;
use anyhow::{Context, Result};
use ssri::Integrity; use ssri::Integrity;
use crate::content::rm; use crate::content::rm;
use crate::errors::{Internal, Result};
use crate::index; use crate::index;
/// Removes an individual index metadata entry. The associated content will be /// Removes an individual index metadata entry. The associated content will be
@ -17,10 +17,9 @@ use crate::index;
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// ///
/// cacache::remove("./my-cache", "my-key").await?; /// cacache::remove("./my-cache", "my-key").await?;
@ -39,15 +38,7 @@ where
P: AsRef<Path>, P: AsRef<Path>,
K: AsRef<str>, K: AsRef<str>,
{ {
index::delete_async(cache.as_ref(), key.as_ref()) index::delete_async(cache.as_ref(), key.as_ref()).await
.await
.with_context(|| {
format!(
"Failed to delete cache entry for {} in cache at {:?}",
key.as_ref(),
cache.as_ref()
)
})
} }
/// Removes an individual content entry. Any index entries pointing to this /// Removes an individual content entry. Any index entries pointing to this
@ -57,10 +48,9 @@ where
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// ///
/// cacache::remove_hash("./my-cache", &sri).await?; /// cacache::remove_hash("./my-cache", &sri).await?;
@ -76,13 +66,7 @@ where
/// } /// }
/// ``` /// ```
pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> { pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
rm::rm_async(cache.as_ref(), &sri).await.with_context(|| { Ok(rm::rm_async(cache.as_ref(), &sri).await?)
format!(
"Failed to remove content under {} in cache at {:?}",
sri.to_string(),
cache.as_ref()
)
})
} }
/// Removes entire contents of the cache, including temporary files, the entry /// Removes entire contents of the cache, including temporary files, the entry
@ -92,10 +76,9 @@ pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()
/// ```no_run /// ```no_run
/// use async_std::prelude::*; /// use async_std::prelude::*;
/// use async_attributes; /// use async_attributes;
/// use anyhow::Result;
/// ///
/// #[async_attributes::main] /// #[async_attributes::main]
/// async fn main() -> Result<()> { /// async fn main() -> cacache::Result<()> {
/// let sri = cacache::write("./my-cache", "my-key", b"hello").await?; /// let sri = cacache::write("./my-cache", "my-key", b"hello").await?;
/// ///
/// cacache::clear("./my-cache").await?; /// cacache::clear("./my-cache").await?;
@ -109,9 +92,9 @@ pub async fn remove_hash<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()
/// } /// }
/// ``` /// ```
pub async fn clear<P: AsRef<Path>>(cache: P) -> Result<()> { pub async fn clear<P: AsRef<Path>>(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 { if let Ok(entry) = entry {
afs::remove_dir_all(entry.path()).await?; afs::remove_dir_all(entry.path()).await.to_internal()?;
} }
} }
Ok(()) Ok(())
@ -122,10 +105,9 @@ pub async fn clear<P: AsRef<Path>>(cache: P) -> Result<()> {
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// ///
/// cacache::remove_sync("./my-cache", "my-key")?; /// cacache::remove_sync("./my-cache", "my-key")?;
@ -144,13 +126,7 @@ where
P: AsRef<Path>, P: AsRef<Path>,
K: AsRef<str>, K: AsRef<str>,
{ {
index::delete(cache.as_ref(), key.as_ref()).with_context(|| { index::delete(cache.as_ref(), key.as_ref())
format!(
"Failed to delete cache entry for {} in cache at {:?}",
key.as_ref(),
cache.as_ref()
)
})
} }
/// Removes an individual content entry synchronously. Any index entries /// Removes an individual content entry synchronously. Any index entries
@ -158,10 +134,9 @@ where
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// ///
/// cacache::remove_hash_sync("./my-cache", &sri)?; /// cacache::remove_hash_sync("./my-cache", &sri)?;
@ -177,13 +152,7 @@ where
/// } /// }
/// ``` /// ```
pub fn remove_hash_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> { pub fn remove_hash_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()> {
rm::rm(cache.as_ref(), &sri).with_context(|| { Ok(rm::rm(cache.as_ref(), &sri)?)
format!(
"Failed to remove content under {} in cache at {:?}",
sri.to_string(),
cache.as_ref()
)
})
} }
/// Removes entire contents of the cache synchronously, including temporary /// Removes entire contents of the cache synchronously, including temporary
@ -191,10 +160,9 @@ pub fn remove_hash_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()>
/// ///
/// ## Example /// ## Example
/// ```no_run /// ```no_run
/// use anyhow::Result;
/// use std::io::Read; /// use std::io::Read;
/// ///
/// fn main() -> Result<()> { /// fn main() -> cacache::Result<()> {
/// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?; /// let sri = cacache::write_sync("./my-cache", "my-key", b"hello")?;
/// ///
/// cacache::clear_sync("./my-cache")?; /// cacache::clear_sync("./my-cache")?;
@ -208,9 +176,9 @@ pub fn remove_hash_sync<P: AsRef<Path>>(cache: P, sri: &Integrity) -> Result<()>
/// } /// }
/// ``` /// ```
pub fn clear_sync<P: AsRef<Path>>(cache: P) -> Result<()> { pub fn clear_sync<P: AsRef<Path>>(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 { if let Ok(entry) = entry {
fs::remove_dir_all(entry.path())?; fs::remove_dir_all(entry.path()).to_internal()?;
} }
} }
Ok(()) Ok(())