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 /// Copy given file to new destination
15 Copy(Box<Path>),
16 /// Print message and do nothing
17 Echo(String),
18 /// Move to trash
19 Trash,
20}
21
22impl Action {
23 pub async fn run(self, source: PathBuf, execute: bool) {
24 if execute {
25 self.execute(source).await
26 } else {
27 self.dry_run(source).await
28 }
29 }
30
31 pub async fn dry_run(self, source: PathBuf) {
32 match self {
33 Action::Script(ref script) => println!("Execute {script:?} {source:?}"),
34 Action::Move(ref dest) => println!("Move {source:?} -> {dest:?}"),
35 Action::Copy(ref dest) => println!("Copy {source:?} -> {dest:?}"),
36 Action::Echo(ref message) => println!("{source:?} - {message}"),
37 Action::Trash => println!("Move {source:?} to trash"),
38 }
39 }
40
41 pub async fn execute(self, source: PathBuf) {
42 match self {
43 Action::Script(ref script) => {
44 Command::new(script.as_ref())
45 .arg(&source)
46 .current_dir(source.parent().unwrap())
47 .spawn()
48 .expect("Couldnt spawn process")
49 .wait()
50 .await
51 .expect("Child exited abnormally");
52 }
53
54 Action::Copy(ref dest_dir) => {
55 let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap());
56 fs::copy(&source, dest).await.expect("Couldnt copy file");
57 }
58
59 Action::Move(ref dest_dir) => {
60 let dest = crate::job::normalise_path(dest_dir).join(source.file_name().unwrap());
61 if let Err(err) = fs::rename(&source, &dest).await {
62 if err.raw_os_error() == Some(libc::EXDEV) {
63 panic!("X dev");
64 } else {
65 panic!("Cannot move {source:?} -> {dest:?}: {err:?}");
66 }
67 }
68 }
69
70 Action::Echo(ref message) => println!("{source:?} - {message}"),
71
72 Action::Trash => trash::delete(source).unwrap(),
73 }
74 }
75}