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