// SPDX-FileCopyrightText: 2024 Ɓukasz Niemier <#@hauleth.dev> // // SPDX-License-Identifier: EUPL-1.2 use tokio::fs; use tokio::process::Command; use std::path::{Path, PathBuf}; /// Actions available for file #[derive(Clone, Debug, serde::Deserialize)] #[serde(rename_all = "snake_case")] pub enum Action { /// Run given script with 1st argument. It will be ran in parent directory for given file Script(Box), /// Move given file to new destination Move(Box), /// Copy given file to new destination Copy(Box), /// Print message and do nothing Echo(String), /// Move to trash Trash, } impl Action { pub async fn run(self, source: PathBuf, execute: bool) { self.dry_run(&source).await; if execute { self.execute(source).await } } pub async fn dry_run(&self, source: &Path) { match self { Action::Script(ref script) => println!("Execute {script:?} {source:?}"), Action::Move(ref dest) => println!("Move {source:?} -> {dest:?}"), Action::Copy(ref dest) => println!("Copy {source:?} -> {dest:?}"), Action::Echo(ref message) => println!("{source:?} - {message}"), Action::Trash => println!("Move {source:?} to trash"), } } pub async fn execute(self, source: PathBuf) { match self { Action::Script(ref script) => { Command::new(script.as_ref()) .arg(&source) .current_dir(source.parent().unwrap()) .spawn() .expect("Couldnt spawn process") .wait() .await .expect("Child exited abnormally"); } Action::Copy(ref dest_dir) => { let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap()); fs::copy(&source, dest).await.expect("Couldnt copy file"); } Action::Move(ref dest_dir) => { let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap()); if let Err(err) = fs::rename(&source, &dest).await { if err.raw_os_error() == Some(libc::EXDEV) { panic!("X dev"); } else { panic!("Cannot move {source:?} -> {dest:?}: {err:?}"); } } } Action::Echo(ref message) => println!("{source:?} - {message}"), Action::Trash => trash::delete(source).unwrap(), } } }