file_matcher/actions/
copier.rs1#[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}