create Error::Mismatch variant
This commit is contained in:
parent
9de8f948dc
commit
b17f239801
8 changed files with 43 additions and 44 deletions
|
|
@ -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:?}");
|
||||
|
|
|
|||
13
src/error.rs
13
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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<bool> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> {
|
||||
use crate::error;
|
||||
|
||||
fn compute_file_hash(path: &Path, size: u64, on_progress: impl Fn(u64)) -> error::Result<String> {
|
||||
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<bool> {
|
||||
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<bool>;
|
||||
fn check_hash(&self, on_progress: impl Fn(u64)) -> error::Result<()>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<bool> {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ fn find_cause(
|
|||
error.into()
|
||||
}
|
||||
}
|
||||
error => error::Error::unknown(error),
|
||||
error => error::Error::Unknown(error.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<StyledObject<&'t str>>;
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
"<proto>://<base>/api/v2/alias/upload/<share>/files/tus/<file>",
|
||||
uri,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue