Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(error): improve error messages and file handling #334

Merged
merged 9 commits into from
Nov 18, 2024
46 changes: 44 additions & 2 deletions crates/backend/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@ impl LocalBackend {
}
Ok(())
}

/// Returns the parent path of the given file type and id.
///
/// # Arguments
///
/// * `tpe` - The type of the file.
/// * `id` - The id of the file.
///
/// # Returns
///
/// The parent path of the file or `None` if the file does not have a parent.
fn parent_path(&self, tpe: FileType, id: &Id) -> Option<PathBuf> {
let path = self.path(tpe, id);
path.parent().map(Path::to_path_buf)
}
}

impl ReadBackend for LocalBackend {
Expand Down Expand Up @@ -355,13 +370,14 @@ impl ReadBackend for LocalBackend {
length: u32,
) -> RusticResult<Bytes> {
trace!("reading tpe: {tpe:?}, id: {id}, offset: {offset}, length: {length}");
let mut file = File::open(self.path(tpe, id)).map_err(|err| {
let filename = self.path(tpe, id);
let mut file = File::open(filename.clone()).map_err(|err| {
RusticError::with_source(
ErrorKind::Backend,
"Failed to open the file `{path}`. Please check the file and try again.",
err,
)
.attach_context("path", self.path(tpe, id).to_string_lossy())
.attach_context("path", filename.to_string_lossy())
})?;
_ = file.seek(SeekFrom::Start(offset.into())).map_err(|err| {
RusticError::with_source(
Expand Down Expand Up @@ -459,6 +475,10 @@ impl WriteBackend for LocalBackend {
/// * If the length of the file could not be set.
/// * If the bytes could not be written to the file.
/// * If the OS Metadata could not be synced to disk.
/// * If the file does not have a parent directory.
/// * If the parent directory could not be created.
/// * If the file cannot be opened, due to missing permissions.
/// * If the file cannot be written to, due to lack of space on the disk.
fn write_bytes(
&self,
tpe: FileType,
Expand All @@ -469,6 +489,28 @@ impl WriteBackend for LocalBackend {
trace!("writing tpe: {:?}, id: {}", &tpe, &id);
let filename = self.path(tpe, id);

let Some(parent) = self.parent_path(tpe, id) else {
return Err(
RusticError::new(
ErrorKind::Backend,
"The file `{path}` does not have a parent directory. This may be empty or a root path. Please check the file and try again.",
)
.attach_context("path", filename.display().to_string())
.ask_report()
);
};

// create parent directory if it does not exist
fs::create_dir_all(parent.clone()).map_err(|err| {
RusticError::with_source(
ErrorKind::InputOutput,
"Failed to create directories `{path}`. Does the directory already exist? Please check the file and try again.",
err,
)
.attach_context("path", parent.display().to_string())
.ask_report()
})?;

let mut file = fs::OpenOptions::new()
.create(true)
.truncate(true)
Expand Down
8 changes: 7 additions & 1 deletion crates/core/src/commands/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,13 @@ pub(crate) fn check_repository<P: ProgressBars, S: Open>(

packs.into_par_iter().for_each(|pack| {
let id = pack.id;
let data = be.read_full(FileType::Pack, &id).unwrap();
let data = match be.read_full(FileType::Pack, &id) {
Ok(data) => data,
Err(err) => {
error!("Error reading data for pack {id} : {err}");
simonsan marked this conversation as resolved.
Show resolved Hide resolved
return;
}
};
match check_pack(be, pack, data, &p) {
Ok(()) => {}
Err(err) => error!("Error reading pack {id} : {err}",),
Expand Down
Loading