feat: handle interrupts cleanly
This commit is contained in:
parent
1a2cdf2c2f
commit
e3e734c39e
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
54
src/main.rs
54
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;
|
#[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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue