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}