file_matcher/actions/
mover.rs

1#[cfg(not(feature = "mover"))]
2compile_error!("Please select a mover feature to build with mover support");
3
4use crate::Result;
5use crate::{FileMatcherError, OneEntry};
6use fs_extra::dir::CopyOptions;
7use std::path::{Path, PathBuf};
8
9pub trait OneEntryMover {
10    fn r#move(&self, destination: impl AsRef<Path>) -> Result<PathBuf>;
11}
12
13impl OneEntryMover for OneEntry {
14    fn r#move(&self, destination: impl AsRef<Path>) -> Result<PathBuf> {
15        let destination = destination.as_ref();
16        let file = self.as_path_buf()?;
17
18        return if let Some(alias) = self.entry().name_alias() {
19            Ok(move_entry(&file, destination, alias)?)
20        } else if let Some(file_name) = file.file_name() {
21            if let Some(file_name) = file_name.to_str() {
22                Ok(move_entry(&file, destination, file_name)?)
23            } else {
24                FileMatcherError::InvalidUnicode(file_name.to_os_string()).into()
25            }
26        } else {
27            FileMatcherError::NotReadable(file.clone()).into()
28        };
29    }
30}
31
32fn move_entry(from: impl AsRef<Path>, to: impl AsRef<Path>, file_name: &str) -> Result<PathBuf> {
33    let from = from.as_ref();
34    if from.is_file() {
35        move_file(from, to, file_name)
36    } else if from.is_dir() {
37        move_folder(from, to, file_name)
38    } else {
39        FileMatcherError::NotReadable(from.to_path_buf()).into()
40    }
41}
42
43fn move_file(from: impl AsRef<Path>, to: impl AsRef<Path>, file_name: &str) -> Result<PathBuf> {
44    let destination = to.as_ref();
45
46    let destination = if destination.is_dir() {
47        destination.join(file_name)
48    } else {
49        destination.to_path_buf()
50    };
51
52    std::fs::copy(&from, &destination)?;
53    std::fs::remove_file(&from)?;
54    Ok(destination)
55}
56
57fn move_folder(from: impl AsRef<Path>, to: impl AsRef<Path>, file_name: &str) -> Result<PathBuf> {
58    let destination = to.as_ref();
59
60    let destination = destination.join(file_name);
61
62    let mut options = CopyOptions::new();
63    options.copy_inside = true;
64
65    fs_extra::dir::copy(&from, &destination, &options).map_err(FileMatcherError::FsExtraError)?;
66
67    std::fs::remove_dir_all(&from)?;
68
69    Ok(destination)
70}