diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 466dc9f..2c52766 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -292,3 +292,26 @@ jobs: # with: # name: 'ouch-x86_64-pc-windows-gnu' # path: target\x86_64-pc-windows-gnu\release\ouch.exe + + fmt: + name: Check sourcecode format + runs-on: ubuntu-latest + + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + target: x86_64-unknown-linux-musl + components: rustfmt + override: true + + - name: Check format with cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check diff --git a/Cargo.lock b/Cargo.lock index 758456c..75733f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,6 +157,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fs-err" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ebd3504ad6116843b8375ad70df74e7bfe83cac77a1f3fe73200c844d43bfe0" + [[package]] name = "getrandom" version = "0.2.3" @@ -294,6 +300,7 @@ dependencies = [ "clap", "clap_generate", "flate2", + "fs-err", "infer", "libc", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index e9d9b02..f290ac0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ description = "A command-line utility for easily compressing and decompressing f [dependencies] clap = "=3.0.0-beta.5" # Keep it pinned while in beta! atty = "0.2.14" +fs-err = "2.6.0" once_cell = "1.8.0" walkdir = "2.3.2" bzip2 = "0.4.3" diff --git a/src/archive/tar.rs b/src/archive/tar.rs index 7106392..4c0d96e 100644 --- a/src/archive/tar.rs +++ b/src/archive/tar.rs @@ -1,15 +1,17 @@ //! Contains Tar-specific building and unpacking functions use std::{ - env, fs, + env, io::prelude::*, path::{Path, PathBuf}, }; +use fs_err as fs; use tar; use walkdir::WalkDir; use crate::{ + error::FinalError, info, utils::{self, Bytes}, QuestionPolicy, @@ -63,7 +65,12 @@ where builder.append_dir(path, path)?; } else { let mut file = fs::File::open(path)?; - builder.append_file(path, &mut file)?; + builder.append_file(path, file.file_mut()).map_err(|err| { + FinalError::with_title("Could not create archive") + .detail("Unexpected error while trying to read file") + .detail(format!("Error: {}.", err)) + .into_owned() + })?; } } env::set_current_dir(previous_location)?; diff --git a/src/archive/zip.rs b/src/archive/zip.rs index 3cce681..a43af53 100644 --- a/src/archive/zip.rs +++ b/src/archive/zip.rs @@ -1,11 +1,13 @@ //! Contains Zip-specific building and unpacking functions use std::{ - env, fs, + env, io::{self, prelude::*}, path::{Path, PathBuf}, }; +use fs_err as fs; + use walkdir::WalkDir; use zip::{self, read::ZipFile, ZipArchive}; @@ -127,10 +129,11 @@ fn check_for_comments(file: &ZipFile) { #[cfg(unix)] fn __unix_set_permissions(file_path: &Path, file: &ZipFile) -> crate::Result<()> { + use std::fs::Permissions; use std::os::unix::fs::PermissionsExt; if let Some(mode) = file.unix_mode() { - fs::set_permissions(file_path, fs::Permissions::from_mode(mode))?; + fs::set_permissions(file_path, Permissions::from_mode(mode))?; } Ok(()) diff --git a/src/cli.rs b/src/cli.rs index 7f57c14..4ef39ec 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -6,6 +6,7 @@ use std::{ }; use clap::Parser; +use fs_err as fs; use crate::{Error, Opts, QuestionPolicy, Subcommand}; @@ -31,7 +32,7 @@ impl Opts { } fn canonicalize(path: impl AsRef) -> crate::Result { - match std::fs::canonicalize(&path.as_ref()) { + match fs::canonicalize(&path.as_ref()) { Ok(abs_path) => Ok(abs_path), Err(io_err) => { if !path.as_ref().exists() { diff --git a/src/commands.rs b/src/commands.rs index 75de550..f58753a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -3,11 +3,11 @@ //! Also, where correctly call functions based on the detected `Command`. use std::{ - fs, io::{self, BufReader, BufWriter, Read, Write}, path::{Path, PathBuf}, }; +use fs_err as fs; use utils::colors; use crate::{ diff --git a/src/error.rs b/src/error.rs index a8dd654..4773970 100644 --- a/src/error.rs +++ b/src/error.rs @@ -21,7 +21,7 @@ pub enum Error { FileNotFound(PathBuf), AlreadyExists, InvalidZipArchive(&'static str), - PermissionDenied, + PermissionDenied { error_title: String }, UnsupportedZipArchive(&'static str), InternalError, CompressingRootFolder, @@ -78,6 +78,10 @@ impl FinalError { self.hints.push(hint.to_string()); self } + + pub fn into_owned(&mut self) -> Self { + std::mem::take(self) + } } impl fmt::Display for Error { @@ -134,7 +138,9 @@ impl fmt::Display for Error { Error::UnknownExtensionError(_) => todo!(), Error::AlreadyExists => todo!(), Error::InvalidZipArchive(_) => todo!(), - Error::PermissionDenied => todo!(), + Error::PermissionDenied { error_title } => { + FinalError::with_title(error_title).detail("Permission denied").to_owned() + } Error::UnsupportedZipArchive(_) => todo!(), Error::Custom { reason } => reason.clone(), }; @@ -152,8 +158,8 @@ impl Error { impl From for Error { fn from(err: std::io::Error) -> Self { match err.kind() { - std::io::ErrorKind::NotFound => panic!("{}", err), - std::io::ErrorKind::PermissionDenied => Self::PermissionDenied, + std::io::ErrorKind::NotFound => todo!(), + std::io::ErrorKind::PermissionDenied => Self::PermissionDenied { error_title: err.to_string() }, std::io::ErrorKind::AlreadyExists => Self::AlreadyExists, _other => Self::IoError { reason: err.to_string() }, } @@ -177,3 +183,9 @@ impl From for Error { Self::WalkdirError { reason: err.to_string() } } } + +impl From for Error { + fn from(err: FinalError) -> Self { + Self::Custom { reason: err } + } +} diff --git a/src/utils.rs b/src/utils.rs index 7c3a0e7..3c77495 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,16 +1,17 @@ use std::{ cmp, env, ffi::OsStr, - fs::{self, ReadDir}, path::Component, path::{Path, PathBuf}, }; +use fs_err as fs; + use crate::{dialogs::Confirmation, info}; /// Checks if the given path represents an empty directory. pub fn dir_is_empty(dir_path: &Path) -> bool { - let is_empty = |mut rd: ReadDir| rd.next().is_none(); + let is_empty = |mut rd: std::fs::ReadDir| rd.next().is_none(); dir_path.read_dir().map(is_empty).unwrap_or_default() } diff --git a/tests/compress_and_decompress.rs b/tests/compress_and_decompress.rs index 6422953..2b6efa1 100644 --- a/tests/compress_and_decompress.rs +++ b/tests/compress_and_decompress.rs @@ -1,13 +1,15 @@ mod utils; use std::{ - env, fs, + env, io::prelude::*, path::{Path, PathBuf}, time::Duration, }; use ouch::{commands::run, Opts, QuestionPolicy, Subcommand}; + +use fs_err as fs; use rand::{rngs::SmallRng, RngCore, SeedableRng}; use tempfile::NamedTempFile; use utils::*; diff --git a/tests/utils.rs b/tests/utils.rs index 9ee7c7c..e085ec0 100644 --- a/tests/utils.rs +++ b/tests/utils.rs @@ -2,10 +2,9 @@ #![allow(dead_code)] -use std::{ - fs, - path::{Path, PathBuf}, -}; +use std::path::{Path, PathBuf}; + +use fs_err as fs; use ouch::{commands::run, Opts, QuestionPolicy, Subcommand};