feat: handle interrupts cleanly

This commit is contained in:
Anna 2018-08-13 20:04:16 -04:00
parent 1a2cdf2c2f
commit e3e734c39e
3 changed files with 71 additions and 8 deletions

24
Cargo.lock generated
View File

@ -121,6 +121,15 @@ dependencies = [
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "deflate" name = "deflate"
version = "0.7.18" version = "0.7.18"
@ -360,6 +369,18 @@ dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "nodrop" name = "nodrop"
version = "0.1.12" version = "0.1.12"
@ -551,6 +572,7 @@ name = "screenshot_organiser"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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-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-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 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 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 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" "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 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 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 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 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 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" "checksum notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d023ef40ca7680784b07be3f49913e1ea176da1b63949f2eb2fed96438bd7f42"

View File

@ -20,3 +20,4 @@ failure = "0.1"
tempdir = "0.3" tempdir = "0.3"
num_cpus = "1" num_cpus = "1"
rayon = "1" rayon = "1"
ctrlc = "3"

View File

@ -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; #[macro_use] extern crate serde_derive;
@ -20,34 +20,50 @@ use rayon::prelude::*;
use tempdir::TempDir; 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<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
fn main() -> Result<()> { fn main() -> Result<()> {
println!("Starting FFXIV Screenshot Organiser.");
let ctrlc_rx = set_ctrlc_handler()?;
let config_path = match std::env::args().nth(1) { let config_path = match std::env::args().nth(1) {
Some(x) => x, Some(x) => x,
None => "config.json".into(), None => "config.json".into(),
}; };
println!("Attempting to read config from `{}`.", config_path);
let f = fs::File::open(config_path)?; let f = fs::File::open(config_path)?;
let config: Config = serde_json::from_reader(f)?; let config: Config = serde_json::from_reader(f)?;
println!("Config successfully read.");
let screenshots_dir = config.options.screenshots_dir.canonicalize()?; let screenshots_dir = config.options.screenshots_dir.canonicalize()?;
println!("Screenshots are located at `{}`.", screenshots_dir.to_string_lossy());
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let temp_dir = TempDir::new("fso-")?; let temp_dir = TempDir::new("fso-")?;
let temp_path = temp_dir.path().to_owned(); 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<DirEntry> = std::fs::read_dir(&screenshots_dir)?.collect::<std::result::Result<_, _>>()?; let existing_files: Vec<DirEntry> = std::fs::read_dir(&screenshots_dir)?.collect::<std::result::Result<_, _>>()?;
println!("Processing {} existing file(s).", existing_files.len());
existing_files.into_par_iter().for_each(|entry| { existing_files.into_par_iter().for_each(|entry| {
if let Err(e) = handle(&config, temp_path.clone(), entry.path()) { if let Err(e) = handle(&config, temp_path.clone(), entry.path()) {
eprintln!("{}", e); eprintln!("{}", e);
} }
}); });
println!("Done!");
let mut watcher = notify::watcher( let mut watcher = notify::watcher(
tx, tx,
Duration::milliseconds(config.options.event_delay).to_std().unwrap(), Duration::milliseconds(config.options.event_delay).to_std().unwrap(),
@ -58,15 +74,26 @@ fn main() -> Result<()> {
RecursiveMode::NonRecursive RecursiveMode::NonRecursive
)?; )?;
println!("Waiting for new files.");
loop { loop {
match rx.recv() { select! {
Ok(DebouncedEvent::Create(p)) => if let Err(e) = handle(&config, temp_path.clone(), p) { _ = ctrlc_rx.recv() => break,
eprintln!("{}", e); e = rx.recv() => {
}, match e {
Ok(_) => {}, Ok(DebouncedEvent::Create(p)) => if let Err(e) = handle(&config, temp_path.clone(), p) {
Err(e) => eprintln!("{:#?}", e), eprintln!("{}", e);
},
Ok(_) => {},
Err(e) => eprintln!("{:#?}", e),
}
}
} }
} }
println!("Exiting.");
Ok(())
} }
fn handle(config: &Config, temp_dir: PathBuf, p: PathBuf) -> Result<()> { fn handle(config: &Config, temp_dir: PathBuf, p: PathBuf) -> Result<()> {
@ -119,3 +146,14 @@ fn parse_screenshot_name(config: &Config, s: &str) -> Option<DateTime<Utc>> {
); );
Some(dt.with_timezone(&Utc)) Some(dt.with_timezone(&Utc))
} }
fn set_ctrlc_handler() -> Result<Receiver<()>> {
let (tx, rx) = mpsc::channel();
ctrlc::set_handler(move || {
println!("Received interrupt.");
tx.send(()).ok();
})?;
Ok(rx)
}