summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2022-10-06 09:00:00 +0300
committerLars Wirzenius <liw@liw.fi>2022-10-06 09:04:41 +0300
commitbd46378ac4b20701bb9b105c1227074c2e1bf0e0 (patch)
treec3d29d9b968c6fe6e9a10de174c55f17ed724d5f /src
parent8246e3b8f6982410f255953aa6e210a35f88ca3f (diff)
downloadcachedir-rs-bd46378ac4b20701bb9b105c1227074c2e1bf0e0.tar.gz
refactor: use custom error type instead of anyhow
This is tidier and less magic. Sponsored-by: author
Diffstat (limited to 'src')
-rw-r--r--src/bin/cachedir.rs39
-rw-r--r--src/lib.rs22
2 files changed, 42 insertions, 19 deletions
diff --git a/src/bin/cachedir.rs b/src/bin/cachedir.rs
index 0675248..965a14d 100644
--- a/src/bin/cachedir.rs
+++ b/src/bin/cachedir.rs
@@ -12,9 +12,10 @@
//! $
//! ~~~
-use cachedir::{is_cachedir_tag, CACHEDIR_TAG, TAG};
+use cachedir::{is_cachedir_tag, CacheDirError, CACHEDIR_TAG, TAG};
use clap::{Parser, Subcommand};
use std::fs::{remove_file, write};
+use std::error::Error;
use std::path::PathBuf;
use walkdir::{DirEntry, WalkDir};
@@ -22,20 +23,26 @@ use walkdir::{DirEntry, WalkDir};
fn main() {
if let Err(e) = real_main() {
eprintln!("ERROR: {}", e);
+
+ let mut e = e.source();
+ while let Some(err) = e {
+ eprintln!("caused by: {}", err);
+ e = err.source();
+ }
+
std::process::exit(1);
}
}
/// Fallible main program.
-fn real_main() -> anyhow::Result<()> {
+fn real_main() -> Result<(), CacheDirError> {
let args = Args::parse();
match args.cmd {
- Command::Find { dirs } => walk(&dirs, find)?,
- Command::Tag { dirs } => walk(&dirs, tag)?,
- Command::Untag { dirs } => walk(&dirs, untag)?,
- Command::IsCache { dir } => is_cache(dir)?,
+ Command::Find { dirs } => walk(&dirs, find),
+ Command::Tag { dirs } => walk(&dirs, tag),
+ Command::Untag { dirs } => walk(&dirs, untag),
+ Command::IsCache { dir } => is_cache(dir),
}
- Ok(())
}
/// Command line arguments.
@@ -59,7 +66,7 @@ enum Command {
}
/// Is the given directory a cache?
-fn is_cache(dir: PathBuf) -> Result<(), std::io::Error> {
+fn is_cache(dir: PathBuf) -> Result<(), CacheDirError> {
let filename = dir.join(CACHEDIR_TAG);
if !is_cachedir_tag(&filename)? {
std::process::exit(1);
@@ -68,7 +75,7 @@ fn is_cache(dir: PathBuf) -> Result<(), std::io::Error> {
}
/// Is the given directory a cache?
-fn find(entry: &DirEntry) -> Result<(), std::io::Error> {
+fn find(entry: &DirEntry) -> Result<(), CacheDirError> {
let filename = tag_filename(entry);
if is_cachedir_tag(&filename)? {
println!("{}", entry.path().display());
@@ -77,31 +84,31 @@ fn find(entry: &DirEntry) -> Result<(), std::io::Error> {
}
/// Add a tag file to the given directory.
-fn tag(entry: &DirEntry) -> Result<(), std::io::Error> {
+fn tag(entry: &DirEntry) -> Result<(), CacheDirError> {
let filename = tag_filename(entry);
if !is_cachedir_tag(&filename)? {
- write(filename, TAG)?;
+ write(&filename, TAG).map_err(|e| CacheDirError::Write(filename.clone(), e))?;
}
Ok(())
}
/// Remove a tag file from the given directory.
-fn untag(entry: &DirEntry) -> Result<(), std::io::Error> {
+fn untag(entry: &DirEntry) -> Result<(), CacheDirError> {
let filename = tag_filename(entry);
if is_cachedir_tag(&filename)? {
- remove_file(filename)?;
+ remove_file(&filename).map_err(|e| CacheDirError::Remove(filename.clone(), e))?;
}
Ok(())
}
/// Iterate over all directories, call given function for each.
-fn walk<F>(dirs: &[PathBuf], mut func: F) -> Result<(), std::io::Error>
+fn walk<F>(dirs: &[PathBuf], mut func: F) -> Result<(), CacheDirError>
where
- F: FnMut(&DirEntry) -> Result<(), std::io::Error>,
+ F: FnMut(&DirEntry) -> Result<(), CacheDirError>,
{
for dir in dirs {
for entry in WalkDir::new(dir) {
- let entry = entry?;
+ let entry = entry.map_err(CacheDirError::WalkDir)?;
if entry.metadata()?.is_dir() {
func(&entry)?;
}
diff --git a/src/lib.rs b/src/lib.rs
index 5c01557..40f4f11 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,5 +1,5 @@
use std::fs::read;
-use std::path::Path;
+use std::path::{Path, PathBuf};
/// Name of tag file.
pub const CACHEDIR_TAG: &str = "CACHEDIR.TAG";
@@ -8,7 +8,7 @@ pub const CACHEDIR_TAG: &str = "CACHEDIR.TAG";
pub const TAG: &str = "Signature: 8a477f597d28d172789f06886806bc55";
/// Is a given file a cache directory tag?
-pub fn is_cachedir_tag(filename: &Path) -> Result<bool, std::io::Error> {
+pub fn is_cachedir_tag(filename: &Path) -> Result<bool, CacheDirError> {
// Is the filename OK?
if let Some(basename) = filename.file_name() {
if basename != CACHEDIR_TAG {
@@ -23,10 +23,26 @@ pub fn is_cachedir_tag(filename: &Path) -> Result<bool, std::io::Error> {
}
// Does the file start with the right prefix?
- let data = read(filename)?;
+ let data = read(filename)
+ .map_err(|e| CacheDirError::Read(filename.into(), e))?;
if data.len() >= TAG.len() {
Ok(&data[..TAG.len()] == TAG.as_bytes())
} else {
Ok(false)
}
}
+
+#[derive(Debug, thiserror::Error)]
+pub enum CacheDirError {
+ #[error("failed to read file {0}")]
+ Read(PathBuf, #[source] std::io::Error),
+
+ #[error("failed to write file {0}")]
+ Write(PathBuf, #[source] std::io::Error),
+
+ #[error("failed to delete file {0}")]
+ Remove(PathBuf, #[source] std::io::Error),
+
+ #[error(transparent)]
+ WalkDir(#[from] walkdir::Error),
+}