file_matcher/actions/
copier.rs

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