From 8af3ff10e2347da70c35eb45046f8a04843f7256 Mon Sep 17 00:00:00 2001 From: boastful-squirrel Date: Sun, 21 Apr 2019 16:27:34 +0200 Subject: Rework error system + avoid panics in main() --- src/archive.rs | 106 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 48 deletions(-) (limited to 'src/archive.rs') diff --git a/src/archive.rs b/src/archive.rs index 4703c0d..00d2901 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -1,6 +1,5 @@ use actix_web::http::ContentEncoding; use bytes::Bytes; -use failure::ResultExt; use libflate::gzip::Encoder; use serde::Deserialize; use std::io; @@ -8,7 +7,7 @@ use std::path::PathBuf; use strum_macros::{Display, EnumIter, EnumString}; use tar::Builder; -use crate::errors; +use crate::errors::{ContextualError, ContextualErrorKind}; /// Available compression methods #[derive(Deserialize, Clone, EnumIter, EnumString, Display)] @@ -47,45 +46,47 @@ pub fn create_archive( method: &CompressionMethod, dir: &PathBuf, skip_symlinks: bool, -) -> Result<(String, Bytes), errors::CompressionError> { +) -> Result<(String, Bytes), ContextualError> { match method { CompressionMethod::TarGz => tgz_compress(&dir, skip_symlinks), } } /// Compresses a given folder in .tar.gz format, and returns the result as a stream of bytes -fn tgz_compress( - dir: &PathBuf, - skip_symlinks: bool, -) -> Result<(String, Bytes), errors::CompressionError> { +fn tgz_compress(dir: &PathBuf, skip_symlinks: bool) -> Result<(String, Bytes), ContextualError> { let src_dir = dir.display().to_string(); let inner_folder = match dir.file_name() { Some(directory_name) => match directory_name.to_str() { Some(directory) => directory, None => { - return Err(errors::CompressionError::new( - errors::CompressionErrorKind::InvalidUTF8DirectoryName, - )) + // https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_str + return Err(ContextualError::new(ContextualErrorKind::InvalidPathError( + "Directory name contains invalid UTF-8 characters".to_string(), + ))); } }, None => { - return Err(errors::CompressionError::new( - errors::CompressionErrorKind::InvalidDirectoryName, - )) + // https://doc.rust-lang.org/std/path/struct.Path.html#method.file_name + return Err(ContextualError::new(ContextualErrorKind::InvalidPathError( + "Directory name terminates in \"..\"".to_string(), + ))); } }; let dst_filename = format!("{}.tar", inner_folder); let dst_tgz_filename = format!("{}.gz", dst_filename); - let tar_content = tar(src_dir, inner_folder.to_string(), skip_symlinks).context( - errors::CompressionErrorKind::TarBuildingError { - message: "an error occured while writing the TAR archive".to_string(), - }, - )?; - let gz_data = gzip(&tar_content).context(errors::CompressionErrorKind::GZipBuildingError { - message: "an error occured while writing the GZIP archive".to_string(), + let tar_content = tar(src_dir, inner_folder.to_string(), skip_symlinks).map_err(|e| { + ContextualError::new(ContextualErrorKind::ArchiveCreationError( + "tarball".to_string(), + Box::new(e), + )) + })?; + let gz_data = gzip(&tar_content).map_err(|e| { + ContextualError::new(ContextualErrorKind::ArchiveCreationError( + "GZIP archive".to_string(), + Box::new(e), + )) })?; - let mut data = Bytes::new(); data.extend_from_slice(&gz_data); @@ -97,44 +98,53 @@ fn tar( src_dir: String, inner_folder: String, skip_symlinks: bool, -) -> Result, errors::CompressionError> { +) -> Result, ContextualError> { let mut tar_builder = Builder::new(Vec::new()); tar_builder.follow_symlinks(!skip_symlinks); // Recursively adds the content of src_dir into the archive stream - tar_builder.append_dir_all(inner_folder, &src_dir).context( - errors::CompressionErrorKind::TarBuildingError { - message: format!( - "failed to append the content of {} to the TAR archive", - &src_dir - ), - }, - )?; + tar_builder + .append_dir_all(inner_folder, &src_dir) + .map_err(|e| { + ContextualError::new(ContextualErrorKind::IOError( + format!( + "Failed to append the content of {} to the TAR archive", + &src_dir + ), + e, + )) + })?; - let tar_content = - tar_builder - .into_inner() - .context(errors::CompressionErrorKind::TarBuildingError { - message: "failed to finish writing the TAR archive".to_string(), - })?; + let tar_content = tar_builder.into_inner().map_err(|e| { + ContextualError::new(ContextualErrorKind::IOError( + "Failed to finish writing the TAR archive".to_string(), + e, + )) + })?; Ok(tar_content) } /// Compresses a stream of bytes using the GZIP algorithm, and returns the resulting stream -fn gzip(mut data: &[u8]) -> Result, errors::CompressionError> { - let mut encoder = - Encoder::new(Vec::new()).context(errors::CompressionErrorKind::GZipBuildingError { - message: "failed to create GZIP encoder".to_string(), - })?; - io::copy(&mut data, &mut encoder).context(errors::CompressionErrorKind::GZipBuildingError { - message: "failed to write GZIP data".to_string(), +fn gzip(mut data: &[u8]) -> Result, ContextualError> { + let mut encoder = Encoder::new(Vec::new()).map_err(|e| { + ContextualError::new(ContextualErrorKind::IOError( + "Failed to create GZIP encoder".to_string(), + e, + )) + })?; + io::copy(&mut data, &mut encoder).map_err(|e| { + ContextualError::new(ContextualErrorKind::IOError( + "Failed to write GZIP data".to_string(), + e, + )) + })?; + let data = encoder.finish().into_result().map_err(|e| { + ContextualError::new(ContextualErrorKind::IOError( + "Failed to write GZIP trailer".to_string(), + e, + )) })?; - let data = encoder.finish().into_result().context( - errors::CompressionErrorKind::GZipBuildingError { - message: "failed to write GZIP trailer".to_string(), - }, - )?; Ok(data) } -- cgit v1.2.3 From 63572cf0fc2f94646e2736e27967ba985e5f7405 Mon Sep 17 00:00:00 2001 From: boastful-squirrel Date: Tue, 23 Apr 2019 19:52:42 +0200 Subject: Made code more idiomatic --- src/archive.rs | 69 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'src/archive.rs') diff --git a/src/archive.rs b/src/archive.rs index 00d2901..b5788f5 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -55,42 +55,41 @@ pub fn create_archive( /// Compresses a given folder in .tar.gz format, and returns the result as a stream of bytes fn tgz_compress(dir: &PathBuf, skip_symlinks: bool) -> Result<(String, Bytes), ContextualError> { let src_dir = dir.display().to_string(); - let inner_folder = match dir.file_name() { - Some(directory_name) => match directory_name.to_str() { - Some(directory) => directory, - None => { - // https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_str - return Err(ContextualError::new(ContextualErrorKind::InvalidPathError( - "Directory name contains invalid UTF-8 characters".to_string(), - ))); - } - }, - None => { - // https://doc.rust-lang.org/std/path/struct.Path.html#method.file_name - return Err(ContextualError::new(ContextualErrorKind::InvalidPathError( - "Directory name terminates in \"..\"".to_string(), - ))); - } - }; - let dst_filename = format!("{}.tar", inner_folder); - let dst_tgz_filename = format!("{}.gz", dst_filename); - - let tar_content = tar(src_dir, inner_folder.to_string(), skip_symlinks).map_err(|e| { - ContextualError::new(ContextualErrorKind::ArchiveCreationError( - "tarball".to_string(), - Box::new(e), - )) - })?; - let gz_data = gzip(&tar_content).map_err(|e| { - ContextualError::new(ContextualErrorKind::ArchiveCreationError( - "GZIP archive".to_string(), - Box::new(e), - )) - })?; - let mut data = Bytes::new(); - data.extend_from_slice(&gz_data); + if let Some(inner_folder) = dir.file_name() { + if let Some(directory) = inner_folder.to_str() { + let dst_filename = format!("{}.tar", directory); + let dst_tgz_filename = format!("{}.gz", dst_filename); + let mut tgz_data = Bytes::new(); - Ok((dst_tgz_filename, data)) + let tar_data = tar(src_dir, directory.to_string(), skip_symlinks).map_err(|e| { + ContextualError::new(ContextualErrorKind::ArchiveCreationError( + "tarball".to_string(), + Box::new(e), + )) + })?; + + let gz_data = gzip(&tar_data).map_err(|e| { + ContextualError::new(ContextualErrorKind::ArchiveCreationError( + "GZIP archive".to_string(), + Box::new(e), + )) + })?; + + tgz_data.extend_from_slice(&gz_data); + + Ok((dst_tgz_filename, tgz_data)) + } else { + // https://doc.rust-lang.org/std/ffi/struct.OsStr.html#method.to_str + Err(ContextualError::new(ContextualErrorKind::InvalidPathError( + "Directory name contains invalid UTF-8 characters".to_string(), + ))) + } + } else { + // https://doc.rust-lang.org/std/path/struct.Path.html#method.file_name + Err(ContextualError::new(ContextualErrorKind::InvalidPathError( + "Directory name terminates in \"..\"".to_string(), + ))) + } } /// Creates a TAR archive of a folder, and returns it as a stream of bytes -- cgit v1.2.3