From e3e734c39e4ed8375d73860c33ef4ab1bb595f54 Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 13 Aug 2018 20:04:16 -0400 Subject: [PATCH] feat: handle interrupts cleanly --- Cargo.lock | 24 ++++++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40d2eec..6dfa40b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,6 +121,15 @@ dependencies = [ "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ctrlc" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "deflate" version = "0.7.18" @@ -360,6 +369,18 @@ dependencies = [ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nix" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nodrop" version = "0.1.12" @@ -551,6 +572,7 @@ name = "screenshot_organiser" version = "0.1.0" dependencies = [ "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -750,6 +772,7 @@ dependencies = [ "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" +"checksum ctrlc 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "630391922b1b893692c6334369ff528dcc3a9d8061ccf4c803aa8f83cb13db5e" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" @@ -777,6 +800,7 @@ dependencies = [ "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d023ef40ca7680784b07be3f49913e1ea176da1b63949f2eb2fed96438bd7f42" diff --git a/Cargo.toml b/Cargo.toml index 171cd09..d3df0de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ failure = "0.1" tempdir = "0.3" num_cpus = "1" rayon = "1" +ctrlc = "3" diff --git a/src/main.rs b/src/main.rs index 5098499..b866df2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -#![feature(rust_2018_preview, iterator_find_map, use_extern_macros)] +#![feature(rust_2018_preview, iterator_find_map, use_extern_macros, mpsc_select)] #[macro_use] extern crate serde_derive; @@ -20,34 +20,50 @@ use rayon::prelude::*; use tempdir::TempDir; -use std::{fs::{self, DirEntry}, path::PathBuf, sync::mpsc}; +use std::{fs::{self, DirEntry}, path::PathBuf, sync::mpsc::{self, Receiver}}; pub type Result = std::result::Result; fn main() -> Result<()> { + println!("Starting FFXIV Screenshot Organiser."); + + let ctrlc_rx = set_ctrlc_handler()?; + let config_path = match std::env::args().nth(1) { Some(x) => x, None => "config.json".into(), }; + println!("Attempting to read config from `{}`.", config_path); let f = fs::File::open(config_path)?; let config: Config = serde_json::from_reader(f)?; + println!("Config successfully read."); + let screenshots_dir = config.options.screenshots_dir.canonicalize()?; + println!("Screenshots are located at `{}`.", screenshots_dir.to_string_lossy()); + let (tx, rx) = mpsc::channel(); let temp_dir = TempDir::new("fso-")?; let temp_path = temp_dir.path().to_owned(); + println!("Storing temporary files in `{}`.", temp_path.to_string_lossy()); + + println!("Collecting existing files."); let existing_files: Vec = std::fs::read_dir(&screenshots_dir)?.collect::>()?; + println!("Processing {} existing file(s).", existing_files.len()); + existing_files.into_par_iter().for_each(|entry| { if let Err(e) = handle(&config, temp_path.clone(), entry.path()) { eprintln!("{}", e); } }); + println!("Done!"); + let mut watcher = notify::watcher( tx, Duration::milliseconds(config.options.event_delay).to_std().unwrap(), @@ -58,15 +74,26 @@ fn main() -> Result<()> { RecursiveMode::NonRecursive )?; + println!("Waiting for new files."); + loop { - match rx.recv() { - Ok(DebouncedEvent::Create(p)) => if let Err(e) = handle(&config, temp_path.clone(), p) { - eprintln!("{}", e); - }, - Ok(_) => {}, - Err(e) => eprintln!("{:#?}", e), + select! { + _ = ctrlc_rx.recv() => break, + e = rx.recv() => { + match e { + Ok(DebouncedEvent::Create(p)) => if let Err(e) = handle(&config, temp_path.clone(), p) { + eprintln!("{}", e); + }, + Ok(_) => {}, + Err(e) => eprintln!("{:#?}", e), + } + } } } + + println!("Exiting."); + + Ok(()) } fn handle(config: &Config, temp_dir: PathBuf, p: PathBuf) -> Result<()> { @@ -119,3 +146,14 @@ fn parse_screenshot_name(config: &Config, s: &str) -> Option> { ); Some(dt.with_timezone(&Utc)) } + +fn set_ctrlc_handler() -> Result> { + let (tx, rx) = mpsc::channel(); + + ctrlc::set_handler(move || { + println!("Received interrupt."); + tx.send(()).ok(); + })?; + + Ok(rx) +}