mirror of
https://github.com/ouch-org/ouch.git
synced 2025-06-07 03:55:28 +00:00
Docs improvements
+ Removed some dead code
This commit is contained in:
parent
ebe3918478
commit
d2d4a929e1
@ -71,7 +71,6 @@ where
|
|||||||
FinalError::with_title("Could not create archive")
|
FinalError::with_title("Could not create archive")
|
||||||
.detail("Unexpected error while trying to read file")
|
.detail("Unexpected error while trying to read file")
|
||||||
.detail(format!("Error: {}.", err))
|
.detail(format!("Error: {}.", err))
|
||||||
.into_owned()
|
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
src/cli.rs
11
src/cli.rs
@ -1,6 +1,4 @@
|
|||||||
//! CLI configuration step, uses definitions from `opts.rs`.
|
//! CLI related functions, uses the clap argparsing definitions from `opts.rs`.
|
||||||
//!
|
|
||||||
//! Also used to treat some inputs.
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -13,8 +11,11 @@ use fs_err as fs;
|
|||||||
use crate::{Error, Opts, QuestionPolicy, Subcommand};
|
use crate::{Error, Opts, QuestionPolicy, Subcommand};
|
||||||
|
|
||||||
impl Opts {
|
impl Opts {
|
||||||
/// A helper method that calls `clap::Parser::parse` and then translates relative paths to absolute.
|
/// A helper method that calls `clap::Parser::parse`.
|
||||||
/// Also determines if the user wants to skip questions or not
|
///
|
||||||
|
/// And:
|
||||||
|
/// 1. Make paths absolute.
|
||||||
|
/// 2. Checks the QuestionPolicy.
|
||||||
pub fn parse_args() -> crate::Result<(Self, QuestionPolicy)> {
|
pub fn parse_args() -> crate::Result<(Self, QuestionPolicy)> {
|
||||||
let mut opts: Self = Self::parse();
|
let mut opts: Self = Self::parse();
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ fn represents_several_files(files: &[PathBuf]) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Entrypoint of ouch, receives cli options and matches Subcommand
|
/// Entrypoint of ouch, receives cli options and matches Subcommand
|
||||||
/// to decide current operation
|
/// to decide what to do
|
||||||
pub fn run(args: Opts, question_policy: QuestionPolicy) -> crate::Result<()> {
|
pub fn run(args: Opts, question_policy: QuestionPolicy) -> crate::Result<()> {
|
||||||
match args.cmd {
|
match args.cmd {
|
||||||
Subcommand::Compress { files, output: output_path } => {
|
Subcommand::Compress { files, output: output_path } => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Pretty (and colored) dialog for asking [Y/n] for the end user.
|
//! Pretty (and colored) dialog for asking [Y/n] for the end user.
|
||||||
//!
|
//!
|
||||||
//! Example:
|
//! Example:
|
||||||
//! "Do you want to overwrite 'archive.targz'? [Y/n]"
|
//! "Do you want to overwrite 'archive.tar.gz'? [Y/n]"
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@ -10,19 +10,21 @@ use std::{
|
|||||||
|
|
||||||
use crate::utils::colors;
|
use crate::utils::colors;
|
||||||
|
|
||||||
/// Represents a confirmation dialog
|
/// Confirmation dialog for end user with [Y/n] question.
|
||||||
|
///
|
||||||
|
/// If the placeholder is found in the prompt text, it will be replaced to form the final message.
|
||||||
pub struct Confirmation<'a> {
|
pub struct Confirmation<'a> {
|
||||||
/// Represents the message to the displayed
|
/// The message to be displayed with the placeholder text in it.
|
||||||
/// e.g.: "Do you want to overwrite 'FILE'?"
|
/// e.g.: "Do you want to overwrite 'FILE'?"
|
||||||
pub prompt: &'a str,
|
pub prompt: &'a str,
|
||||||
|
|
||||||
/// Represents a placeholder to be changed at runtime
|
/// The placeholder text that will be replaced in the `ask` function:
|
||||||
/// e.g.: Some("FILE")
|
/// e.g.: Some("FILE")
|
||||||
pub placeholder: Option<&'a str>,
|
pub placeholder: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Confirmation<'a> {
|
impl<'a> Confirmation<'a> {
|
||||||
/// New Confirmation
|
/// Creates a new Confirmation.
|
||||||
pub const fn new(prompt: &'a str, pattern: Option<&'a str>) -> Self {
|
pub const fn new(prompt: &'a str, pattern: Option<&'a str>) -> Self {
|
||||||
Self { prompt, placeholder: pattern }
|
Self { prompt, placeholder: pattern }
|
||||||
}
|
}
|
||||||
@ -35,20 +37,17 @@ impl<'a> Confirmation<'a> {
|
|||||||
(Some(placeholder), Some(subs)) => Cow::Owned(self.prompt.replace(placeholder, subs)),
|
(Some(placeholder), Some(subs)) => Cow::Owned(self.prompt.replace(placeholder, subs)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ask the same question to end while no valid answers are given
|
||||||
loop {
|
loop {
|
||||||
print!("{} [{}Y{}/{}n{}] ", message, *colors::GREEN, *colors::RESET, *colors::RED, *colors::RESET);
|
print!("{} [{}Y{}/{}n{}] ", message, *colors::GREEN, *colors::RESET, *colors::RED, *colors::RESET);
|
||||||
io::stdout().flush()?;
|
io::stdout().flush()?;
|
||||||
|
|
||||||
let mut answer = String::new();
|
let mut answer = String::new();
|
||||||
io::stdin().read_line(&mut answer)?;
|
io::stdin().read_line(&mut answer)?;
|
||||||
let trimmed_answer = answer.trim();
|
|
||||||
|
|
||||||
if trimmed_answer.is_empty() {
|
answer.make_ascii_lowercase();
|
||||||
return Ok(true);
|
match answer.trim() {
|
||||||
}
|
"" | "y" | "yes" => return Ok(true),
|
||||||
|
|
||||||
match trimmed_answer.to_ascii_lowercase().as_ref() {
|
|
||||||
"y" | "yes" => return Ok(true),
|
|
||||||
"n" | "no" => return Ok(false),
|
"n" | "no" => return Ok(false),
|
||||||
_ => continue, // Try again
|
_ => continue, // Try again
|
||||||
}
|
}
|
||||||
|
60
src/error.rs
60
src/error.rs
@ -1,12 +1,6 @@
|
|||||||
//! Error type definitions.
|
//! Error types definitions.
|
||||||
//!
|
//!
|
||||||
//! All the unexpected user-side errors should be treated in this file, that does not include
|
//! All usage errors will pass throught the Error enum, a lot of them in the Error::Custom.
|
||||||
//! errors made by devs in our implementation.
|
|
||||||
//!
|
|
||||||
//! TODO: wrap `FinalError` in a variant to keep all `FinalError::display_and_crash()` function
|
|
||||||
//! calls inside of this module.
|
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
@ -15,32 +9,64 @@ use std::{
|
|||||||
|
|
||||||
use crate::utils::colors::*;
|
use crate::utils::colors::*;
|
||||||
|
|
||||||
/// Custom Ouch Errors
|
/// All errors that can be generated by `ouch`
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
/// Extension found is not supported and known to ouch
|
||||||
UnknownExtensionError(String),
|
UnknownExtensionError(String),
|
||||||
|
/// TO BE REMOVED
|
||||||
MissingExtensionError(PathBuf),
|
MissingExtensionError(PathBuf),
|
||||||
IoError { reason: String },
|
/// Not every IoError, some of them get filtered by `From<io::Error>` into other variants
|
||||||
|
IoError {
|
||||||
|
/// TODO
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
/// Detected from io::Error if .kind() is io::ErrorKind::NotFound
|
||||||
FileNotFound(PathBuf),
|
FileNotFound(PathBuf),
|
||||||
|
/// TO BE REMOVED
|
||||||
AlreadyExists,
|
AlreadyExists,
|
||||||
|
/// TO BE REMOVED
|
||||||
InvalidZipArchive(&'static str),
|
InvalidZipArchive(&'static str),
|
||||||
PermissionDenied { error_title: String },
|
/// Detected from io::Error if .kind() is io::ErrorKind::PermissionDenied
|
||||||
|
PermissionDenied {
|
||||||
|
/// TODO
|
||||||
|
error_title: String,
|
||||||
|
},
|
||||||
|
/// TO BE REMOVED
|
||||||
UnsupportedZipArchive(&'static str),
|
UnsupportedZipArchive(&'static str),
|
||||||
|
/// TO BE REMOVED
|
||||||
InternalError,
|
InternalError,
|
||||||
|
/// TO BE REMOVED
|
||||||
CompressingRootFolder,
|
CompressingRootFolder,
|
||||||
|
/// TO BE REMOVED
|
||||||
MissingArgumentsForCompression,
|
MissingArgumentsForCompression,
|
||||||
|
/// TO BE REMOVED
|
||||||
MissingArgumentsForDecompression,
|
MissingArgumentsForDecompression,
|
||||||
|
/// TO BE REMOVED
|
||||||
CompressionTypo,
|
CompressionTypo,
|
||||||
WalkdirError { reason: String },
|
/// Specialized walkdir's io::Error wrapper with additional information on the error
|
||||||
Custom { reason: FinalError },
|
WalkdirError {
|
||||||
|
/// TODO
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
/// Custom and unique errors are reported in this variant
|
||||||
|
Custom {
|
||||||
|
/// TODO
|
||||||
|
reason: FinalError,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Alias to std's Result with ouch's Error
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
/// Pretty final error message for end users, crashing the program after display.
|
||||||
#[derive(Clone, Debug, Default, PartialEq)]
|
#[derive(Clone, Debug, Default, PartialEq)]
|
||||||
pub struct FinalError {
|
pub struct FinalError {
|
||||||
|
/// Should be made of just one line, appears after the "[ERROR]" part
|
||||||
title: String,
|
title: String,
|
||||||
|
/// Shown as a unnumbered list in yellow
|
||||||
details: Vec<String>,
|
details: Vec<String>,
|
||||||
|
/// Shown as green at the end to give hints on how to work around this error, if it's fixable
|
||||||
hints: Vec<String>,
|
hints: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,23 +94,22 @@ impl Display for FinalError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FinalError {
|
impl FinalError {
|
||||||
|
/// Only constructor
|
||||||
pub fn with_title(title: impl ToString) -> Self {
|
pub fn with_title(title: impl ToString) -> Self {
|
||||||
Self { title: title.to_string(), details: vec![], hints: vec![] }
|
Self { title: title.to_string(), details: vec![], hints: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add one detail line, can have multiple
|
||||||
pub fn detail(mut self, detail: impl ToString) -> Self {
|
pub fn detail(mut self, detail: impl ToString) -> Self {
|
||||||
self.details.push(detail.to_string());
|
self.details.push(detail.to_string());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add one hint line, can have multiple
|
||||||
pub fn hint(mut self, hint: impl ToString) -> Self {
|
pub fn hint(mut self, hint: impl ToString) -> Self {
|
||||||
self.hints.push(hint.to_string());
|
self.hints.push(hint.to_string());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_owned(&mut self) -> Self {
|
|
||||||
std::mem::take(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -151,6 +176,7 @@ impl fmt::Display for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
/// TO BE REMOVED
|
||||||
pub fn with_reason(reason: FinalError) -> Self {
|
pub fn with_reason(reason: FinalError) -> Self {
|
||||||
Self::Custom { reason }
|
Self::Custom { reason }
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ use self::CompressionFormat::*;
|
|||||||
/// A wrapper around `CompressionFormat` that allows combinations like `tgz`
|
/// A wrapper around `CompressionFormat` that allows combinations like `tgz`
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Extension {
|
pub struct Extension {
|
||||||
|
/// One extension like "tgz" can be made of multiple CompressionFormats ([Tar, Gz])
|
||||||
pub compression_formats: Vec<CompressionFormat>,
|
pub compression_formats: Vec<CompressionFormat>,
|
||||||
|
/// The input text for this extension, like "tgz", "tar" or "xz"
|
||||||
pub display_text: String,
|
pub display_text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,6 +28,7 @@ impl Extension {
|
|||||||
self.compression_formats[0].is_archive_format()
|
self.compression_formats[0].is_archive_format()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iteration to inner compression formats, useful for flat_mapping
|
||||||
pub fn iter(&self) -> impl Iterator<Item = &CompressionFormat> {
|
pub fn iter(&self) -> impl Iterator<Item = &CompressionFormat> {
|
||||||
self.compression_formats.iter()
|
self.compression_formats.iter()
|
||||||
}
|
}
|
||||||
@ -37,16 +40,21 @@ impl fmt::Display for Extension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
/// Accepted extensions for input and output
|
/// Accepted extensions for input and output
|
||||||
pub enum CompressionFormat {
|
pub enum CompressionFormat {
|
||||||
Gzip, // .gz
|
/// .gz
|
||||||
Bzip, // .bz
|
Gzip,
|
||||||
Lzma, // .lzma
|
/// .bz .bz2
|
||||||
Tar, // .tar (technically not a compression extension, but will do for now)
|
Bzip,
|
||||||
Zstd, // .zst
|
/// .xz .lzma .lz
|
||||||
Zip, // .zip
|
Lzma,
|
||||||
|
/// tar, tgz, tbz, tbz2, txz, tlz, tlzma, tzst
|
||||||
|
Tar,
|
||||||
|
/// .zst
|
||||||
|
Zstd,
|
||||||
|
/// .zip
|
||||||
|
Zip,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompressionFormat {
|
impl CompressionFormat {
|
||||||
|
10
src/lib.rs
10
src/lib.rs
@ -1,8 +1,4 @@
|
|||||||
//! This library is meant to be published, just used internally by our binary crate at `main.rs`.
|
//! This library isn't meant to be published, but used internally by our binary crate `main.rs`.
|
||||||
//!
|
|
||||||
//! A module shall be public only if:
|
|
||||||
//! 1. It's required by `main.rs`, or
|
|
||||||
//! 2. It's required by some integration tests at tests/ folder.
|
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
@ -17,12 +13,12 @@ pub mod error;
|
|||||||
pub mod extension;
|
pub mod extension;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
/// CLI configuration step, uses definitions from `opts.rs`, also used to treat some inputs.
|
/// CLI argparsing definitions, using `clap`.
|
||||||
pub mod opts;
|
pub mod opts;
|
||||||
|
|
||||||
pub use error::{Error, Result};
|
pub use error::{Error, Result};
|
||||||
pub use opts::{Opts, Subcommand};
|
pub use opts::{Opts, Subcommand};
|
||||||
pub use utils::QuestionPolicy;
|
pub use utils::QuestionPolicy;
|
||||||
|
|
||||||
/// The status code ouch has when an error is encountered
|
/// The status code returned from `ouch` on error
|
||||||
pub const EXIT_FAILURE: i32 = libc::EXIT_FAILURE;
|
pub const EXIT_FAILURE: i32 = libc::EXIT_FAILURE;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! Macros used on ouch.
|
//! Macros used on ouch.
|
||||||
|
|
||||||
/// Macro that prints message in INFO mode
|
/// Macro that prints [INFO] messages, wraps [`println`].
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! info {
|
macro_rules! info {
|
||||||
($($arg:tt)*) => {
|
($($arg:tt)*) => {
|
||||||
@ -9,7 +9,7 @@ macro_rules! info {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints the `[Info]` tag
|
/// Helper to display "[INFO]", colored yellow
|
||||||
pub fn _info_helper() {
|
pub fn _info_helper() {
|
||||||
use crate::utils::colors::{RESET, YELLOW};
|
use crate::utils::colors::{RESET, YELLOW};
|
||||||
|
|
||||||
|
30
src/opts.rs
30
src/opts.rs
@ -6,41 +6,51 @@ use std::path::PathBuf;
|
|||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(version, about)]
|
#[clap(version, about)]
|
||||||
pub struct Opts {
|
pub struct Opts {
|
||||||
/// Skip overwrite questions positively.
|
/// Skip [Y/n] questions positively.
|
||||||
#[clap(short, long, conflicts_with = "no")]
|
#[clap(short, long, conflicts_with = "no")]
|
||||||
pub yes: bool,
|
pub yes: bool,
|
||||||
|
|
||||||
/// Skip overwrite questions negatively.
|
/// Skip [Y/n] questions negatively.
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub no: bool,
|
pub no: bool,
|
||||||
|
|
||||||
/// Action to take
|
/// Ouch and claps subcommands
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
pub cmd: Subcommand,
|
pub cmd: Subcommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Actions to take
|
// CAREFUL: this docs can accidentally become part of the --help message if they get too long
|
||||||
|
// this was tested in clap 3.0.0-beta5.
|
||||||
|
/// Repository: https://github.com/ouch-org/ouch
|
||||||
|
//
|
||||||
|
// Ouch commands:
|
||||||
|
// - `compress`
|
||||||
|
// - `decompress`
|
||||||
|
// - `list`
|
||||||
|
//
|
||||||
|
// Clap commands:
|
||||||
|
// - `help`
|
||||||
#[derive(Parser, PartialEq, Eq, Debug)]
|
#[derive(Parser, PartialEq, Eq, Debug)]
|
||||||
pub enum Subcommand {
|
pub enum Subcommand {
|
||||||
/// Compress files. Alias: c
|
/// Compress one or more files into one output file.
|
||||||
#[clap(alias = "c")]
|
#[clap(alias = "c")]
|
||||||
Compress {
|
Compress {
|
||||||
/// Files to be compressed
|
/// Files to be compressed.
|
||||||
#[clap(required = true, min_values = 1)]
|
#[clap(required = true, min_values = 1)]
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
|
|
||||||
/// The resulting file. Its extensions specify how the files will be compressed and they need to be supported
|
/// The resulting file. It's extensions can be used to specify the compression formats.
|
||||||
#[clap(required = true, value_hint = ValueHint::FilePath)]
|
#[clap(required = true, value_hint = ValueHint::FilePath)]
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
},
|
},
|
||||||
/// Compress files. Alias: d
|
/// Decompresses one or more files, optionally into another folder.
|
||||||
#[clap(alias = "d")]
|
#[clap(alias = "d")]
|
||||||
Decompress {
|
Decompress {
|
||||||
/// Files to be decompressed
|
/// Files to be decompressed.
|
||||||
#[clap(required = true, min_values = 1)]
|
#[clap(required = true, min_values = 1)]
|
||||||
files: Vec<PathBuf>,
|
files: Vec<PathBuf>,
|
||||||
|
|
||||||
/// Decompress files in a directory other than the current
|
/// Choose to files in a directory other than the current
|
||||||
#[clap(short, long = "dir", value_hint = ValueHint::DirPath)]
|
#[clap(short, long = "dir", value_hint = ValueHint::DirPath)]
|
||||||
output_dir: Option<PathBuf>,
|
output_dir: Option<PathBuf>,
|
||||||
},
|
},
|
||||||
|
41
src/utils.rs
41
src/utils.rs
@ -1,4 +1,4 @@
|
|||||||
//! Utils used on ouch.
|
//! Random stuff used on ouch.
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
cmp, env,
|
cmp, env,
|
||||||
@ -11,7 +11,7 @@ use fs_err as fs;
|
|||||||
|
|
||||||
use crate::{dialogs::Confirmation, info};
|
use crate::{dialogs::Confirmation, info};
|
||||||
|
|
||||||
/// Checks if the given path represents an empty directory.
|
/// Checks given path points to an empty directory.
|
||||||
pub fn dir_is_empty(dir_path: &Path) -> bool {
|
pub fn dir_is_empty(dir_path: &Path) -> bool {
|
||||||
let is_empty = |mut rd: std::fs::ReadDir| rd.next().is_none();
|
let is_empty = |mut rd: std::fs::ReadDir| rd.next().is_none();
|
||||||
|
|
||||||
@ -37,21 +37,18 @@ pub fn strip_cur_dir(source_path: &Path) -> PathBuf {
|
|||||||
.unwrap_or_else(|_| source_path.to_path_buf())
|
.unwrap_or_else(|_| source_path.to_path_buf())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Changes the process' current directory to the directory that contains the
|
/// Returns current directory, but before change the process' directory to the
|
||||||
/// file pointed to by `filename` and returns the directory that the process
|
/// one that contains the file pointed to by `filename`.
|
||||||
/// was in before this function was called.
|
|
||||||
pub fn cd_into_same_dir_as(filename: &Path) -> crate::Result<PathBuf> {
|
pub fn cd_into_same_dir_as(filename: &Path) -> crate::Result<PathBuf> {
|
||||||
let previous_location = env::current_dir()?;
|
let previous_location = env::current_dir()?;
|
||||||
|
|
||||||
let parent = filename.parent().ok_or(crate::Error::CompressingRootFolder)?;
|
let parent = filename.parent().ok_or(crate::Error::CompressingRootFolder)?;
|
||||||
|
|
||||||
env::set_current_dir(parent)?;
|
env::set_current_dir(parent)?;
|
||||||
|
|
||||||
Ok(previous_location)
|
Ok(previous_location)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Centralizes the decision of overwriting a file or not,
|
/// Check if QuestionPolicy flags were set, otherwise, ask user if they want to overwrite.
|
||||||
/// whether the user has already passed a question_policy or not.
|
|
||||||
pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) -> crate::Result<bool> {
|
pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) -> crate::Result<bool> {
|
||||||
match question_policy {
|
match question_policy {
|
||||||
QuestionPolicy::AlwaysYes => Ok(true),
|
QuestionPolicy::AlwaysYes => Ok(true),
|
||||||
@ -65,13 +62,17 @@ pub fn user_wants_to_overwrite(path: &Path, question_policy: QuestionPolicy) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an OsStr to utf8.
|
/// Converts an OsStr to utf8 with custom formatting.
|
||||||
|
///
|
||||||
|
/// This is different from [`Path::display`].
|
||||||
|
///
|
||||||
|
/// See https://gist.github.com/marcospb19/ebce5572be26397cf08bbd0fd3b65ac1 for a comparison.
|
||||||
pub fn to_utf(os_str: impl AsRef<OsStr>) -> String {
|
pub fn to_utf(os_str: impl AsRef<OsStr>) -> String {
|
||||||
let text = format!("{:?}", os_str.as_ref());
|
let text = format!("{:?}", os_str.as_ref());
|
||||||
text.trim_matches('"').to_string()
|
text.trim_matches('"').to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Treats weird paths for better user messages.
|
/// Display the directory name, but change to "current directory" when necessary.
|
||||||
pub fn nice_directory_display(os_str: impl AsRef<OsStr>) -> String {
|
pub fn nice_directory_display(os_str: impl AsRef<OsStr>) -> String {
|
||||||
let text = to_utf(os_str);
|
let text = to_utf(os_str);
|
||||||
if text == "." {
|
if text == "." {
|
||||||
@ -81,11 +82,6 @@ pub fn nice_directory_display(os_str: impl AsRef<OsStr>) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Struct used to overload functionality onto Byte presentation.
|
|
||||||
pub struct Bytes {
|
|
||||||
bytes: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Module with a list of bright colors.
|
/// Module with a list of bright colors.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub mod colors {
|
pub mod colors {
|
||||||
@ -116,10 +112,15 @@ pub mod colors {
|
|||||||
color!(YELLOW = "\u{1b}[38;5;11m");
|
color!(YELLOW = "\u{1b}[38;5;11m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Struct useful to printing bytes as kB, MB, GB, etc.
|
||||||
|
pub struct Bytes {
|
||||||
|
bytes: f64,
|
||||||
|
}
|
||||||
|
|
||||||
impl Bytes {
|
impl Bytes {
|
||||||
const UNIT_PREFIXES: [&'static str; 6] = ["", "k", "M", "G", "T", "P"];
|
const UNIT_PREFIXES: [&'static str; 6] = ["", "k", "M", "G", "T", "P"];
|
||||||
|
|
||||||
/// New Byte structure
|
/// Create a new Bytes.
|
||||||
pub fn new(bytes: u64) -> Self {
|
pub fn new(bytes: u64) -> Self {
|
||||||
Self { bytes: bytes as f64 }
|
Self { bytes: bytes as f64 }
|
||||||
}
|
}
|
||||||
@ -141,13 +142,13 @@ impl std::fmt::Display for Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
/// How overwrite questions should be handled
|
/// Determines if overwrite questions should be skipped or asked to the user
|
||||||
pub enum QuestionPolicy {
|
pub enum QuestionPolicy {
|
||||||
/// Ask everytime
|
/// Ask the user every time
|
||||||
Ask,
|
Ask,
|
||||||
/// Skip overwrite questions positively
|
/// Set by `--yes`, will say 'Y' to all overwrite questions
|
||||||
AlwaysYes,
|
AlwaysYes,
|
||||||
/// Skip overwrite questions negatively
|
/// Set by `--no`, will say 'N' to all overwrite questions
|
||||||
AlwaysNo,
|
AlwaysNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user