mirror of
https://github.com/timvisee/ffsend.git
synced 2025-10-06 10:39:57 +02:00
Ensure there is enough free disk space, allow info messages with errors
This commit is contained in:
parent
54bdb922b7
commit
f348e603e2
5 changed files with 111 additions and 8 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -363,6 +363,7 @@ dependencies = [
|
||||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ffsend-api 0.0.1",
|
"ffsend-api 0.0.1",
|
||||||
|
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pbr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -412,6 +413,15 @@ name = "foreign-types-shared"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs2"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-zircon"
|
name = "fuchsia-zircon"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -1628,6 +1638,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
||||||
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||||
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||||
"checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c"
|
"checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c"
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
# Release 0.1
|
# Release 0.1
|
||||||
- Panic when secret is missing from URL with info action
|
- Panic when secret is missing from URL with info action
|
||||||
- History compiler flag
|
|
||||||
- Lowercase error messages
|
- Lowercase error messages
|
||||||
- Switch to `directories` instead of `app_dirs2`?
|
- Switch to `directories` instead of `app_dirs2`?
|
||||||
- Allow file/directory archiving on upload
|
- Allow file/directory archiving on upload
|
||||||
|
|
|
@ -25,6 +25,7 @@ derive_builder = "0.5"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
failure_derive = "0.1"
|
failure_derive = "0.1"
|
||||||
ffsend-api = { version = "*", path = "../api" }
|
ffsend-api = { version = "*", path = "../api" }
|
||||||
|
fs2 = "0.4"
|
||||||
lazy_static = "1.0"
|
lazy_static = "1.0"
|
||||||
open = "1"
|
open = "1"
|
||||||
pbr = "1"
|
pbr = "1"
|
||||||
|
|
|
@ -28,6 +28,7 @@ use cmd::matcher::{
|
||||||
use history_tool;
|
use history_tool;
|
||||||
use progress::ProgressBar;
|
use progress::ProgressBar;
|
||||||
use util::{
|
use util::{
|
||||||
|
ensure_enough_space,
|
||||||
ensure_password,
|
ensure_password,
|
||||||
ErrorHints,
|
ErrorHints,
|
||||||
prompt_yes,
|
prompt_yes,
|
||||||
|
@ -95,6 +96,11 @@ impl<'a> Download<'a> {
|
||||||
&matcher_main,
|
&matcher_main,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure there is enough disk space available when not being forced
|
||||||
|
if !matcher_main.force() {
|
||||||
|
ensure_enough_space(target.parent().unwrap(), metadata.size());
|
||||||
|
}
|
||||||
|
|
||||||
// Create a progress bar reporter
|
// Create a progress bar reporter
|
||||||
let bar = Arc::new(Mutex::new(ProgressBar::new_download()));
|
let bar = Arc::new(Mutex::new(ProgressBar::new_download()));
|
||||||
|
|
||||||
|
|
100
cli/src/util.rs
100
cli/src/util.rs
|
@ -1,6 +1,7 @@
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
extern crate clipboard;
|
extern crate clipboard;
|
||||||
extern crate colored;
|
extern crate colored;
|
||||||
|
extern crate fs2;
|
||||||
extern crate open;
|
extern crate open;
|
||||||
|
|
||||||
use std::env::current_exe;
|
use std::env::current_exe;
|
||||||
|
@ -13,15 +14,17 @@ use std::io::{
|
||||||
stderr,
|
stderr,
|
||||||
Write,
|
Write,
|
||||||
};
|
};
|
||||||
|
use std::path::Path;
|
||||||
use std::process::{exit, ExitStatus};
|
use std::process::{exit, ExitStatus};
|
||||||
|
|
||||||
use chrono::Duration;
|
use chrono::Duration;
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
use self::clipboard::{ClipboardContext, ClipboardProvider};
|
|
||||||
use self::colored::*;
|
|
||||||
use failure::{err_msg, Fail};
|
use failure::{err_msg, Fail};
|
||||||
use ffsend_api::url::Url;
|
use ffsend_api::url::Url;
|
||||||
use rpassword::prompt_password_stderr;
|
use rpassword::prompt_password_stderr;
|
||||||
|
use self::clipboard::{ClipboardContext, ClipboardProvider};
|
||||||
|
use self::colored::*;
|
||||||
|
use self::fs2::available_space;
|
||||||
|
|
||||||
use cmd::matcher::MainMatcher;
|
use cmd::matcher::MainMatcher;
|
||||||
|
|
||||||
|
@ -38,15 +41,15 @@ pub fn print_error<E: Fail>(err: E) {
|
||||||
.filter(|err| !err.is_empty())
|
.filter(|err| !err.is_empty())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, err)| if i == 0 {
|
.map(|(i, err)| if i == 0 {
|
||||||
eprintln!("{} {}", "error:".red().bold(), err);
|
eprintln!("{} {}", highlight_error("error:"), err);
|
||||||
} else {
|
} else {
|
||||||
eprintln!("{} {}", "caused by:".red().bold(), err);
|
eprintln!("{} {}", highlight_error("caused by:"), err);
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
// Fall back to a basic message
|
// Fall back to a basic message
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
eprintln!("{} {}", "error:".red().bold(), "An undefined error occurred");
|
eprintln!("{} {}", highlight_error("error:"), "An undefined error occurred");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +67,7 @@ pub fn print_warning<S>(err: S)
|
||||||
where
|
where
|
||||||
S: AsRef<str> + Display + Debug + Sync + Send + 'static
|
S: AsRef<str> + Display + Debug + Sync + Send + 'static
|
||||||
{
|
{
|
||||||
eprintln!("{} {}", "warning:".yellow().bold(), err);
|
eprintln!("{} {}", highlight_warning("warning:"), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Quit the application regularly.
|
/// Quit the application regularly.
|
||||||
|
@ -95,9 +98,12 @@ pub fn quit_error_msg<S>(err: S, hints: ErrorHints) -> !
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The error hint configuration.
|
/// The error hint configuration.
|
||||||
#[derive(Copy, Clone, Builder)]
|
#[derive(Clone, Builder)]
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub struct ErrorHints {
|
pub struct ErrorHints {
|
||||||
|
/// A list of info messages to print along with the error.
|
||||||
|
info: Vec<String>,
|
||||||
|
|
||||||
/// Show about the password option.
|
/// Show about the password option.
|
||||||
password: bool,
|
password: bool,
|
||||||
|
|
||||||
|
@ -130,6 +136,11 @@ impl ErrorHints {
|
||||||
|
|
||||||
/// Print the error hints.
|
/// Print the error hints.
|
||||||
pub fn print(&self) {
|
pub fn print(&self) {
|
||||||
|
// Print info messages
|
||||||
|
for msg in &self.info {
|
||||||
|
eprintln!("{} {}", highlight_info("info:"), msg);
|
||||||
|
}
|
||||||
|
|
||||||
// Stop if nothing should be printed
|
// Stop if nothing should be printed
|
||||||
if !self.any() {
|
if !self.any() {
|
||||||
return;
|
return;
|
||||||
|
@ -165,6 +176,7 @@ impl ErrorHints {
|
||||||
impl Default for ErrorHints {
|
impl Default for ErrorHints {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
ErrorHints {
|
ErrorHints {
|
||||||
|
info: Vec::new(),
|
||||||
password: false,
|
password: false,
|
||||||
owner: false,
|
owner: false,
|
||||||
history: false,
|
history: false,
|
||||||
|
@ -175,11 +187,43 @@ impl Default for ErrorHints {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ErrorHintsBuilder {
|
||||||
|
/// Add a single info entry.
|
||||||
|
pub fn add_info(mut self, info: String) -> Self {
|
||||||
|
// Initialize the info list
|
||||||
|
if self.info.is_none() {
|
||||||
|
self.info = Some(Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the item to the info list
|
||||||
|
if let Some(ref mut list) = self.info {
|
||||||
|
list.push(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Highlight the given text with a color.
|
/// Highlight the given text with a color.
|
||||||
pub fn highlight(msg: &str) -> ColoredString {
|
pub fn highlight(msg: &str) -> ColoredString {
|
||||||
msg.yellow()
|
msg.yellow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Highlight the given text with an error color.
|
||||||
|
pub fn highlight_error(msg: &str) -> ColoredString {
|
||||||
|
msg.red().bold()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Highlight the given text with an warning color.
|
||||||
|
pub fn highlight_warning(msg: &str) -> ColoredString {
|
||||||
|
highlight(msg).bold()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Highlight the given text with an info color
|
||||||
|
pub fn highlight_info(msg: &str) -> ColoredString {
|
||||||
|
msg.cyan()
|
||||||
|
}
|
||||||
|
|
||||||
/// Open the given URL in the users default browser.
|
/// Open the given URL in the users default browser.
|
||||||
/// The browsers exit statis is returned.
|
/// The browsers exit statis is returned.
|
||||||
pub fn open_url(url: Url) -> Result<ExitStatus, IoError> {
|
pub fn open_url(url: Url) -> Result<ExitStatus, IoError> {
|
||||||
|
@ -501,3 +545,45 @@ pub fn exe_name() -> String {
|
||||||
.and_then(|n| n.into_string().ok())
|
.and_then(|n| n.into_string().ok())
|
||||||
.unwrap_or(crate_name!().into())
|
.unwrap_or(crate_name!().into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether there is enough space avaialble at the given `path` to store a file
|
||||||
|
/// with the given `size`.
|
||||||
|
///
|
||||||
|
/// If an error occurred while querying the file system,
|
||||||
|
/// the error is reported to the user, and `true` is returned.
|
||||||
|
///
|
||||||
|
/// `false` is only returned when sure that there isn't enough space available.
|
||||||
|
pub fn ensure_enough_space<P: AsRef<Path>>(path: P, size: u64) {
|
||||||
|
// Get the available space at this path
|
||||||
|
let space = match available_space(path) {
|
||||||
|
Ok(space) => space,
|
||||||
|
Err(err) => {
|
||||||
|
print_error(err.context("Failed to check available space on disk, ignoring"));
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return if enough disk space is avaiable
|
||||||
|
if space >= size {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an info message giving details about the required space
|
||||||
|
let info = format!(
|
||||||
|
"{} is required, but only {} is available",
|
||||||
|
format_bytes(size),
|
||||||
|
format_bytes(space),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Print an descriptive error and quit
|
||||||
|
quit_error(
|
||||||
|
err_msg("Not enough disk space available in the target directory")
|
||||||
|
.context("Failed to download file"),
|
||||||
|
ErrorHintsBuilder::default()
|
||||||
|
.add_info(info)
|
||||||
|
.force(true)
|
||||||
|
.verbose(false)
|
||||||
|
.build()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue