summaryrefslogtreecommitdiffstats
path: root/vendor/fs_extra/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/fs_extra/src/lib.rs')
-rw-r--r--vendor/fs_extra/src/lib.rs802
1 files changed, 802 insertions, 0 deletions
diff --git a/vendor/fs_extra/src/lib.rs b/vendor/fs_extra/src/lib.rs
new file mode 100644
index 000000000..118643ab8
--- /dev/null
+++ b/vendor/fs_extra/src/lib.rs
@@ -0,0 +1,802 @@
+macro_rules! err {
+ ($text:expr, $kind:expr) => {
+ return Err(Error::new($kind, $text))
+ };
+
+ ($text:expr) => {
+ err!($text, ErrorKind::Other)
+ };
+}
+
+/// The error type for fs_extra operations on files and directories.
+pub mod error;
+/// This module includes additional methods for working with files.
+///
+/// One of the distinguishing features is receipt information
+/// about process work with files.
+///
+/// # Example
+/// ```rust,ignore
+/// use std::path::Path;
+/// use std::{thread, time};
+/// use std::sync::mpsc::{self, TryRecvError};
+///
+/// extern crate fs_extra;
+/// use fs_extra::file::*;
+/// use fs_extra::error::*;
+///
+/// fn example_copy() -> Result<()> {
+/// let path_from = Path::new("./temp");
+/// let path_to = path_from.join("out");
+/// let test_file = (path_from.join("test_file.txt"), path_to.join("test_file.txt"));
+///
+///
+/// fs_extra::dir::create_all(&path_from, true)?;
+/// fs_extra::dir::create_all(&path_to, true)?;
+///
+/// write_all(&test_file.0, "test_data")?;
+/// assert!(test_file.0.exists());
+/// assert!(!test_file.1.exists());
+///
+///
+/// let options = CopyOptions {
+/// buffer_size: 1,
+/// ..Default::default()
+/// }
+/// let (tx, rx) = mpsc::channel();
+/// thread::spawn(move || {
+/// let handler = |process_info: TransitProcess| {
+/// tx.send(process_info).unwrap();
+/// thread::sleep(time::Duration::from_millis(500));
+/// };
+/// copy_with_progress(&test_file.0, &test_file.1, &options, handler).unwrap();
+/// assert!(test_file.0.exists());
+/// assert!(test_file.1.exists());
+///
+/// });
+/// loop {
+/// match rx.try_recv() {
+/// Ok(process_info) => {
+/// println!("{} of {} bytes",
+/// process_info.copied_bytes,
+/// process_info.total_bytes);
+/// }
+/// Err(TryRecvError::Disconnected) => {
+/// println!("finished");
+/// break;
+/// }
+/// Err(TryRecvError::Empty) => {}
+/// }
+/// }
+/// Ok(())
+///
+/// }
+///
+///
+/// fn main() {
+/// example_copy();
+/// }
+///
+/// ```
+pub mod file;
+
+/// This module includes additional methods for working with directories.
+///
+/// One of the additional features is information
+/// about process and recursion operations.
+///
+/// # Example
+/// ```rust,ignore
+/// use std::path::Path;
+/// use std::{thread, time};
+/// use std::sync::mpsc::{self, TryRecvError};
+///
+/// extern crate fs_extra;
+/// use fs_extra::dir::*;
+/// use fs_extra::error::*;
+///
+/// fn example_copy() -> Result<()> {
+///
+/// let path_from = Path::new("./temp");
+/// let path_to = path_from.join("out");
+/// let test_folder = path_from.join("test_folder");
+/// let dir = test_folder.join("dir");
+/// let sub = dir.join("sub");
+/// let file1 = dir.join("file1.txt");
+/// let file2 = sub.join("file2.txt");
+///
+/// create_all(&sub, true)?;
+/// create_all(&path_to, true)?;
+/// fs_extra::file::write_all(&file1, "content1")?;
+/// fs_extra::file::write_all(&file2, "content2")?;
+///
+/// assert!(dir.exists());
+/// assert!(sub.exists());
+/// assert!(file1.exists());
+/// assert!(file2.exists());
+///
+///
+/// let options = CopyOptions {
+/// buffer_size: 1,
+/// ..Default::default(),
+/// };
+/// let (tx, rx) = mpsc::channel();
+/// thread::spawn(move || {
+/// let handler = |process_info: TransitProcess| {
+/// tx.send(process_info).unwrap();
+/// thread::sleep(time::Duration::from_millis(500));
+/// };
+/// copy_with_progress(&test_folder, &path_to, &options, handler).unwrap();
+/// });
+///
+/// loop {
+/// match rx.try_recv() {
+/// Ok(process_info) => {
+/// println!("{} of {} bytes",
+/// process_info.copied_bytes,
+/// process_info.total_bytes);
+/// }
+/// Err(TryRecvError::Disconnected) => {
+/// println!("finished");
+/// break;
+/// }
+/// Err(TryRecvError::Empty) => {}
+/// }
+/// }
+/// Ok(())
+///
+/// }
+/// fn main() {
+/// example_copy();
+/// }
+/// ```
+///
+pub mod dir;
+
+use crate::error::*;
+use std::path::Path;
+
+/// Copies a list of directories and files to another place recursively. This function will
+/// also copy the permission bits of the original files to destination files (not for
+/// directories).
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these case:
+///
+/// * List `from` contains file or directory does not exist.
+///
+/// * List `from` contains file or directory with invalid name.
+///
+/// * The current process does not have the permission to access to file from `lists from` or
+/// `to`.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
+///
+/// // copy dir1 and file1.txt to target/dir1 and target/file1.txt
+/// let mut from_paths = Vec::new();
+/// from_paths.push("source/dir1");
+/// from_paths.push("source/file.txt");
+/// copy_items(&from_paths, "target", &options)?;
+/// ```
+///
+pub fn copy_items<P, Q>(from: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let mut result: u64 = 0;
+ if options.content_only {
+ err!(
+ "Options 'content_only' not acccess for copy_items function",
+ ErrorKind::Other
+ );
+ }
+ for item in from {
+ let item = item.as_ref();
+ if item.is_dir() {
+ result += dir::copy(item, &to, options)?;
+ } else if let Some(file_name) = item.file_name() {
+ if let Some(file_name) = file_name.to_str() {
+ let file_options = file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ ..Default::default()
+ };
+ result += file::copy(item, to.as_ref().join(file_name), &file_options)?;
+ }
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+ }
+
+ Ok(result)
+}
+
+/// A structure which includes information about the current status of copying or moving a directory.
+pub struct TransitProcess {
+ /// Already copied bytes
+ pub copied_bytes: u64,
+ /// All the bytes which should be copied or moved (dir size).
+ pub total_bytes: u64,
+ /// Copied bytes on this time for file.
+ pub file_bytes_copied: u64,
+ /// Size of currently copied file.
+ pub file_total_bytes: u64,
+ /// Name of currently copied file.
+ pub file_name: String,
+ /// Name of currently copied folder.
+ pub dir_name: String,
+ /// Transit state
+ pub state: dir::TransitState,
+}
+
+impl Clone for TransitProcess {
+ fn clone(&self) -> TransitProcess {
+ TransitProcess {
+ copied_bytes: self.copied_bytes,
+ total_bytes: self.total_bytes,
+ file_bytes_copied: self.file_bytes_copied,
+ file_total_bytes: self.file_total_bytes,
+ file_name: self.file_name.clone(),
+ dir_name: self.dir_name.clone(),
+ state: self.state.clone(),
+ }
+ }
+}
+
+/// Copies a list of directories and files to another place recursively, with
+/// information about progress. This function will also copy the permission bits of the
+/// original files to destination files (not for directories).
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these case:
+///
+/// * List `from` contains file or directory does not exist.
+///
+/// * List `from` contains file or directory with invalid name.
+///
+/// * The current process does not have the permission to access to file from `lists from` or
+/// `to`.
+///
+/// # Example
+/// ```rust,ignore
+///
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| {
+/// println!("{}", process_info.total_bytes);
+/// fs_extra::dir::TransitProcessResult::ContinueOrAbort
+/// }
+/// // copy dir1 and file1.txt to target/dir1 and target/file1.txt
+/// let mut from_paths = Vec::new();
+/// from_paths.push("source/dir1");
+/// from_paths.push("source/file.txt");
+/// copy_items_with_progress(&from_paths, "target", &options, handle)?;
+/// ```
+///
+pub fn copy_items_with_progress<P, Q, F>(
+ from: &[P],
+ to: Q,
+ options: &dir::CopyOptions,
+ mut progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess) -> dir::TransitProcessResult,
+{
+ if options.content_only {
+ err!(
+ "Options 'content_only' not access for copy_items_with_progress function",
+ ErrorKind::Other
+ );
+ }
+ let mut total_size = 0;
+ let mut list_paths = Vec::new();
+ for item in from {
+ let item = item.as_ref();
+ total_size += dir::get_size(item)?;
+ list_paths.push(item);
+ }
+
+ let mut result: u64 = 0;
+ let mut info_process = TransitProcess {
+ copied_bytes: 0,
+ total_bytes: total_size,
+ file_bytes_copied: 0,
+ file_total_bytes: 0,
+ file_name: String::new(),
+ dir_name: String::new(),
+ state: dir::TransitState::Normal,
+ };
+
+ let mut options = options.clone();
+ for item in list_paths {
+ if item.is_dir() {
+ if let Some(dir_name) = item.components().last() {
+ if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() {
+ info_process.dir_name = dir_name;
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+
+ let copied_bytes = result;
+ let dir_options = options.clone();
+ let handler = |info: dir::TransitProcess| {
+ info_process.copied_bytes = copied_bytes + info.copied_bytes;
+ info_process.state = info.state;
+ let result = progress_handler(info_process.clone());
+ match result {
+ dir::TransitProcessResult::OverwriteAll => options.overwrite = true,
+ dir::TransitProcessResult::SkipAll => options.skip_exist = true,
+ _ => {}
+ }
+ result
+ };
+ result += dir::copy_with_progress(item, &to, &dir_options, handler)?;
+ } else {
+ let mut file_options = file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ if let Some(file_name) = item.file_name() {
+ if let Some(file_name) = file_name.to_str() {
+ info_process.file_name = file_name.to_string();
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+
+ info_process.file_bytes_copied = 0;
+ info_process.file_total_bytes = item.metadata()?.len();
+
+ let copied_bytes = result;
+ let file_name = to.as_ref().join(info_process.file_name.clone());
+ let mut work = true;
+
+ let mut result_copy: Result<u64>;
+ while work {
+ {
+ let handler = |info: file::TransitProcess| {
+ info_process.copied_bytes = copied_bytes + info.copied_bytes;
+ info_process.file_bytes_copied = info.copied_bytes;
+ progress_handler(info_process.clone());
+ };
+ result_copy =
+ file::copy_with_progress(item, &file_name, &file_options, handler);
+ }
+ match result_copy {
+ Ok(val) => {
+ result += val;
+ work = false;
+ }
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ let mut info_process = info_process.clone();
+ info_process.state = dir::TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ dir::TransitProcessResult::Overwrite => {
+ file_options.overwrite = true;
+ }
+ dir::TransitProcessResult::OverwriteAll => {
+ file_options.overwrite = true;
+ options.overwrite = true;
+ }
+ dir::TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ dir::TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ dir::TransitProcessResult::Retry => {}
+ dir::TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ dir::TransitProcessResult::Abort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ ErrorKind::PermissionDenied => {
+ let mut info_process = info_process.clone();
+ info_process.state = dir::TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ dir::TransitProcessResult::Overwrite => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ dir::TransitProcessResult::OverwriteAll => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ dir::TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ dir::TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ dir::TransitProcessResult::Retry => {}
+ dir::TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ dir::TransitProcessResult::Abort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ _ => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ },
+ }
+ }
+ }
+ }
+
+ Ok(result)
+}
+
+/// Moves a list of directories and files to another place recursively. This function will
+/// also copy the permission bits of the original files to destination files (not for
+/// directories).
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these case:
+///
+/// * List `from` contains file or directory does not exist.
+///
+/// * List `from` contains file or directory with invalid name.
+///
+/// * The current process does not have the permission to access to file from `lists from` or
+/// `to`.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
+///
+/// // move dir1 and file1.txt to target/dir1 and target/file1.txt
+/// let mut from_paths = Vec::new();
+/// from_paths.push("source/dir1");
+/// from_paths.push("source/file.txt");
+/// move_items(&from_paths, "target", &options)?;
+/// ```
+///
+pub fn move_items<P, Q>(from_items: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ if options.content_only {
+ err!(
+ "Options 'content_only' not access for move_items function",
+ ErrorKind::Other
+ );
+ }
+ let mut total_size = 0;
+ let mut list_paths = Vec::new();
+ for item in from_items {
+ let item = item.as_ref();
+ total_size += dir::get_size(item)?;
+ list_paths.push(item);
+ }
+
+ let mut result = 0;
+ let mut info_process = TransitProcess {
+ copied_bytes: 0,
+ total_bytes: total_size,
+ file_bytes_copied: 0,
+ file_total_bytes: 0,
+ file_name: String::new(),
+ dir_name: String::new(),
+ state: dir::TransitState::Normal,
+ };
+
+ for item in list_paths {
+ if item.is_dir() {
+ if let Some(dir_name) = item.components().last() {
+ if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() {
+ info_process.dir_name = dir_name;
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+
+ result += dir::move_dir(item, &to, options)?;
+ } else {
+ let file_options = file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ if let Some(file_name) = item.file_name() {
+ if let Some(file_name) = file_name.to_str() {
+ info_process.file_name = file_name.to_string();
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+
+ info_process.file_bytes_copied = 0;
+ info_process.file_total_bytes = item.metadata()?.len();
+
+ let file_name = to.as_ref().join(info_process.file_name.clone());
+ result += file::move_file(item, &file_name, &file_options)?;
+ }
+ }
+
+ Ok(result)
+}
+
+/// Moves a list of directories and files to another place recursively, with
+/// information about progress. This function will also copy the permission bits of the
+/// original files to destination files (not for directories).
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these case:
+///
+/// * List `from` contains file or directory does not exist.
+///
+/// * List `from` contains file or directory with invalid name.
+///
+/// * The current process does not have the permission to access to file from `lists from` or
+/// `to`.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| {
+/// println!("{}", process_info.total_bytes);
+/// fs_extra::dir::TransitProcessResult::ContinueOrAbort
+/// }
+/// // move dir1 and file1.txt to target/dir1 and target/file1.txt
+/// let mut from_paths = Vec::new();
+/// from_paths.push("source/dir1");
+/// from_paths.push("source/file.txt");
+/// move_items_with_progress(&from_paths, "target", &options, handle)?;
+/// ```
+///
+pub fn move_items_with_progress<P, Q, F>(
+ from_items: &[P],
+ to: Q,
+ options: &dir::CopyOptions,
+ mut progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess) -> dir::TransitProcessResult,
+{
+ if options.content_only {
+ err!(
+ "Options 'content_only' not access for move_items_with_progress function",
+ ErrorKind::Other
+ );
+ }
+ let mut total_size = 0;
+ let mut list_paths = Vec::new();
+ for item in from_items {
+ let item = item.as_ref();
+ total_size += dir::get_size(item)?;
+ list_paths.push(item);
+ }
+
+ let mut result = 0;
+ let mut info_process = TransitProcess {
+ copied_bytes: 0,
+ total_bytes: total_size,
+ file_bytes_copied: 0,
+ file_total_bytes: 0,
+ file_name: String::new(),
+ dir_name: String::new(),
+ state: dir::TransitState::Normal,
+ };
+ let mut options = options.clone();
+
+ for item in list_paths {
+ if item.is_dir() {
+ if let Some(dir_name) = item.components().last() {
+ if let Ok(dir_name) = dir_name.as_os_str().to_os_string().into_string() {
+ info_process.dir_name = dir_name;
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+
+ let copied_bytes = result;
+ let dir_options = options.clone();
+ let handler = |info: dir::TransitProcess| {
+ info_process.copied_bytes = copied_bytes + info.copied_bytes;
+ info_process.state = info.state;
+ let result = progress_handler(info_process.clone());
+ match result {
+ dir::TransitProcessResult::OverwriteAll => options.overwrite = true,
+ dir::TransitProcessResult::SkipAll => options.skip_exist = true,
+ _ => {}
+ }
+ result
+ };
+ result += dir::move_dir_with_progress(item, &to, &dir_options, handler)?;
+ } else {
+ let mut file_options = file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ if let Some(file_name) = item.file_name() {
+ if let Some(file_name) = file_name.to_str() {
+ info_process.file_name = file_name.to_string();
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+
+ info_process.file_bytes_copied = 0;
+ info_process.file_total_bytes = item.metadata()?.len();
+
+ let copied_bytes = result;
+ let file_name = to.as_ref().join(info_process.file_name.clone());
+ let mut work = true;
+
+ let mut result_copy: Result<u64>;
+ while work {
+ {
+ let handler = |info: file::TransitProcess| {
+ info_process.copied_bytes = copied_bytes + info.copied_bytes;
+ info_process.file_bytes_copied = info.copied_bytes;
+ progress_handler(info_process.clone());
+ };
+ result_copy =
+ file::move_file_with_progress(item, &file_name, &file_options, handler);
+ }
+ match result_copy {
+ Ok(val) => {
+ result += val;
+ work = false;
+ }
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ let mut info_process = info_process.clone();
+ info_process.state = dir::TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ dir::TransitProcessResult::Overwrite => {
+ file_options.overwrite = true;
+ }
+ dir::TransitProcessResult::OverwriteAll => {
+ file_options.overwrite = true;
+ options.overwrite = true;
+ }
+ dir::TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ dir::TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ dir::TransitProcessResult::Retry => {}
+ dir::TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ dir::TransitProcessResult::Abort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ ErrorKind::PermissionDenied => {
+ let mut info_process = info_process.clone();
+ info_process.state = dir::TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ dir::TransitProcessResult::Overwrite => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ dir::TransitProcessResult::OverwriteAll => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ dir::TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ dir::TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ dir::TransitProcessResult::Retry => {}
+ dir::TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ dir::TransitProcessResult::Abort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ _ => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ },
+ }
+ }
+ }
+ }
+ Ok(result)
+}
+
+/// Removes a list of files or directories.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// let mut from_paths = Vec::new();
+/// from_paths.push("source/dir1");
+/// from_paths.push("source/file.txt");
+///
+/// remove_items(&from_paths).unwrap();
+/// ```
+///
+pub fn remove_items<P>(from_items: &[P]) -> Result<()>
+where
+ P: AsRef<Path>,
+{
+ for item in from_items {
+ let item = item.as_ref();
+ if item.is_dir() {
+ dir::remove(item)?;
+ } else {
+ file::remove(item)?
+ }
+ }
+
+ Ok(())
+}