Simple tool for automatic file management
1use tokio::fs; 2use tokio::process::Command; 3 4use std::path::{Path, PathBuf}; 5 6/// Actions available for file 7#[derive(Clone, Debug, serde::Deserialize)] 8#[serde(rename_all = "snake_case")] 9pub enum Action { 10 /// Run given script with 1st argument. It will be ran in parent directory for given file 11 Script(Box<Path>), 12 /// Move given file to new destination 13 Move(Box<Path>), 14 /// Print message and do nothing 15 Echo(String), 16 /// Move to trash 17 Trash, 18} 19 20impl Action { 21 pub async fn run(self, source: PathBuf, execute: bool) { 22 if execute { 23 self.execute(source).await 24 } else { 25 self.dry_run(source).await 26 } 27 } 28 29 pub async fn dry_run(self, source: PathBuf) { 30 match self { 31 Action::Script(ref script) => println!("Execute {script:?} {source:?}"), 32 Action::Move(ref dest) => println!("Move {source:?} -> {dest:?}"), 33 Action::Echo(ref message) => println!("{source:?} - {message}"), 34 Action::Trash => println!("Move {source:?} to trash"), 35 } 36 } 37 38 pub async fn execute(self, source: PathBuf) { 39 match self { 40 Action::Script(ref script) => { 41 Command::new(script.as_ref()) 42 .arg(&source) 43 .current_dir(source.parent().unwrap()) 44 .spawn() 45 .expect("Couldnt spawn process") 46 .wait() 47 .await 48 .expect("Child exited abnormally"); 49 } 50 51 Action::Move(ref dest_dir) => { 52 let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap()); 53 if let Err(err) = fs::rename(&source, &dest).await { 54 if err.raw_os_error() == Some(libc::EXDEV) { 55 panic!("X dev"); 56 } else { 57 panic!("Cannot move {source:?} -> {dest:?}: {err:?}"); 58 } 59 } 60 } 61 62 Action::Echo(ref message) => println!("{source:?} - {message}"), 63 64 Action::Trash => trash::delete(source).unwrap(), 65 } 66 } 67}