diff --git a/src/cachefile.rs b/src/cachefile.rs index 861aab7..9d0dba3 100644 --- a/src/cachefile.rs +++ b/src/cachefile.rs @@ -63,15 +63,7 @@ impl CacheFile { bar: &ProgressBar, ) -> error::Result<()> { bar.set_message(format!("checking {:?}", file.get_name())); - - match file.check_hash(|bytes| bar.inc(bytes)) { - Ok(true) => Ok(()), - Ok(false) => Err(error::Error::unknown(format!( - "Hash mismatch for file {:?}!", - file.get_name() - ))), - Err(e) => Err(e.into()), - } + file.check_hash(|bytes| bar.inc(bytes)) } info!("checking files in {state:?}"); diff --git a/src/error.rs b/src/error.rs index 515f567..f636617 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,12 +26,15 @@ pub enum Error { #[error(transparent)] StdIo(#[from] std::io::Error), - #[error("response error: {0}")] + #[error("Response error: {0}")] Response(String), #[error("Invalid {0}")] InvalidParameter(Parameter), + #[error("Mismatch, expected {expected:?} but got {actual:?}")] + Mismatch { expected: String, actual: String }, + #[error("Unknown error: {0}")] Unknown(String), } @@ -59,14 +62,18 @@ impl Error { Self::Response(into_string(e)) } - pub fn unknown(e: impl ToString) -> Self { - Self::Unknown(into_string(e)) + pub fn mismatch(expected: impl ToString, actual: impl ToString) -> Self { + Self::Mismatch { + expected: into_string(expected), + actual: into_string(actual), + } } #[must_use] pub fn is_fatal(&self) -> bool { match self { Self::InvalidParameter(p) => p.is_fatal(), + Self::Mismatch { .. } => true, Self::Unknown(_) => true, _ => false, } diff --git a/src/file/checked.rs b/src/file/checked.rs index 07688f7..92e9ef7 100644 --- a/src/file/checked.rs +++ b/src/file/checked.rs @@ -53,12 +53,9 @@ impl Checked { } } - pub fn hash(&mut self, f: impl Fn(u64)) -> io::Result<()> { + pub fn hash(&mut self, f: impl Fn(u64)) -> error::Result<()> { if self.hash.is_some() { - return Err(io::Error::other(format!( - "file {:?} is already hashed!", - self.path.display() - ))); + return Err(error::Error::mismatch("unhashed file", self.path.display())); } self.hash = Some(super::compute_file_hash(&self.path, self.size, f)?); @@ -101,7 +98,7 @@ impl<'t> FileTrait<'t> for Checked { self.size } - fn check_hash(&self, on_progress: impl Fn(u64)) -> io::Result { + fn check_hash(&self, on_progress: impl Fn(u64)) -> error::Result<()> { super::check_file_hash(&self.path, self.size, self.hash.as_ref(), on_progress) } } diff --git a/src/file/mod.rs b/src/file/mod.rs index f2df684..95436a8 100644 --- a/src/file/mod.rs +++ b/src/file/mod.rs @@ -2,22 +2,19 @@ mod checked; mod chunk; mod uploading; -use std::{ - ffi::OsStr, - fs, - io::{self, Read}, - path::Path, -}; +use std::{ffi::OsStr, fs, io::Read, path::Path}; use base64ct::{Base64, Encoding}; use blake2b_simd::Params as Blake2b; pub use checked::Checked; pub use chunk::Chunk; -use log::debug; +use log::{debug, warn}; pub use uploading::Uploading; -fn compute_file_hash(path: &Path, size: u64, on_progress: impl Fn(u64)) -> io::Result { +use crate::error; + +fn compute_file_hash(path: &Path, size: u64, on_progress: impl Fn(u64)) -> error::Result { let mut file = fs::File::open(path)?; let mut hasher = Blake2b::new().hash_length(64).to_state(); @@ -36,9 +33,7 @@ fn compute_file_hash(path: &Path, size: u64, on_progress: impl Fn(u64)) -> io::R } if bytes_read != size { - return Err(io::Error::other(format!( - "Hashed {bytes_read:?} bytes, known file size {size:?}!" - ))); + return Err(error::Error::mismatch(size, bytes_read)); } let result = Base64::encode_string(hasher.finalize().as_bytes()); @@ -51,15 +46,20 @@ fn check_file_hash( size: u64, hash: Option<&String>, on_progress: impl Fn(u64), -) -> io::Result { - let Some(hash) = hash else { - debug!("no hash to check for {:?}!", path.display()); - return Ok(false); +) -> error::Result<()> { + let Some(expected) = hash else { + return Err(error::Error::mismatch("hash", path.display())); }; - let result = *hash == compute_file_hash(path, size, on_progress)?; - debug!("matches {:?}: {result:?}", *hash); - Ok(result) + let actual = &compute_file_hash(path, size, on_progress)?; + + if expected == actual { + debug!("hash matches {expected:?}"); + Ok(()) + } else { + warn!("hash mismatch for file {:?}", path.display()); + Err(error::Error::mismatch(expected, actual)) + } } pub trait FileTrait<'t> { @@ -80,5 +80,5 @@ pub trait FileTrait<'t> { /// get the file's size fn get_size(&self) -> u64; - fn check_hash(&self, on_progress: impl Fn(u64)) -> io::Result; + fn check_hash(&self, on_progress: impl Fn(u64)) -> error::Result<()>; } diff --git a/src/file/uploading.rs b/src/file/uploading.rs index 079317b..fec53b1 100644 --- a/src/file/uploading.rs +++ b/src/file/uploading.rs @@ -7,6 +7,8 @@ use std::{ use log::warn; use serde::{Deserialize, Serialize}; +use crate::error; + use super::{Checked, Chunk, FileTrait}; #[derive(Serialize, Deserialize, Debug)] @@ -101,7 +103,7 @@ impl<'t> FileTrait<'t> for Uploading { self.size } - fn check_hash(&self, on_progress: impl Fn(u64)) -> io::Result { + fn check_hash(&self, on_progress: impl Fn(u64)) -> error::Result<()> { super::check_file_hash(&self.path, self.size, self.hash.as_ref(), on_progress) } } diff --git a/src/impl_ureq.rs b/src/impl_ureq.rs index 1ffd188..99e083b 100644 --- a/src/impl_ureq.rs +++ b/src/impl_ureq.rs @@ -42,7 +42,7 @@ fn find_cause( error.into() } } - error => error::Error::unknown(error), + error => error::Error::Unknown(error.to_string()), } } diff --git a/src/output.rs b/src/output.rs index b10d5e2..4d1bca9 100644 --- a/src/output.rs +++ b/src/output.rs @@ -3,7 +3,7 @@ use std::{fmt, process, sync::LazyLock}; use console::{StyledObject, style}; use dialoguer::{Confirm, Select, theme::ColorfulTheme}; use indicatif::{ProgressBar, ProgressStyle}; -use log::{error, info}; +use log::{info, warn}; type StaticStyled<'t> = LazyLock>; @@ -95,7 +95,7 @@ impl Log { pub fn handle(e: &crate::error::Error) { if e.is_fatal() { // react to fatal error - error!("fatal error: {e:?}"); + warn!("fatal error: {e:?}"); Self::error(e); } diff --git a/src/sharry/client.rs b/src/sharry/client.rs index 517a40a..ddb914c 100644 --- a/src/sharry/client.rs +++ b/src/sharry/client.rs @@ -32,9 +32,10 @@ pub trait Client { { Ok(fid) } else { - Err(error::Error::unknown(format!( - "Could not extract File ID from {uri:?}" - ))) + Err(error::Error::mismatch( + ":///api/v2/alias/upload//files/tus/", + uri, + )) } }