summaryrefslogtreecommitdiffstats
path: root/vendor/fs_extra
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /vendor/fs_extra
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz
rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/fs_extra')
-rw-r--r--vendor/fs_extra/.cargo-checksum.json1
-rw-r--r--vendor/fs_extra/Cargo.toml26
-rw-r--r--vendor/fs_extra/LICENSE21
-rw-r--r--vendor/fs_extra/README.md134
-rw-r--r--vendor/fs_extra/src/dir.rs1398
-rw-r--r--vendor/fs_extra/src/error.rs158
-rw-r--r--vendor/fs_extra/src/file.rs413
-rw-r--r--vendor/fs_extra/src/lib.rs802
-rw-r--r--vendor/fs_extra/tests/dir.rs4824
-rw-r--r--vendor/fs_extra/tests/file.rs1036
-rw-r--r--vendor/fs_extra/tests/lib.rs3883
11 files changed, 12696 insertions, 0 deletions
diff --git a/vendor/fs_extra/.cargo-checksum.json b/vendor/fs_extra/.cargo-checksum.json
new file mode 100644
index 000000000..408d7d719
--- /dev/null
+++ b/vendor/fs_extra/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"84508fee5e8b314e18c1fab6d601975bff0b0897b9dbfe1fbf1451efe71a4449","LICENSE":"251ea8ccb1205ce5fa847d6e264d6b6753af62de2cecf2fd9abc0eb02c7c83fc","README.md":"6c72565b5c7e12dcdb4dbaca0034fd5c9721f38bf5952fd96c3947571df26db0","src/dir.rs":"888a2defde401d8fb1da5aa18b58efe210a0fdd9e74bdfa6867c3aa188de0b40","src/error.rs":"7306cb0e85081d7ef4b2d59cf5f068df7585c2d0ce3b5219c7c9448c20801a61","src/file.rs":"e6eefb1b91503b834571f8d27badbca8dac50c50f23d43b03277a52ed2c3edbb","src/lib.rs":"cb4ae7a8080a6de2cf99aae2338486cf777bb300f7d2082d98238b4eb746648c","tests/dir.rs":"20bda4edbaa23397e83361586e5742360fcbbec8f5bf46c9c208ee7b05a13db7","tests/file.rs":"06829b2db83e2805c87b83862c75cb1016ce7d12e5d8236eefbe39ffa16fa553","tests/lib.rs":"567eb582e8e1524b3f6c79cd8683fdd7b11cbd1ba5461b319cf2ffec211eb789"},"package":"42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"} \ No newline at end of file
diff --git a/vendor/fs_extra/Cargo.toml b/vendor/fs_extra/Cargo.toml
new file mode 100644
index 000000000..3f119234a
--- /dev/null
+++ b/vendor/fs_extra/Cargo.toml
@@ -0,0 +1,26 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "fs_extra"
+version = "1.3.0"
+authors = ["Denis Kurilenko <webdesus@gmail.com>"]
+include = ["**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md"]
+description = "Expanding std::fs and std::io. Recursively copy folders with information about process and much more."
+homepage = "https://github.com/webdesus/fs_extra"
+documentation = "https://docs.rs/fs_extra"
+keywords = ["filesystem", "recursion", "copy", "dir", "file"]
+license = "MIT"
+repository = "https://github.com/webdesus/fs_extra"
+
+[dependencies]
diff --git a/vendor/fs_extra/LICENSE b/vendor/fs_extra/LICENSE
new file mode 100644
index 000000000..2f97c3d7d
--- /dev/null
+++ b/vendor/fs_extra/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Denis Kurilenko
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/fs_extra/README.md b/vendor/fs_extra/README.md
new file mode 100644
index 000000000..13aee1ea7
--- /dev/null
+++ b/vendor/fs_extra/README.md
@@ -0,0 +1,134 @@
+# fs_extra
+
+A Rust library that provides additional functionality not present in [`std::fs`](https://doc.rust-lang.org/std/fs/index.html).
+
+[![Build Status](https://travis-ci.org/webdesus/fs_extra.svg)](https://travis-ci.org/webdesus/fs_extra)
+[![Crates.io Status](https://img.shields.io/crates/v/fs_extra.svg)](https://crates.io/crates/fs_extra)
+[![Docs](https://docs.rs/fs_extra/badge.svg)](https://docs.rs/fs_extra)
+
+[Documentation](https://docs.rs/fs_extra)
+
+[Migrations to 1.x.x version](https://github.com/webdesus/fs_extra/wiki/Migrations-to-1.x.x-version)
+
+
+## Key features:
+
+* Copy files (optionally with information about the progress).
+
+* Copy directories recursively (optionally with information about the progress).
+
+* Move files (optionally with information about the progress).
+
+* Move directories recursively (optionally with information about the progress).
+
+* A single method for create and write `String` content in file.
+
+* A single method for open and read `String` content from file.
+
+* Get folder size
+
+* Get collection of directory entries
+
+## Functions:
+
+| Function | Description |
+| ------------- | ------------- |
+| [fs_extra::copy_items](https://docs.rs/fs_extra/*/fs_extra/fn.copy_items.html) | Recursively copies files and directories from one location to another |
+| [fs_extra::copy_items_with_progress](https://docs.rs/fs_extra/*/fs_extra/fn.copy_items_with_progress.html) | Recursively copies files and directories from one location to another with information about progress |
+| [fs_extra::move_items](https://docs.rs/fs_extra/*/fs_extra/fn.move_items.html) | Recursively moves files and directories from one location to another |
+| [fs_extra::move_items_with_progress](https://docs.rs/fs_extra/*/fs_extra/fn.move_items_with_progress.html) | Recursively moves files and directories from one location to another with information about progress |
+| [fs_extra::remove_items](https://docs.rs/fs_extra/*/fs_extra/fn.remove_items.html) | Removes files or directories |
+| [fs_extra::file::copy](https://docs.rs/fs_extra/*/fs_extra/file/fn.copy.html) | Copies the contents of one file to another |
+| [fs_extra::file::copy_with_progress](https://docs.rs/fs_extra/*/fs_extra/file/fn.copy_with_progress.html) | Copies the contents of one file to another with information about progress |
+| [fs_extra::file::move_file](https://docs.rs/fs_extra/*/fs_extra/file/fn.move_file.html) | Moves a file from one location to another |
+| [fs_extra::file::move_file_with_progress](https://docs.rs/fs_extra/*/fs_extra/file/fn.move_file_with_progress.html) | Moves a file from one location to another with information about progress |
+| [fs_extra::file::remove](https://docs.rs/fs_extra/*/fs_extra/file/fn.remove.html) | Removes a file |
+| [fs_extra::file::read_to_string](https://docs.rs/fs_extra/*/fs_extra/file/fn.read_to_string.html) | Reads file content into a `String` |
+| [fs_extra::file::write_all](https://docs.rs/fs_extra/*/fs_extra/file/fn.write_all.html) | Writes `String` content to a file |
+| [fs_extra::dir::create](https://docs.rs/fs_extra/*/fs_extra/dir/fn.create.html) | Creates a new, empty directory at the given path |
+| [fs_extra::dir::create_all](https://docs.rs/fs_extra/*/fs_extra/dir/fn.create_all.html) | Recursively creates a directory and all of its parent components if they are missing |
+| [fs_extra::dir::copy](https://docs.rs/fs_extra/*/fs_extra/dir/fn.copy.html) | Recursively copies the directory contents from one location to another |
+| [fs_extra::dir::copy_with_progress](https://docs.rs/fs_extra/*/fs_extra/dir/fn.copy_with_progress.html) | Recursively copies the directory contents from one location to another with information about progress |
+| [fs_extra::dir::move_dir](https://docs.rs/fs_extra/*/fs_extra/dir/fn.move_dir.html) | Moves directory contents from one location to another |
+| [fs_extra::dir::move_dir_with_progress](https://docs.rs/fs_extra/*/fs_extra/dir/fn.move_dir_with_progress.html) | Moves directory contents from one location to another with information about progress |
+| [fs_extra::dir::remove](https://docs.rs/fs_extra/*/fs_extra/dir/fn.remove.html) | Removes directory |
+| [fs_extra::dir::get_size](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_size.html) | Returns the size of the file or directory |
+| [fs_extra::dir::get_dir_content](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_dir_content.html) | Gets details such as the size and child items of a directory |
+| [fs_extra::dir::get_dir_content2](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_dir_content2.html) | Gets details such as the size and child items of a directory using specified settings |
+| [fs_extra::dir::get_details_entry](https://docs.rs/fs_extra/*/fs_extra/dir/fn.get_details_entry.html) | Gets attributes of a directory entry |
+| [fs_extra::dir::ls](https://docs.rs/fs_extra/*/fs_extra/dir/fn.ls.html) | Gets attributes of directory entries in a directory |
+
+## Usage
+
+Add this to your `Cargo.toml`:
+```toml
+[dependencies]
+fs_extra = "1.3.0"
+```
+## Examples
+
+The following example shows how to copy a directory recursively and display progress. First a source directory `./temp/dir` containing file `test1.txt` and a subdirectory `sub` is createad with `sub` itself having a file `test2.txt`. `./temp/dir` and all contents are then copied out to `./out/dir`.
+
+```rust
+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 mut options = CopyOptions::new();
+ options.buffer_size = 1;
+ 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));
+ fs_extra::dir::TransitProcessResult::ContinueOrAbort
+ };
+ 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();
+}
+```
diff --git a/vendor/fs_extra/src/dir.rs b/vendor/fs_extra/src/dir.rs
new file mode 100644
index 000000000..a5d111249
--- /dev/null
+++ b/vendor/fs_extra/src/dir.rs
@@ -0,0 +1,1398 @@
+use crate::error::*;
+use std::collections::{HashMap, HashSet};
+use std::fs::{create_dir, create_dir_all, read_dir, remove_dir_all, Metadata};
+use std::path::{Path, PathBuf};
+use std::time::SystemTime;
+
+/// Options and flags which can be used to configure how a file will be copied or moved.
+#[derive(Clone)]
+pub struct CopyOptions {
+ /// Overwrite existing files if true (default: false).
+ pub overwrite: bool,
+ /// Skip existing files if true (default: false).
+ pub skip_exist: bool,
+ /// Buffer size that specifies the amount of bytes to be moved or copied before the progress handler is called. This only affects functions with progress handlers. (default: 64000)
+ pub buffer_size: usize,
+ /// Recursively copy a directory with a new name or place it inside the destination (default: false, same behaviors as cp -r on Unix)
+ pub copy_inside: bool,
+ /// Copy only contents without a creating a new folder in the destination folder (default: false).
+ pub content_only: bool,
+ /// Sets levels reading. Set 0 for read all directory folder (default: 0).
+ ///
+ /// Warning: Work only for copy operations!
+ pub depth: u64,
+}
+
+impl CopyOptions {
+ /// Initialize struct CopyOptions with default value.
+ ///
+ /// ```rust,ignore
+ /// overwrite: false
+ ///
+ /// skip_exist: false
+ ///
+ /// buffer_size: 64000 // 64kb
+ ///
+ /// copy_inside: false
+ /// ```
+ pub fn new() -> CopyOptions {
+ CopyOptions {
+ overwrite: false,
+ skip_exist: false,
+ buffer_size: 64000, // 64kb
+ copy_inside: false,
+ content_only: false,
+ depth: 0,
+ }
+ }
+
+ /// Overwrite existing files if true.
+ pub fn overwrite(mut self, overwrite: bool) -> Self {
+ self.overwrite = overwrite;
+ self
+ }
+
+ /// Skip existing files if true.
+ pub fn skip_exist(mut self, skip_exist: bool) -> Self {
+ self.skip_exist = skip_exist;
+ self
+ }
+
+ /// Buffer size that specifies the amount of bytes to be moved or copied before the progress handler is called. This only affects functions with progress handlers.
+ pub fn buffer_size(mut self, buffer_size: usize) -> Self {
+ self.buffer_size = buffer_size;
+ self
+ }
+
+ /// Recursively copy a directory with a new name or place it inside the destination (default: false, same behaviors as cp -r on Unix)
+ pub fn copy_inside(mut self, copy_inside: bool) -> Self {
+ self.copy_inside = copy_inside;
+ self
+ }
+
+ /// Copy only contents without a creating a new folder in the destination folder.
+ pub fn content_only(mut self, content_only: bool) -> Self {
+ self.content_only = content_only;
+ self
+ }
+
+ /// Sets levels reading. Set 0 for read all directory folder
+ pub fn depth(mut self, depth: u64) -> Self {
+ self.depth = depth;
+ self
+ }
+}
+
+impl Default for CopyOptions {
+ fn default() -> Self {
+ CopyOptions::new()
+ }
+}
+
+// Options and flags which can be used to configure how to read a directory.
+#[derive(Clone, Default)]
+pub struct DirOptions {
+ /// Sets levels reading. Set value 0 for read all directory folder. By default 0.
+ pub depth: u64,
+}
+
+impl DirOptions {
+ /// Initialize struct DirOptions with default value.
+ pub fn new() -> DirOptions {
+ Default::default()
+ }
+}
+
+/// A structure which include information about directory
+pub struct DirContent {
+ /// Directory size in bytes.
+ pub dir_size: u64,
+ /// List all files directory and sub directories.
+ pub files: Vec<String>,
+ /// List all folders and sub folders directory.
+ pub directories: Vec<String>,
+}
+
+/// A structure which include information about the current status of the copy or move directory.
+pub struct TransitProcess {
+ /// Copied bytes on this time for folder
+ pub copied_bytes: u64,
+ /// All the bytes which should to copy or move (dir size).
+ pub total_bytes: u64,
+ /// Copied bytes on this time for file.
+ pub file_bytes_copied: u64,
+ /// Size current copied file.
+ pub file_total_bytes: u64,
+ /// Name current copied file.
+ pub file_name: String,
+ /// Transit state
+ pub state: TransitState,
+}
+
+///
+#[derive(Hash, Eq, PartialEq, Clone)]
+pub enum TransitState {
+ /// Standard state.
+ Normal,
+ /// Pause state when destination path exists.
+ Exists,
+ /// Pause state when current process does not have the permission to access from or to
+ /// path.
+ NoAccess,
+}
+
+/// Available returns codes for user decide
+pub enum TransitProcessResult {
+ /// Rewrite exist file or directory.
+ Overwrite,
+ /// Rewrite for all exist files or directories.
+ OverwriteAll,
+ /// Skip current problem file or directory.
+ Skip,
+ /// Skip for all problems file or directory.
+ SkipAll,
+ /// Retry current operation.
+ Retry,
+ /// Abort current operation.
+ Abort,
+ /// Continue execute process if process not have error and abort if process content error.
+ ContinueOrAbort,
+}
+
+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(),
+ state: self.state.clone(),
+ }
+ }
+}
+
+/// Available attributes for get information about directory entry.
+#[derive(Hash, Eq, PartialEq, Clone)]
+pub enum DirEntryAttr {
+ /// Folder name or file name without extension.
+ Name,
+ /// File extension.
+ Ext,
+ /// Folder name or file name with extension.
+ FullName,
+ /// Path to file or directory.
+ Path,
+ /// Dos path to file or directory.
+ DosPath,
+ /// File size in bytes.
+ FileSize,
+ /// Size file or directory in bytes.
+ ///
+ /// `Attention!`: This operation very expensive and sometimes required additional rights.
+ Size,
+ /// Return whether entry is directory or not.
+ IsDir,
+ /// Return whether entry is file or not.
+ IsFile,
+ /// Last modification time for directory entry.
+ Modified,
+ /// Last access time for directory entry.
+ Accessed,
+ /// Created time for directory entry.
+ ///
+ /// `Attention!`: Not supported UNIX platform.
+ Created,
+ /// Return or not return base information target folder.
+ BaseInfo,
+}
+
+/// Available types for directory entry.
+pub enum DirEntryValue {
+ /// String type
+ String(String),
+ /// Boolean type
+ Boolean(bool),
+ /// SystemTime type
+ SystemTime(SystemTime),
+ /// u64 type
+ U64(u64),
+}
+
+/// Result returned by the `ls` function.
+pub struct LsResult {
+ /// Base folder target path
+ pub base: HashMap<DirEntryAttr, DirEntryValue>,
+ /// Collection directory entry with information.
+ pub items: Vec<HashMap<DirEntryAttr, DirEntryValue>>,
+}
+
+/// Returned information about directory entry with information which you choose in config.
+///
+/// This function takes to arguments:
+///
+/// * `path` - Path to directory.
+///
+/// * `config` - Set attributes which you want see inside return data.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` does not exist.
+/// * Invalid `path`.
+/// * The current process does not have the permission to access `path`.
+///
+/// #Examples
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::{get_details_entry, DirEntryAttr};
+/// use std::collections::{HashMap, HashSet};
+///
+/// let mut config = HashSet::new();
+/// config.insert(DirEntryAttr::Name);
+/// config.insert(DirEntryAttr::Size);
+///
+/// let entry_info = get_details_entry("test", &config);
+/// assert_eq!(2, entry_info.len());
+/// ```
+pub fn get_details_entry<P>(
+ path: P,
+ config: &HashSet<DirEntryAttr>,
+) -> Result<HashMap<DirEntryAttr, DirEntryValue>>
+where
+ P: AsRef<Path>,
+{
+ let path = path.as_ref();
+ let metadata = path.metadata()?;
+ get_details_entry_with_meta(path, config, metadata)
+}
+
+fn get_details_entry_with_meta<P>(
+ path: P,
+ config: &HashSet<DirEntryAttr>,
+ metadata: Metadata,
+) -> Result<HashMap<DirEntryAttr, DirEntryValue>>
+where
+ P: AsRef<Path>,
+{
+ let path = path.as_ref();
+ let mut item = HashMap::new();
+ if config.contains(&DirEntryAttr::Name) {
+ if metadata.is_dir() {
+ if let Some(file_name) = path.file_name() {
+ item.insert(
+ DirEntryAttr::Name,
+ DirEntryValue::String(file_name.to_os_string().into_string()?),
+ );
+ } else {
+ item.insert(DirEntryAttr::Name, DirEntryValue::String(String::new()));
+ }
+ } else if let Some(file_stem) = path.file_stem() {
+ item.insert(
+ DirEntryAttr::Name,
+ DirEntryValue::String(file_stem.to_os_string().into_string()?),
+ );
+ } else {
+ item.insert(DirEntryAttr::Name, DirEntryValue::String(String::new()));
+ }
+ }
+ if config.contains(&DirEntryAttr::Ext) {
+ if let Some(value) = path.extension() {
+ item.insert(
+ DirEntryAttr::Ext,
+ DirEntryValue::String(value.to_os_string().into_string()?),
+ );
+ } else {
+ item.insert(DirEntryAttr::Ext, DirEntryValue::String(String::from("")));
+ }
+ }
+ if config.contains(&DirEntryAttr::FullName) {
+ if let Some(file_name) = path.file_name() {
+ item.insert(
+ DirEntryAttr::FullName,
+ DirEntryValue::String(file_name.to_os_string().into_string()?),
+ );
+ } else {
+ item.insert(DirEntryAttr::FullName, DirEntryValue::String(String::new()));
+ }
+ }
+ if config.contains(&DirEntryAttr::Path) {
+ let mut result_path: PathBuf;
+ match path.canonicalize() {
+ Ok(new_path) => {
+ result_path = new_path;
+ }
+ Err(_) => {
+ if let Some(parent_path) = path.parent() {
+ if let Some(name) = path.file_name() {
+ result_path = parent_path.canonicalize()?;
+ result_path.push(name);
+ } else {
+ err!("Error get part name path", ErrorKind::Other);
+ }
+ } else {
+ err!("Error get parent path", ErrorKind::Other);
+ }
+ }
+ }
+ let mut path = result_path.as_os_str().to_os_string().into_string()?;
+ if path.find("\\\\?\\") == Some(0) {
+ path = path[4..].to_string();
+ }
+ item.insert(DirEntryAttr::Path, DirEntryValue::String(path));
+ }
+ if config.contains(&DirEntryAttr::DosPath) {
+ let mut result_path: PathBuf;
+ match path.canonicalize() {
+ Ok(new_path) => {
+ result_path = new_path;
+ }
+ Err(_) => {
+ if let Some(parent_path) = path.parent() {
+ if let Some(name) = path.file_name() {
+ result_path = parent_path.canonicalize()?;
+ result_path.push(name);
+ } else {
+ err!("Error get part name path", ErrorKind::Other);
+ }
+ } else {
+ err!("Error get parent path", ErrorKind::Other);
+ }
+ }
+ }
+ let path = result_path.as_os_str().to_os_string().into_string()?;
+ item.insert(DirEntryAttr::DosPath, DirEntryValue::String(path));
+ }
+ if config.contains(&DirEntryAttr::Size) {
+ item.insert(DirEntryAttr::Size, DirEntryValue::U64(get_size(&path)?));
+ }
+ if config.contains(&DirEntryAttr::FileSize) {
+ item.insert(DirEntryAttr::FileSize, DirEntryValue::U64(metadata.len()));
+ }
+ if config.contains(&DirEntryAttr::IsDir) {
+ item.insert(
+ DirEntryAttr::IsDir,
+ DirEntryValue::Boolean(metadata.is_dir()),
+ );
+ }
+ if config.contains(&DirEntryAttr::IsFile) {
+ item.insert(
+ DirEntryAttr::IsFile,
+ DirEntryValue::Boolean(metadata.is_file()),
+ );
+ }
+ if config.contains(&DirEntryAttr::Modified) {
+ item.insert(
+ DirEntryAttr::Modified,
+ DirEntryValue::SystemTime(metadata.modified()?),
+ );
+ }
+ if config.contains(&DirEntryAttr::Accessed) {
+ item.insert(
+ DirEntryAttr::Accessed,
+ DirEntryValue::SystemTime(metadata.accessed()?),
+ );
+ }
+ if config.contains(&DirEntryAttr::Created) {
+ item.insert(
+ DirEntryAttr::Created,
+ DirEntryValue::SystemTime(metadata.created()?),
+ );
+ }
+ Ok(item)
+}
+
+/// Returns a collection of directory entries with attributes specifying the information that should be returned.
+///
+/// This function takes to arguments:
+///
+/// * `path` - Path to directory.
+///
+/// * `config` - Set attributes which you want see in return data.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` directory does not exist.
+/// * Invalid `path`.
+/// * The current process does not have the permission to access `path`.
+///
+/// #Examples
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::{ls, DirEntryAttr, LsResult};
+/// use std::collections::HashSet;
+///
+/// let mut config = HashSet::new();
+/// config.insert(DirEntryAttr::Name);
+/// config.insert(DirEntryAttr::Size);
+/// config.insert(DirEntryAttr::BaseInfo);
+///
+/// let result = ls("test", &config);
+/// assert_eq!(2, ls_result.items.len());
+/// assert_eq!(2, ls_result.base.len());
+/// ```
+pub fn ls<P>(path: P, config: &HashSet<DirEntryAttr>) -> Result<LsResult>
+where
+ P: AsRef<Path>,
+{
+ let mut items = Vec::new();
+ let path = path.as_ref();
+ if !path.is_dir() {
+ err!("Path does not directory", ErrorKind::InvalidFolder);
+ }
+ for entry in read_dir(&path)? {
+ let entry = entry?;
+ let path = entry.path();
+ let metadata = entry.metadata()?;
+ let item = get_details_entry_with_meta(path, &config, metadata)?;
+ items.push(item);
+ }
+ let mut base = HashMap::new();
+ if config.contains(&DirEntryAttr::BaseInfo) {
+ base = get_details_entry(&path, &config)?;
+ }
+ Ok(LsResult { items, base })
+}
+
+/// Creates a new, empty directory at the provided path.
+///
+/// This function takes to arguments:
+///
+/// * `path` - Path to new directory.
+///
+/// * `erase` - If set true and folder exist, then folder will be erased.
+///
+/// #Errors
+///
+/// This function will return an error in the following situations,
+/// but is not limited to just these cases:
+///
+/// * User lacks permissions to create directory at `path`.
+///
+/// * `path` already exists if `erase` set false.
+///
+/// #Examples
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::create;
+///
+/// create("dir", false); // create directory
+/// ```
+pub fn create<P>(path: P, erase: bool) -> Result<()>
+where
+ P: AsRef<Path>,
+{
+ if erase && path.as_ref().exists() {
+ remove(&path)?;
+ }
+ Ok(create_dir(&path)?)
+}
+
+/// Recursively create a directory and all of its parent components if they are missing.
+///
+/// This function takes to arguments:
+///
+/// * `path` - Path to new directory.
+///
+/// * `erase` - If set true and folder exist, then folder will be erased.
+///
+///#Errors
+///
+/// This function will return an error in the following situations,
+/// but is not limited to just these cases:
+///
+/// * User lacks permissions to create directory at `path`.
+///
+/// * `path` already exists if `erase` set false.
+///
+/// #Examples
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::create_all;
+///
+/// create_all("/some/dir", false); // create directory some and dir
+pub fn create_all<P>(path: P, erase: bool) -> Result<()>
+where
+ P: AsRef<Path>,
+{
+ if erase && path.as_ref().exists() {
+ remove(&path)?;
+ }
+ Ok(create_dir_all(&path)?)
+}
+
+/// Copies the directory contents from one place to another using recursive method.
+/// 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 cases:
+///
+/// * This `from` path is not a directory.
+/// * This `from` directory does not exist.
+/// * Invalid folder name for `from` or `to`.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// // options.mirror_copy = true; // To mirror copy the whole structure of the source directory
+///
+///
+/// // copy source/dir1 to target/dir1
+/// copy("source/dir1", "target/dir1", &options)?;
+///
+/// ```
+pub fn copy<P, Q>(from: P, to: Q, options: &CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let from = from.as_ref();
+
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist or you don't have access!", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist Or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+ if !from.is_dir() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" is not a directory!", msg);
+ err!(&msg, ErrorKind::InvalidFolder);
+ }
+ err!("Path is not a directory!", ErrorKind::InvalidFolder);
+ }
+ let dir_name;
+ if let Some(val) = from.components().last() {
+ dir_name = val.as_os_str();
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ let mut to: PathBuf = to.as_ref().to_path_buf();
+ if (to.exists() || !options.copy_inside) && !options.content_only {
+ to.push(dir_name);
+ }
+
+ let mut read_options = DirOptions::new();
+ if options.depth > 0 {
+ read_options.depth = options.depth;
+ }
+
+ let dir_content = get_dir_content2(from, &read_options)?;
+ for directory in dir_content.directories {
+ let tmp_to = Path::new(&directory).strip_prefix(from)?;
+ let dir = to.join(&tmp_to);
+ if !dir.exists() {
+ if options.copy_inside {
+ create_all(dir, false)?;
+ } else {
+ create(dir, false)?;
+ }
+ }
+ }
+ let mut result: u64 = 0;
+ for file in dir_content.files {
+ let to = to.to_path_buf();
+ let tp = Path::new(&file).strip_prefix(from)?;
+ let path = to.join(&tp);
+
+ let file_options = super::file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+ let mut result_copy: Result<u64>;
+ let mut work = true;
+
+ while work {
+ result_copy = super::file::copy(&file, &path, &file_options);
+ match result_copy {
+ Ok(val) => {
+ result += val;
+ work = false;
+ }
+ Err(err) => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ }
+ Ok(result)
+}
+
+/// Return DirContent which contains information about directory:
+///
+/// * Size of the directory in bytes.
+/// * List of source paths of files in the directory (files inside subdirectories included too).
+/// * List of source paths of all directories and subdirectories.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` directory does not exist.
+/// * Invalid `path`.
+/// * The current process does not have the permission to access `path`.
+///
+/// # Examples
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::get_dir_content;
+///
+/// let dir_content = get_dir_content("dir")?;
+/// for directory in dir_content.directories {
+/// println!("{}", directory); // print directory path
+/// }
+/// ```
+///
+pub fn get_dir_content<P>(path: P) -> Result<DirContent>
+where
+ P: AsRef<Path>,
+{
+ let options = DirOptions::new();
+ get_dir_content2(path, &options)
+}
+
+/// Return DirContent which contains information about directory:
+///
+/// * Size directory.
+/// * List all files source directory(files subdirectories included too).
+/// * List all directory and subdirectories source path.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` directory does not exist.
+/// * Invalid `path`.
+/// * The current process does not have the permission to access `path`.
+///
+/// # Examples
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::{DirOptions, get_dir_content2};
+///
+/// let mut options = DirOptions::new();
+/// options.depth = 3; // Get 3 levels of folder.
+/// let dir_content = get_dir_content2("dir", &options)?;
+/// for directory in dir_content.directories {
+/// println!("{}", directory); // print directory path
+/// }
+/// ```
+///
+pub fn get_dir_content2<P>(path: P, options: &DirOptions) -> Result<DirContent>
+where
+ P: AsRef<Path>,
+{
+ let mut depth = 0;
+ if options.depth != 0 {
+ depth = options.depth + 1;
+ }
+ _get_dir_content(path, depth)
+}
+
+fn _get_dir_content<P>(path: P, mut depth: u64) -> Result<DirContent>
+where
+ P: AsRef<Path>,
+{
+ let mut directories = Vec::new();
+ let mut files = Vec::new();
+ let mut dir_size;
+ let item = path.as_ref().to_str();
+ if item.is_none() {
+ err!("Invalid path", ErrorKind::InvalidPath);
+ }
+ let item = item.unwrap().to_string();
+
+ if path.as_ref().is_dir() {
+ dir_size = path.as_ref().metadata()?.len();
+ directories.push(item);
+ if depth == 0 || depth > 1 {
+ if depth > 1 {
+ depth -= 1;
+ }
+ for entry in read_dir(&path)? {
+ let _path = entry?.path();
+
+ match _get_dir_content(_path, depth) {
+ Ok(items) => {
+ let mut _files = items.files;
+ let mut _directories = items.directories;
+ dir_size += items.dir_size;
+ files.append(&mut _files);
+ directories.append(&mut _directories);
+ }
+ Err(err) => return Err(err),
+ }
+ }
+ }
+ } else {
+ dir_size = path.as_ref().metadata()?.len();
+ files.push(item);
+ }
+ Ok(DirContent {
+ dir_size,
+ files,
+ directories,
+ })
+}
+
+/// Returns the size of the file or directory in bytes.(!important: folders size not count)
+///
+/// If used on a directory, this function will recursively iterate over every file and every
+/// directory inside the directory. This can be very time consuming if used on large directories.
+///
+/// Does not follow symlinks.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` directory does not exist.
+/// * Invalid `path`.
+/// * The current process does not have the permission to access `path`.
+///
+/// # Examples
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::get_size;
+///
+/// let folder_size = get_size("dir")?;
+/// println!("{}", folder_size); // print directory size in bytes
+/// ```
+pub fn get_size<P>(path: P) -> Result<u64>
+where
+ P: AsRef<Path>,
+{
+ // Using `fs::symlink_metadata` since we don't want to follow symlinks,
+ // as we're calculating the exact size of the requested path itself.
+ let path_metadata = path.as_ref().symlink_metadata()?;
+
+ let mut size_in_bytes = 0;
+
+ if path_metadata.is_dir() {
+ for entry in read_dir(&path)? {
+ let entry = entry?;
+ // `DirEntry::metadata` does not follow symlinks (unlike `fs::metadata`), so in the
+ // case of symlinks, this is the size of the symlink itself, not its target.
+ let entry_metadata = entry.metadata()?;
+
+ if entry_metadata.is_dir() {
+ // The size of the directory entry itself will be counted inside the `get_size()` call,
+ // so we intentionally don't also add `entry_metadata.len()` to the total here.
+ size_in_bytes += get_size(entry.path())?;
+ } else {
+ size_in_bytes += entry_metadata.len();
+ }
+ }
+ } else {
+ size_in_bytes = path_metadata.len();
+ }
+
+ Ok(size_in_bytes)
+}
+
+/// Copies the directory contents from one place to another using recursive method,
+/// 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 cases:
+///
+/// * This `from` path is not a directory.
+/// * This `from` directory does not exist.
+/// * Invalid folder name for `from` or `to`.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::copy;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| {
+/// println!("{}", process_info.total_bytes);
+/// fs_extra::dir::TransitProcessResult::ContinueOrAbort
+/// }
+/// // copy source/dir1 to target/dir1
+/// copy_with_progress("source/dir1", "target/dir1", &options, handle)?;
+///
+/// ```
+pub fn copy_with_progress<P, Q, F>(
+ from: P,
+ to: Q,
+ options: &CopyOptions,
+ mut progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess) -> TransitProcessResult,
+{
+ let from = from.as_ref();
+
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist or you don't have access!", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+
+ let mut to: PathBuf = to.as_ref().to_path_buf();
+ if !from.is_dir() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" is not a directory!", msg);
+ err!(&msg, ErrorKind::InvalidFolder);
+ }
+ err!("Path is not a directory!", ErrorKind::InvalidFolder);
+ }
+
+ let dir_name;
+ if let Some(val) = from.components().last() {
+ dir_name = val.as_os_str();
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ if (to.exists() || !options.copy_inside) && !options.content_only {
+ to.push(dir_name);
+ }
+
+ let mut read_options = DirOptions::new();
+ if options.depth > 0 {
+ read_options.depth = options.depth;
+ }
+
+ let dir_content = get_dir_content2(from, &read_options)?;
+ for directory in dir_content.directories {
+ let tmp_to = Path::new(&directory).strip_prefix(from)?;
+ let dir = to.join(&tmp_to);
+ if !dir.exists() {
+ if options.copy_inside {
+ create_all(dir, false)?;
+ } else {
+ create(dir, false)?;
+ }
+ }
+ }
+
+ let mut result: u64 = 0;
+ let mut info_process = TransitProcess {
+ copied_bytes: 0,
+ total_bytes: dir_content.dir_size,
+ file_bytes_copied: 0,
+ file_total_bytes: 0,
+ file_name: String::new(),
+ state: TransitState::Normal,
+ };
+
+ let mut options = options.clone();
+ for file in dir_content.files {
+ let mut to = to.to_path_buf();
+ let tp = Path::new(&file).strip_prefix(from)?;
+ let path = to.join(&tp);
+
+ let file_name = path.file_name();
+ if file_name.is_none() {
+ err!("No file name");
+ }
+ let file_name = file_name.unwrap();
+ to.push(file_name);
+
+ let mut file_options = super::file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ if let Some(file_name) = file_name.to_str() {
+ info_process.file_name = file_name.to_string();
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+
+ info_process.file_bytes_copied = 0;
+ info_process.file_total_bytes = Path::new(&file).metadata()?.len();
+
+ let mut result_copy: Result<u64>;
+ let mut work = true;
+ let copied_bytes = result;
+ while work {
+ {
+ let _progress_handler = |info: super::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 =
+ super::file::copy_with_progress(&file, &path, &file_options, _progress_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 = TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ TransitProcessResult::Overwrite => {
+ file_options.overwrite = true;
+ }
+ TransitProcessResult::OverwriteAll => {
+ file_options.overwrite = true;
+ options.overwrite = true;
+ }
+ TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ TransitProcessResult::Retry => {}
+ TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ 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 = TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ TransitProcessResult::Overwrite => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ TransitProcessResult::OverwriteAll => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ TransitProcessResult::Skip => {
+ file_options.skip_exist = true;
+ }
+ TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ TransitProcessResult::Retry => {}
+ TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ 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 the directory contents from one place to another.
+/// 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 cases:
+///
+/// * This `from` path is not a directory.
+/// * This `from` directory does not exist.
+/// * Invalid folder name for `from` or `to`.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::move_dir;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+///
+/// // move source/dir1 to target/dir1
+/// move_dir("source/dir1", "target/dir1", &options)?;
+///
+/// ```
+pub fn move_dir<P, Q>(from: P, to: Q, options: &CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let mut is_remove = true;
+ if options.skip_exist && to.as_ref().exists() && !options.overwrite {
+ is_remove = false;
+ }
+ let from = from.as_ref();
+
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+
+ let mut to: PathBuf = to.as_ref().to_path_buf();
+ if !from.is_dir() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!(
+ "Path \"{}\" is not a directory or you don't have access!",
+ msg
+ );
+ err!(&msg, ErrorKind::InvalidFolder);
+ }
+ err!(
+ "Path is not a directory or you don't have access!",
+ ErrorKind::InvalidFolder
+ );
+ }
+ let dir_name;
+ if let Some(val) = from.components().last() {
+ dir_name = val.as_os_str();
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+
+ if (to.exists() || !options.copy_inside) && !options.content_only {
+ to.push(dir_name);
+ }
+ let dir_content = get_dir_content(from)?;
+ for directory in dir_content.directories {
+ let tmp_to = Path::new(&directory).strip_prefix(from)?;
+ let dir = to.join(&tmp_to);
+ if !dir.exists() {
+ if options.copy_inside {
+ create_all(dir, false)?;
+ } else {
+ create(dir, false)?;
+ }
+ }
+ }
+ let mut result: u64 = 0;
+ for file in dir_content.files {
+ let to = to.to_path_buf();
+ let tp = Path::new(&file).strip_prefix(from)?;
+ let path = to.join(&tp);
+
+ let file_options = super::file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ let mut result_copy: Result<u64>;
+ let mut work = true;
+ while work {
+ {
+ result_copy = super::file::move_file(&file, &path, &file_options);
+ match result_copy {
+ Ok(val) => {
+ result += val;
+ work = false;
+ }
+ Err(err) => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ }
+ }
+ }
+ }
+ if is_remove {
+ remove(from)?;
+ }
+
+ Ok(result)
+}
+
+/// Moves the directory contents from one place to another 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 cases:
+///
+/// * This `from` path is not a directory.
+/// * This `from` directory does not exist.
+/// * Invalid folder name for `from` or `to`.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::move_dir_with_progress;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| {
+/// println!("{}", process_info.total_bytes);
+/// fs_extra::dir::TransitProcessResult::ContinueOrAbort
+/// }
+///
+/// // move source/dir1 to target/dir1
+/// move_dir_with_progress("source/dir1", "target/dir1", &options, handle)?;
+///
+/// ```
+pub fn move_dir_with_progress<P, Q, F>(
+ from: P,
+ to: Q,
+ options: &CopyOptions,
+ mut progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess) -> TransitProcessResult,
+{
+ let mut is_remove = true;
+ if options.skip_exist && to.as_ref().exists() && !options.overwrite {
+ is_remove = false;
+ }
+ let from = from.as_ref();
+
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist or you don't have access!", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+
+ let mut to: PathBuf = to.as_ref().to_path_buf();
+ if !from.is_dir() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" is not a directory!", msg);
+ err!(&msg, ErrorKind::InvalidFolder);
+ }
+ err!("Path is not a directory!", ErrorKind::InvalidFolder);
+ }
+ let dir_name;
+ if let Some(val) = from.components().last() {
+ dir_name = val.as_os_str();
+ } else {
+ err!("Invalid folder from", ErrorKind::InvalidFolder);
+ }
+ if !(options.content_only || options.copy_inside && !to.exists()) {
+ to.push(dir_name);
+ }
+
+ let dir_content = get_dir_content(from)?;
+ for directory in dir_content.directories {
+ let tmp_to = Path::new(&directory).strip_prefix(from)?;
+ let dir = to.join(&tmp_to);
+ if !dir.exists() {
+ if options.copy_inside {
+ create_all(dir, false)?;
+ } else {
+ create(dir, false)?;
+ }
+ }
+ }
+
+ let mut result: u64 = 0;
+ let mut info_process = TransitProcess {
+ copied_bytes: 0,
+ total_bytes: dir_content.dir_size,
+ file_bytes_copied: 0,
+ file_total_bytes: 0,
+ file_name: String::new(),
+ state: TransitState::Normal,
+ };
+
+ let mut options = options.clone();
+ for file in dir_content.files {
+ let mut to = to.to_path_buf();
+ let tp = Path::new(&file).strip_prefix(from)?;
+ let path = to.join(&tp);
+
+ let file_name = path.file_name();
+ if file_name.is_none() {
+ err!("No file name");
+ }
+ let file_name = file_name.unwrap();
+ to.push(file_name);
+
+ let mut file_options = super::file::CopyOptions {
+ overwrite: options.overwrite,
+ skip_exist: options.skip_exist,
+ buffer_size: options.buffer_size,
+ };
+
+ if let Some(file_name) = file_name.to_str() {
+ info_process.file_name = file_name.to_string();
+ } else {
+ err!("Invalid file name", ErrorKind::InvalidFileName);
+ }
+
+ info_process.file_bytes_copied = 0;
+ info_process.file_total_bytes = Path::new(&file).metadata()?.len();
+
+ let mut result_copy: Result<u64>;
+ let mut work = true;
+ let copied_bytes = result;
+ while work {
+ {
+ let _progress_handler = |info: super::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 = super::file::move_file_with_progress(
+ &file,
+ &path,
+ &file_options,
+ _progress_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 = TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ TransitProcessResult::Overwrite => {
+ file_options.overwrite = true;
+ }
+ TransitProcessResult::OverwriteAll => {
+ file_options.overwrite = true;
+ options.overwrite = true;
+ }
+ TransitProcessResult::Skip => {
+ is_remove = false;
+ file_options.skip_exist = true;
+ }
+ TransitProcessResult::SkipAll => {
+ is_remove = false;
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ TransitProcessResult::Retry => {}
+ TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ 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 = TransitState::Exists;
+ let user_decide = progress_handler(info_process);
+ match user_decide {
+ TransitProcessResult::Overwrite => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ TransitProcessResult::OverwriteAll => {
+ err!("Overwrite denied for this situation!", ErrorKind::Other);
+ }
+ TransitProcessResult::Skip => {
+ is_remove = false;
+ file_options.skip_exist = true;
+ }
+ TransitProcessResult::SkipAll => {
+ file_options.skip_exist = true;
+ options.skip_exist = true;
+ }
+ TransitProcessResult::Retry => {}
+ TransitProcessResult::ContinueOrAbort => {
+ let err_msg = err.to_string();
+ err!(err_msg.as_str(), err.kind)
+ }
+ 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)
+ }
+ },
+ }
+ }
+ }
+ if is_remove {
+ remove(from)?;
+ }
+
+ Ok(result)
+}
+
+/// Removes directory.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::remove;
+///
+/// remove("source/dir1"); // remove dir1
+/// ```
+pub fn remove<P: AsRef<Path>>(path: P) -> Result<()> {
+ if path.as_ref().exists() {
+ Ok(remove_dir_all(path)?)
+ } else {
+ Ok(())
+ }
+}
diff --git a/vendor/fs_extra/src/error.rs b/vendor/fs_extra/src/error.rs
new file mode 100644
index 000000000..f26613e90
--- /dev/null
+++ b/vendor/fs_extra/src/error.rs
@@ -0,0 +1,158 @@
+use std::error::Error as StdError;
+use std::ffi::OsString;
+use std::fmt;
+use std::io::Error as IoError;
+use std::io::ErrorKind as IoErrorKind;
+use std::path::StripPrefixError;
+
+/// A list specifying general categories of fs_extra error.
+#[derive(Debug)]
+pub enum ErrorKind {
+ /// An entity was not found.
+ NotFound,
+ /// The operation lacked the necessary privileges to complete.
+ PermissionDenied,
+ /// An entity already exists.
+ AlreadyExists,
+ /// This operation was interrupted.
+ Interrupted,
+ /// Path does not a directory.
+ InvalidFolder,
+ /// Path does not a file.
+ InvalidFile,
+ /// Invalid file name.
+ InvalidFileName,
+ /// Invalid path.
+ InvalidPath,
+ /// Any I/O error.
+ Io(IoError),
+ /// Any StripPrefix error.
+ StripPrefix(StripPrefixError),
+ /// Any OsString error.
+ OsString(OsString),
+ /// Any fs_extra error not part of this list.
+ Other,
+}
+
+impl ErrorKind {
+ fn as_str(&self) -> &str {
+ match *self {
+ ErrorKind::NotFound => "entity not found",
+ ErrorKind::PermissionDenied => "permission denied",
+ ErrorKind::AlreadyExists => "entity already exists",
+ ErrorKind::Interrupted => "operation interrupted",
+ ErrorKind::Other => "other os error",
+ ErrorKind::InvalidFolder => "invalid folder error",
+ ErrorKind::InvalidFile => "invalid file error",
+ ErrorKind::InvalidFileName => "invalid file name error",
+ ErrorKind::InvalidPath => "invalid path error",
+ ErrorKind::Io(_) => "Io error",
+ ErrorKind::StripPrefix(_) => "Strip prefix error",
+ ErrorKind::OsString(_) => "OsString error",
+ }
+ }
+}
+
+/// A specialized Result type for fs_extra operations.
+///
+/// This typedef is generally used to avoid writing out fs_extra::Error directly
+/// and is otherwise a direct mapping to Result.
+///
+///#Examples
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::dir::create;
+///
+///fn get_string() -> io::Result<()> {
+///
+/// create("test_dir")?;
+///
+/// Ok(())
+/// }
+/// ```
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+/// The error type for fs_extra operations with files and folder.
+///
+/// Errors mostly originate from the underlying OS, but custom instances of
+/// `Error` can be created with crafted error messages and a particular value of
+/// [`ErrorKind`].
+///
+/// [`ErrorKind`]: enum.ErrorKind.html
+#[derive(Debug)]
+pub struct Error {
+ /// Type error
+ pub kind: ErrorKind,
+ message: String,
+}
+
+impl Error {
+ /// Create a new fs_extra error from a kind of error error as well as an arbitrary error payload.
+ ///
+ ///#Examples
+ /// ```rust,ignore
+ ///
+ /// extern crate fs_extra;
+ /// use fs_extra::error::{Error, ErrorKind};
+ ///
+ /// errors can be created from strings
+ /// let custom_error = Error::new(ErrorKind::Other, "Other Error!");
+ /// // errors can also be created from other errors
+ /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
+ ///
+ /// ```
+ pub fn new(kind: ErrorKind, message: &str) -> Error {
+ Error {
+ kind,
+ message: message.to_string(),
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.message)
+ }
+}
+
+impl StdError for Error {
+ fn description(&self) -> &str {
+ self.kind.as_str()
+ }
+}
+impl From<StripPrefixError> for Error {
+ fn from(err: StripPrefixError) -> Error {
+ Error::new(
+ ErrorKind::StripPrefix(err),
+ "StripPrefixError. Look inside for more details",
+ )
+ }
+}
+
+impl From<OsString> for Error {
+ fn from(err: OsString) -> Error {
+ Error::new(
+ ErrorKind::OsString(err),
+ "OsString. Look inside for more details",
+ )
+ }
+}
+
+impl From<IoError> for Error {
+ fn from(err: IoError) -> Error {
+ let err_kind: ErrorKind;
+ match err.kind() {
+ IoErrorKind::NotFound => err_kind = ErrorKind::NotFound,
+ IoErrorKind::PermissionDenied => err_kind = ErrorKind::PermissionDenied,
+ IoErrorKind::AlreadyExists => err_kind = ErrorKind::AlreadyExists,
+ IoErrorKind::Interrupted => err_kind = ErrorKind::Interrupted,
+ IoErrorKind::Other => err_kind = ErrorKind::Other,
+ _ => {
+ err_kind = ErrorKind::Io(err);
+ return Error::new(err_kind, "Io error. Look inside err_kind for more details.");
+ }
+ }
+ Error::new(err_kind, &err.to_string())
+ }
+}
diff --git a/vendor/fs_extra/src/file.rs b/vendor/fs_extra/src/file.rs
new file mode 100644
index 000000000..2b62576bc
--- /dev/null
+++ b/vendor/fs_extra/src/file.rs
@@ -0,0 +1,413 @@
+use crate::error::{Error, ErrorKind, Result};
+use std;
+use std::fs::{remove_file, File};
+use std::io::{Read, Write};
+use std::path::Path;
+
+// Options and flags which can be used to configure how a file will be copied or moved.
+pub struct CopyOptions {
+ /// Sets the option true for overwrite existing files.
+ pub overwrite: bool,
+ /// Sets the option true for skip existing files.
+ pub skip_exist: bool,
+ /// Sets buffer size for copy/move work only with receipt information about process work.
+ pub buffer_size: usize,
+}
+
+impl CopyOptions {
+ /// Initialize struct CopyOptions with default value.
+ ///
+ /// ```rust,ignore
+ ///
+ /// overwrite: false
+ ///
+ /// skip_exist: false
+ ///
+ /// buffer_size: 64000 //64kb
+ /// ```
+ pub fn new() -> CopyOptions {
+ CopyOptions {
+ overwrite: false,
+ skip_exist: false,
+ buffer_size: 64000, //64kb
+ }
+ }
+
+ /// Sets the option true for overwrite existing files.
+ pub fn overwrite(mut self, overwrite: bool) -> Self {
+ self.overwrite = overwrite;
+ self
+ }
+
+ /// Sets the option true for skip existing files.
+ pub fn skip_exist(mut self, skip_exist: bool) -> Self {
+ self.skip_exist = skip_exist;
+ self
+ }
+
+ /// Sets buffer size for copy/move work only with receipt information about process work.
+ pub fn buffer_size(mut self, buffer_size: usize) -> Self {
+ self.buffer_size = buffer_size;
+ self
+ }
+}
+
+impl Default for CopyOptions {
+ fn default() -> Self {
+ CopyOptions::new()
+ }
+}
+
+/// A structure which stores information about the current status of a file that's copied or moved. .
+pub struct TransitProcess {
+ /// Copied bytes on this time.
+ pub copied_bytes: u64,
+ /// All the bytes which should to copy or move.
+ pub total_bytes: u64,
+}
+
+/// Copies the contents of one file to another. This function will also copy the permission
+/// bits of the original file to the destination file.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `from` path is not a file.
+/// * This `from` file does not exist.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::copy;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// copy("dir1/foo.txt", "dir2/bar.txt", &options)?; // Copy dir1/foo.txt to dir2/bar.txt
+///
+/// ```
+pub fn copy<P, Q>(from: P, to: Q, options: &CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let from = from.as_ref();
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist or you don't have access!", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+
+ if !from.is_file() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" is not a file!", msg);
+ err!(&msg, ErrorKind::InvalidFile);
+ }
+ err!("Path is not a file!", ErrorKind::InvalidFile);
+ }
+
+ if !options.overwrite && to.as_ref().exists() {
+ if options.skip_exist {
+ return Ok(0);
+ }
+
+ if let Some(msg) = to.as_ref().to_str() {
+ let msg = format!("Path \"{}\" exists", msg);
+ err!(&msg, ErrorKind::AlreadyExists);
+ }
+ }
+
+ Ok(std::fs::copy(from, to)?)
+}
+
+/// Copies the contents of one file to another file with information about progress.
+/// This function will also copy the permission bits of the original file to the
+/// destination file.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `from` path is not a file.
+/// * This `from` file does not exist.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::copy_with_progress;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| println!("{}", process_info.total_bytes);
+///
+/// // Copy dir1/foo.txt to dir2/foo.txt
+/// copy_with_progress("dir1/foo.txt", "dir2/foo.txt", &options, handle)?;
+///
+/// ```
+pub fn copy_with_progress<P, Q, F>(
+ from: P,
+ to: Q,
+ options: &CopyOptions,
+ mut progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess),
+{
+ let from = from.as_ref();
+ if !from.exists() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" does not exist or you don't have access!", msg);
+ err!(&msg, ErrorKind::NotFound);
+ }
+ err!(
+ "Path does not exist or you don't have access!",
+ ErrorKind::NotFound
+ );
+ }
+
+ if !from.is_file() {
+ if let Some(msg) = from.to_str() {
+ let msg = format!("Path \"{}\" is not a file!", msg);
+ err!(&msg, ErrorKind::InvalidFile);
+ }
+ err!("Path is not a file!", ErrorKind::InvalidFile);
+ }
+
+ if !options.overwrite && to.as_ref().exists() {
+ if options.skip_exist {
+ return Ok(0);
+ }
+
+ if let Some(msg) = to.as_ref().to_str() {
+ let msg = format!("Path \"{}\" exists", msg);
+ err!(&msg, ErrorKind::AlreadyExists);
+ }
+ }
+ let mut file_from = File::open(from)?;
+ let mut buf = vec![0; options.buffer_size];
+ let file_size = file_from.metadata()?.len();
+ let mut copied_bytes: u64 = 0;
+
+ let mut file_to = File::create(to)?;
+ while !buf.is_empty() {
+ match file_from.read(&mut buf) {
+ Ok(0) => break,
+ Ok(n) => {
+ let written_bytes = file_to.write(&buf[..n])?;
+ if written_bytes != n {
+ err!("Couldn't write the whole buffer to file", ErrorKind::Other);
+ }
+ copied_bytes += n as u64;
+ let data = TransitProcess {
+ copied_bytes,
+ total_bytes: file_size,
+ };
+ progress_handler(data);
+ }
+ Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {}
+ Err(e) => return Err(::std::convert::From::from(e)),
+ }
+ }
+ Ok(file_size)
+}
+
+/// Moves a file from one place to another. This function will also copy the permission
+/// bits of the original file to the destination file.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `from` path is not a file.
+/// * This `from` file does not exist.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::move_file;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// move_file("dir1/foo.txt", "dir2/foo.txt", &options)?; // Move dir1/foo.txt to dir2/foo.txt
+///
+/// ```
+pub fn move_file<P, Q>(from: P, to: Q, options: &CopyOptions) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let mut is_remove = true;
+ if options.skip_exist && to.as_ref().exists() && !options.overwrite {
+ is_remove = false;
+ }
+ let result = copy(&from, to, options)?;
+ if is_remove {
+ remove(from)?;
+ }
+
+ Ok(result)
+}
+
+/// Moves a file from one place to another with information about progress.
+/// This function will also copy the permission bits of the original file to the
+/// destination file.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `from` path is not a file.
+/// * This `from` file does not exist.
+/// * The current process does not have the permission to access `from` or write `to`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::move_file;
+///
+/// let options = CopyOptions::new(); //Initialize default values for CopyOptions
+/// let handle = |process_info: TransitProcess| println!("{}", process_info.total_bytes);
+///
+/// // Move dir1/foo.txt to dir2/foo.txt
+/// move_file("dir1/foo.txt", "dir2/foo.txt", &options, handle)?;
+///
+/// ```
+pub fn move_file_with_progress<P, Q, F>(
+ from: P,
+ to: Q,
+ options: &CopyOptions,
+ progress_handler: F,
+) -> Result<u64>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+ F: FnMut(TransitProcess),
+{
+ let mut is_remove = true;
+ if options.skip_exist && to.as_ref().exists() && !options.overwrite {
+ is_remove = false;
+ }
+ let result = copy_with_progress(&from, to, options, progress_handler)?;
+ if is_remove {
+ remove(from)?;
+ }
+
+ Ok(result)
+}
+
+/// Removes a file from the filesystem.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * The current process does not have the permission to access `path`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::remove;
+///
+/// remove("foo.txt" )?; // Remove foo.txt
+///
+/// ```
+pub fn remove<P>(path: P) -> Result<()>
+where
+ P: AsRef<Path>,
+{
+ if path.as_ref().exists() {
+ Ok(remove_file(path)?)
+ } else {
+ Ok(())
+ }
+}
+
+/// Read file contents, placing them into `String`.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` is not a file.
+/// * This `path` file does not exist.
+/// * The current process does not have the permission to access `path`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::read_to_string;
+///
+/// let file_content = read_to_string("foo.txt" )?; // Get file content from foo.txt
+/// println!("{}", file_content);
+///
+/// ```
+pub fn read_to_string<P>(path: P) -> Result<String>
+where
+ P: AsRef<Path>,
+{
+ let path = path.as_ref();
+ if path.exists() && !path.is_file() {
+ if let Some(msg) = path.to_str() {
+ let msg = format!("Path \"{}\" is not a file!", msg);
+ err!(&msg, ErrorKind::InvalidFile);
+ }
+ err!("Path is not a file!", ErrorKind::InvalidFile);
+ }
+
+ let mut file = File::open(path)?;
+ let mut result = String::new();
+ file.read_to_string(&mut result)?;
+
+ Ok(result)
+}
+
+/// Write `String` content into file.
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not limited to just
+/// these cases:
+///
+/// * This `path` is not a file.
+/// * This `path` file does not exist.
+/// * The current process does not have the permission to access `path`.
+///
+/// # Example
+/// ```rust,ignore
+/// extern crate fs_extra;
+/// use fs_extra::file::read_to_string;
+///
+/// write_all("foo.txt", "contents" )?; // Create file foo.txt and send content inside
+///
+/// ```
+pub fn write_all<P>(path: P, content: &str) -> Result<()>
+where
+ P: AsRef<Path>,
+{
+ let path = path.as_ref();
+ if path.exists() && !path.is_file() {
+ if let Some(msg) = path.to_str() {
+ let msg = format!("Path \"{}\" is not a file!", msg);
+ err!(&msg, ErrorKind::InvalidFile);
+ }
+ err!("Path is not a file!", ErrorKind::InvalidFile);
+ }
+
+ let mut f = File::create(path)?;
+
+ Ok(f.write_all(content.as_bytes())?)
+}
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(())
+}
diff --git a/vendor/fs_extra/tests/dir.rs b/vendor/fs_extra/tests/dir.rs
new file mode 100644
index 000000000..264706657
--- /dev/null
+++ b/vendor/fs_extra/tests/dir.rs
@@ -0,0 +1,4824 @@
+use std::collections::HashSet;
+use std::fs::{self, read_dir};
+use std::path::{Path, PathBuf};
+use std::sync::mpsc::{self, TryRecvError};
+use std::thread;
+
+extern crate fs_extra;
+use fs_extra::dir::*;
+use fs_extra::error::*;
+
+fn files_eq<P, Q>(file1: P, file2: Q) -> bool
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let content1 = fs_extra::file::read_to_string(file1).unwrap();
+ let content2 = fs_extra::file::read_to_string(file2).unwrap();
+ content1 == content2
+}
+
+fn compare_dir<P, Q>(path_from: P, path_to: Q) -> bool
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let mut path_to = path_to.as_ref().to_path_buf();
+ match path_from.as_ref().components().last() {
+ None => panic!("Invalid folder from"),
+ Some(dir_name) => {
+ path_to.push(dir_name.as_os_str());
+ if !path_to.exists() {
+ return false;
+ }
+ }
+ }
+
+ for entry in read_dir(&path_from).unwrap() {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ if path.is_dir() {
+ if !compare_dir(path, &path_to) {
+ return false;
+ }
+ } else {
+ let mut path_to = path_to.to_path_buf();
+ match path.file_name() {
+ None => panic!("No file name"),
+ Some(file_name) => {
+ path_to.push(file_name);
+ if !path_to.exists() {
+ return false;
+ } else if !files_eq(&path, path_to.clone()) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ true
+}
+
+// Returns the size of a directory. On Linux with ext4 this can be about 4kB.
+// Since the directory size can vary, we need to calculate is dynamically.
+fn get_dir_size() -> u64 {
+ std::fs::create_dir_all("./tests/temp").expect("Couldn't create test folder");
+
+ std::fs::metadata("./tests/temp")
+ .expect("Couldn't receive metadata of tests/temp folder")
+ .len()
+}
+
+#[cfg(unix)]
+fn create_file_symlink<P: AsRef<Path>, Q: AsRef<Path>>(
+ original: P,
+ link: Q,
+) -> std::io::Result<()> {
+ std::os::unix::fs::symlink(original.as_ref(), link.as_ref())
+}
+
+#[cfg(windows)]
+fn create_file_symlink<P: AsRef<Path>, Q: AsRef<Path>>(
+ original: P,
+ link: Q,
+) -> std::io::Result<()> {
+ std::os::windows::fs::symlink_file(original.as_ref(), link.as_ref())
+}
+
+const TEST_FOLDER: &'static str = "./tests/temp/dir";
+
+#[test]
+fn it_create_all_work() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_all_work");
+ test_dir.push("sub_dir");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ assert!(!test_dir.exists());
+ create_all(&test_dir, false).unwrap();
+ assert!(test_dir.exists());
+}
+
+#[test]
+fn it_create_work() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_work");
+ if !test_dir.exists() {
+ create_all(&test_dir, false).unwrap();
+ }
+ assert!(test_dir.exists());
+ test_dir.push("sub_dir");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ create(&test_dir, false).unwrap();
+ assert!(test_dir.exists());
+}
+
+#[test]
+fn it_create_exist_folder() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_exist_folder");
+ test_dir.push("sub");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ assert!(!test_dir.exists());
+ create_all(&test_dir, false).unwrap();
+ assert!(test_dir.exists());
+ let mut file_path = test_dir.clone();
+ file_path.push("test.txt");
+ assert!(!file_path.exists());
+ let content = "test_content";
+ fs_extra::file::write_all(&file_path, &content).unwrap();
+ assert!(file_path.exists());
+
+ match create(&test_dir, false) {
+ Ok(_) => panic!("Should be error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ assert!(test_dir.exists());
+ assert!(file_path.exists());
+ let new_content = fs_extra::file::read_to_string(file_path).unwrap();
+ assert_eq!(new_content, content);
+ }
+ _ => panic!("Wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_create_erase_exist_folder() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_erase_exist_folder");
+ test_dir.push("sub");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ assert!(!test_dir.exists());
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ let mut file_path = test_dir.clone();
+ file_path.push("test.txt");
+ assert!(!file_path.exists());
+ fs_extra::file::write_all(&file_path, "test_content").unwrap();
+ assert!(file_path.exists());
+
+ create(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ assert!(!file_path.exists());
+}
+
+#[test]
+fn it_create_all_exist_folder() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_all_exist_folder");
+ test_dir.push("sub");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ assert!(!test_dir.exists());
+ create_all(&test_dir, false).unwrap();
+ assert!(test_dir.exists());
+ let mut file_path = test_dir.clone();
+ file_path.push("test.txt");
+ assert!(!file_path.exists());
+ let content = "test_content";
+ fs_extra::file::write_all(&file_path, &content).unwrap();
+ assert!(file_path.exists());
+
+ create_all(&test_dir, false).unwrap();
+ assert!(test_dir.exists());
+ assert!(file_path.exists());
+ let new_content = fs_extra::file::read_to_string(file_path).unwrap();
+ assert_eq!(new_content, content);
+}
+
+#[test]
+fn it_create_all_erase_exist_folder() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_create_all_erase_exist_folder");
+ test_dir.push("sub");
+ if test_dir.exists() {
+ remove(&test_dir).unwrap();
+ }
+ assert!(!test_dir.exists());
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ let mut file_path = test_dir.clone();
+ file_path.push("test.txt");
+ assert!(!file_path.exists());
+ fs_extra::file::write_all(&file_path, "test_content").unwrap();
+ assert!(file_path.exists());
+
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ assert!(!file_path.exists());
+}
+
+#[test]
+fn it_remove_work() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_remove_work");
+ test_dir.push("sub");
+ test_dir.push("second_sub");
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ test_dir.pop();
+ test_dir.pop();
+ remove(&test_dir).unwrap();
+ assert!(!test_dir.exists());
+}
+
+#[test]
+fn it_remove_not_exist() {
+ let mut test_dir = PathBuf::from(TEST_FOLDER);
+ test_dir.push("it_remove_not_exist");
+ test_dir.push("sub");
+ assert!(!test_dir.exists());
+ match remove(&test_dir) {
+ Ok(_) => {
+ assert!(!test_dir.exists());
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_copy_work() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_work");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let options = CopyOptions::new();
+ let result = copy(&path_from, &path_to, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(path_from.exists());
+ assert!(compare_dir(&path_from, &path_to));
+}
+
+#[test]
+fn it_copy_not_folder() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_copy_not_folder");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ path_from.push("test.txt");
+ fs_extra::file::write_all(&path_from, "test").unwrap();
+
+ match copy(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFolder => {
+ let wrong_path = format!(
+ "Path \"{}\" is not a directory!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_source_not_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_copy_source_not_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ assert!(!path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ match copy(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't have \
+ access!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_exist_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_exist_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.overwrite = true;
+ copy(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert!(files_eq(file1_path, exist_path));
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+}
+
+#[test]
+fn it_copy_exist_not_overwrite() {
+ let test_name = "sub";
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_copy_exist_not_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let options = CopyOptions::new();
+ match copy(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ let wrong_path = format!("Path \"{}\" exists", exist_path.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_exist_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_exist_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.skip_exist = true;
+ copy(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert!(!files_eq(file1_path, &exist_path));
+ assert_eq!(
+ fs_extra::file::read_to_string(exist_path).unwrap(),
+ exist_content
+ );
+
+ assert!(path_to.exists());
+ assert!(!compare_dir(&path_from, &path_to));
+}
+
+#[test]
+fn it_copy_exist_overwrite_and_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_exist_overwrite_and_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ copy(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert!(files_eq(file1_path, exist_path));
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+}
+
+#[test]
+fn it_copy_using_first_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_first_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&d_level_4.0, true).unwrap();
+ create_all(&d_level_5.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.depth = 1;
+ let result = copy(&d_level_1.0, path_to, &options).unwrap();
+
+ assert_eq!(8, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+}
+
+#[test]
+fn it_copy_using_four_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_four_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&d_level_4.0, true).unwrap();
+ create_all(&d_level_5.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.depth = 4;
+ let result = copy(&d_level_1.0, path_to, &options).unwrap();
+
+ assert_eq!(32, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+ assert!(d_level_4.1.exists());
+ assert!(d_level_5.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ assert!(files_eq(&file3.0, &file3.1));
+ assert!(files_eq(&file4.0, &file4.1));
+}
+#[test]
+fn it_copy_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_content_only_option");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.clone());
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.content_only = true;
+ let result = copy(&d_level_1.0, path_to, &options).unwrap();
+
+ assert_eq!(24, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ assert!(files_eq(&file3.0, &file3.1));
+}
+
+#[test]
+fn it_copy_progress_work() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_progress_work");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(15, result);
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "test2.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else if process_info.file_name == "test1.txt" {
+ assert_eq!(7, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_not_folder() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_copy_with_progress_not_folder");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ path_from.push("test.txt");
+ fs_extra::file::write_all(&path_from, "test").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ match process_info.state {
+ TransitState::NoAccess => {}
+ _ => panic!("Error not should be!"),
+ };
+ TransitProcessResult::ContinueOrAbort
+ };
+ match copy_with_progress(&path_from, &path_to, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFolder => {
+ let wrong_path = format!(
+ "Path \"{}\" is not a directory!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_with_progress_work_dif_buf_size() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_with_progress_work_dif_buf_size");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+
+ let mut options = CopyOptions::new();
+ options.buffer_size = 2;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+ })
+ .join();
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(i * 2, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2 + 8, process_info.copied_bytes);
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ })
+ .join();
+
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i + 8, process_info.copied_bytes);
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+#[test]
+fn it_copy_with_progress_source_not_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_copy_with_progress_source_not_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ assert!(!path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ match copy_with_progress(&path_from, &path_to, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't \
+ have access!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+ })
+ .join();
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => {}
+ _ => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_with_progress_exist_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+
+ options.buffer_size = 1;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(23, result);
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_not_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_with_progress_exist_not_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+
+ options.buffer_size = 1;
+ let func_test = |process_info: TransitProcess| {
+ match process_info.state {
+ TransitState::Exists => {}
+ _ => panic!("Error not should be!"),
+ };
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test);
+ match result {
+ Ok(_) => panic!("Should be error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!("Wrong wrror"),
+ },
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_with_progress_exist_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+ options.buffer_size = 1;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(0, result);
+ assert!(path_to.exists());
+ assert!(!compare_dir(&path_from, &path_to));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => {}
+ _ => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite_and_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_copy_with_progress_exist_overwrite_and_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+
+ options.buffer_size = 1;
+ options.overwrite = true;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(23, result);
+ assert!(path_to.exists());
+ assert!(compare_dir(&path_from, &path_to));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_using_first_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_first_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&d_level_4.0, true).unwrap();
+ create_all(&d_level_5.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.depth = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(8, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_using_four_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_four_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&d_level_4.0, true).unwrap();
+ create_all(&d_level_5.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.depth = 4;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(32, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+ assert!(d_level_4.1.exists());
+ assert!(d_level_5.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ assert!(files_eq(&file3.0, &file3.1));
+ assert!(files_eq(&file4.0, &file4.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+#[test]
+fn it_copy_with_progress_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_content_only_option");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.clone());
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.content_only = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(24, result);
+
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ assert!(files_eq(&file3.0, &file3.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_inside_work_target_dir_not_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_copy_inside_work_target_dir_not_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+
+ if root_dir2.exists() {
+ remove(&root_dir2).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(!root_dir2.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ let result = copy(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(compare_dir_recursively(&root_dir1, &root_dir2));
+}
+
+#[test]
+fn it_copy_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root =
+ path_root.join("it_copy_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ fs_extra::file::write_all(&file3, "content3").unwrap();
+
+ if root_dir2_dir1.exists() {
+ remove(&root_dir2_dir1).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(!root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ let result = copy(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(compare_dir(&root_dir1, &root_dir2));
+}
+
+#[test]
+fn it_copy_inside_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_copy_inside_work_target_dir_exist_with_source_dir_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ fs_extra::file::write_all(&file3, "content3").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content2").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ match copy(&root_dir1, &root_dir2, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ assert_eq!(1, 1);
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+ options.overwrite = true;
+
+ let result = copy(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(compare_dir(&root_dir1, &root_dir2));
+}
+
+// The compare_dir method assumes that the folder `path_to` must have a sub folder named the last component of the `path_from`.
+// In order to compare two folders with different name but share the same structure, rewrite a new compare method to do that!
+fn compare_dir_recursively<P, Q>(path_from: P, path_to: Q) -> bool
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let path_to = path_to.as_ref().to_path_buf();
+
+ for entry in read_dir(&path_from).unwrap() {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ if path.is_dir() {
+ match path.components().last() {
+ None => panic!("Invalid folder from"),
+ Some(dir_name) => {
+ let mut target_dir = path_to.to_path_buf();
+ target_dir.push(dir_name.as_os_str());
+ if !compare_dir_recursively(path.clone(), &target_dir) {
+ return false;
+ }
+ }
+ }
+ } else {
+ let mut target_file = path_to.to_path_buf();
+ match path.file_name() {
+ None => panic!("No file name"),
+ Some(file_name) => {
+ target_file.push(file_name);
+ if !target_file.exists() {
+ return false;
+ } else if !files_eq(&path, target_file.clone()) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ true
+}
+
+#[test]
+fn it_move_work() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_work");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let options = CopyOptions::new();
+ let result = move_dir(&path_from, &path_to, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+}
+
+#[test]
+fn it_move_not_folder() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_move_not_folder");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ path_from.push("test.txt");
+ fs_extra::file::write_all(&path_from, "test").unwrap();
+
+ match move_dir(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFolder => {
+ let wrong_path = format!(
+ "Path \"{}\" is not a directory or you don't have \
+ access!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_source_not_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_move_source_not_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ assert!(!path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ match move_dir(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!("Path \"{}\" does not exist", path_from.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_exist_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_exist_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.overwrite = true;
+ move_dir(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+}
+
+#[test]
+fn it_move_exist_not_overwrite() {
+ let test_name = "sub";
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_move_exist_not_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let options = CopyOptions::new();
+ match move_dir(&path_from, &path_to, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ let wrong_path = format!("Path \"{}\" exists", exist_path.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_exist_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_exist_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.skip_exist = true;
+ move_dir(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert_eq!(
+ fs_extra::file::read_to_string(exist_path).unwrap(),
+ exist_content
+ );
+
+ assert!(path_to.exists());
+}
+
+#[test]
+fn it_move_exist_overwrite_and_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_exist_overwrite_and_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+ let same_file = "test.txt";
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push(same_file);
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut exist_path = path_to.clone();
+ exist_path.push(&test_name);
+ create(&exist_path, true).unwrap();
+ assert!(exist_path.exists());
+ exist_path.push(same_file);
+ let exist_content = "exist content";
+ assert_ne!(exist_content, content1);
+ fs_extra::file::write_all(&exist_path, exist_content).unwrap();
+ assert!(exist_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ move_dir(&path_from, &path_to, &options).unwrap();
+
+ assert!(exist_path.exists());
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+}
+
+#[test]
+fn it_move_inside_work_target_dir_not_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_move_inside_work_target_dir_not_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+
+ if root_dir2.exists() {
+ remove(&root_dir2).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(!root_dir2.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ let result = move_dir(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!root_dir1.exists());
+ let root_dir2_sub = root_dir2.join("sub");
+ let root_dir2_file1 = root_dir2.join("file1.txt");
+ let root_dir2_sub_file2 = root_dir2_sub.join("file2.txt");
+ assert!(root_dir2.exists());
+ assert!(root_dir2_sub.exists());
+ assert!(root_dir2_file1.exists());
+ assert!(root_dir2_sub_file2.exists());
+}
+
+#[test]
+fn it_move_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root =
+ path_root.join("it_move_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ fs_extra::file::write_all(&file3, "content3").unwrap();
+
+ if root_dir2_dir1.exists() {
+ remove(&root_dir2_dir1).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(!root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ let result = move_dir(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!root_dir1.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt");
+ let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt");
+ assert!(root_dir2_dir1_file1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir1_sub_file2.exists());
+ assert!(root_dir2_dir3_file3.exists());
+}
+
+#[test]
+fn it_move_inside_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_move_inside_work_target_dir_exist_with_source_dir_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ fs_extra::file::write_all(&file3, "content3").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content2").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ match copy(&root_dir1, &root_dir2, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {
+ assert_eq!(1, 1);
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+ options.overwrite = true;
+ let result = move_dir(&root_dir1, &root_dir2, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!root_dir1.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt");
+ let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt");
+ let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt");
+ assert!(root_dir2_dir1_file1.exists());
+ assert!(root_dir2_dir1_sub_file2.exists());
+ assert!(root_dir2_dir3_file3.exists());
+}
+#[test]
+fn it_move_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_content_only_option");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.clone());
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.content_only = true;
+ let result = move_dir(&d_level_1.0, path_to, &options).unwrap();
+
+ assert_eq!(24, result);
+
+ assert!(!d_level_1.0.exists());
+ assert!(!d_level_2.0.exists());
+ assert!(!d_level_3.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+}
+#[test]
+fn it_move_progress_work() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_progress_work");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(15, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "test2.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else if process_info.file_name == "test1.txt" {
+ assert_eq!(7, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_with_progress_not_folder() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_move_with_progress_not_folder");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ path_from.push("test.txt");
+ fs_extra::file::write_all(&path_from, "test").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ match process_info.state {
+ TransitState::NoAccess => {}
+ _ => panic!("Error not should be!"),
+ };
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ match move_dir_with_progress(&path_from, &path_to, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFolder => {
+ let wrong_path = format!(
+ "Path \"{}\" is not a directory!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_with_progress_work_dif_buf_size() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_with_progress_work_dif_buf_size");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content1";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ options.buffer_size = 2;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(16, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+ })
+ .join();
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(i * 2, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2 + 8, process_info.copied_bytes);
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ })
+ .join();
+
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i + 8, process_info.copied_bytes);
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 16, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+#[test]
+fn it_move_with_progress_source_not_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ path_from.push("it_move_with_progress_source_not_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push("sub");
+
+ assert!(!path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let options = CopyOptions::new();
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ match move_dir_with_progress(&path_from, &path_to, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't \
+ have access!",
+ path_from.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+ })
+ .join();
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => {}
+ _ => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_with_progress_exist_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+
+ options.buffer_size = 1;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(23, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_not_overwrite() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_with_progress_exist_not_overwrite");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test);
+ match result {
+ Ok(_) => panic!("Should be error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!("Wrong wrror"),
+ },
+ }
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => {
+ panic!("Error not should be!");
+ }
+ _ => {}
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_with_progress_exist_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+ options.buffer_size = 1;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(0, result);
+ assert!(path_from.exists());
+ assert!(path_to.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => {}
+ _ => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite_and_skip_exist() {
+ let mut path_from = PathBuf::from(TEST_FOLDER);
+ let test_name = "sub";
+ path_from.push("it_move_with_progress_exist_overwrite_and_skip_exist");
+ let mut path_to = path_from.clone();
+ path_to.push("out");
+ path_from.push(&test_name);
+
+ create_all(&path_from, true).unwrap();
+ assert!(path_from.exists());
+ create_all(&path_to, true).unwrap();
+ assert!(path_to.exists());
+
+ let mut file1_path = path_from.clone();
+ file1_path.push("test1.txt");
+ let content1 = "content";
+ fs_extra::file::write_all(&file1_path, &content1).unwrap();
+ assert!(file1_path.exists());
+
+ let mut sub_dir_path = path_from.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2_path = sub_dir_path.clone();
+ file2_path.push("test2.txt");
+ let content2 = "content2";
+ fs_extra::file::write_all(&file2_path, &content2).unwrap();
+ assert!(file2_path.exists());
+
+ let mut options = CopyOptions::new();
+ copy(&path_from, &path_to, &options).unwrap();
+ fs_extra::file::write_all(&file2_path, "another conntent").unwrap();
+
+ options.buffer_size = 1;
+ options.overwrite = true;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&path_from, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(23, result);
+ assert!(path_to.exists());
+ assert!(!path_from.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.recv().unwrap();
+}
+
+#[test]
+fn it_get_folder_size() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_folder_size");
+ path.push("dir");
+
+ create_all(&path, true).unwrap();
+ assert!(path.exists());
+
+ let mut file1 = path.clone();
+ file1.push("test1.txt");
+ fs_extra::file::write_all(&file1, &"A".repeat(100)).unwrap();
+ assert!(file1.exists());
+
+ let mut sub_dir_path = path.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+
+ let mut file2 = sub_dir_path.clone();
+ file2.push("test2.txt");
+ fs_extra::file::write_all(&file2, &"B".repeat(300)).unwrap();
+ assert!(file2.exists());
+
+ let symlink_file = sub_dir_path.join("symlink_file.txt");
+
+ // Rust stdlib APIs for creating a symlinked file only exist for Unix and Windows.
+ #[cfg(any(unix, windows))]
+ {
+ // Only passing the filename since we want this to be a relative symlink.
+ create_file_symlink("test2.txt", &symlink_file).unwrap();
+ assert!(symlink_file.exists());
+ }
+
+ // Total size comprises of:
+ // - 100 bytes for the standard file "test1.txt"
+ // - 300 bytes for the standard file "test2.txt"
+ // - (On supported platforms) 1 x symlink whose whose size varies by filesystem, so is dynamically calculated.
+ let mut expected_size = 100 + 300;
+
+ if symlink_file.exists() {
+ // `fs::symlink_metadata` does not follow symlinks, so this is the size of the symlink itself, not its target.
+ expected_size += fs::symlink_metadata(&symlink_file).unwrap().len();
+ }
+
+ let result = get_size(&path).unwrap();
+
+ assert_eq!(expected_size, result);
+}
+
+#[test]
+fn it_get_file_size() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_file_size");
+
+ create_all(&path, true).unwrap();
+ assert!(path.exists());
+
+ let mut file = path.clone();
+ file.push("test1.txt");
+ fs_extra::file::write_all(&file, "content").unwrap();
+ assert!(file.exists());
+
+ let result = get_size(&path).unwrap();
+
+ assert_eq!(7, result);
+}
+
+#[test]
+fn it_get_size_not_found() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_size_not_found");
+
+ assert!(!path.exists());
+
+ match get_size(&path) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => panic!("Wrong error!"),
+ },
+ };
+}
+
+#[test]
+fn it_get_dir_content() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_dir_content");
+ path.push("dir");
+
+ create_all(&path, true).unwrap();
+ assert!(path.exists());
+
+ let mut file1 = path.clone();
+ file1.push("test1.txt");
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ assert!(file1.exists());
+
+ let mut sub_dir_path = path.clone();
+ sub_dir_path.push("sub");
+ create(&sub_dir_path, true).unwrap();
+ let mut file2 = sub_dir_path.clone();
+ file2.push("test2.txt");
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ assert!(file2.exists());
+
+ let result = get_dir_content(&path).unwrap();
+
+ assert_eq!(get_dir_size() * 2 + 16, result.dir_size);
+ assert_eq!(2, result.files.len());
+ assert_eq!(2, result.directories.len());
+
+ let dir1 = file1.parent().unwrap().to_str().unwrap().to_string();
+ let dir2 = file2.parent().unwrap().to_str().unwrap().to_string();
+ let file1 = file1.to_str().unwrap().to_string();
+ let file2 = file2.to_str().unwrap().to_string();
+
+ let mut files_correct = true;
+ for file in result.files {
+ if file != file1 && file != file2 {
+ files_correct = false;
+ }
+ }
+ assert!(files_correct);
+
+ let mut directories_correct = true;
+ for dir in result.directories {
+ if dir != dir1 && dir != dir2 {
+ directories_correct = false;
+ }
+ }
+ assert!(directories_correct);
+}
+
+#[test]
+fn it_get_dir_content_many_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_get_dir_content_many_levels");
+ let d_level_1 = test_dir.join("d_level_1");
+ let d_level_2 = d_level_1.join("d_level_2");
+ let d_level_3 = d_level_2.join("d_level_3");
+ let d_level_4 = d_level_3.join("d_level_4");
+ let d_level_5 = d_level_4.join("d_level_5");
+
+ let file1 = d_level_1.join("file1.txt");
+ let file2 = d_level_2.join("file2.txt");
+ let file3 = d_level_3.join("file3.txt");
+ let file4 = d_level_4.join("file4.txt");
+ let file5 = d_level_5.join("file5.txt");
+
+ create_all(&d_level_1, true).unwrap();
+ create_all(&d_level_2, true).unwrap();
+ create_all(&d_level_3, true).unwrap();
+ create_all(&d_level_4, true).unwrap();
+ create_all(&d_level_5, true).unwrap();
+
+ assert!(&d_level_1.exists());
+ assert!(&d_level_2.exists());
+ assert!(&d_level_3.exists());
+ assert!(&d_level_4.exists());
+ assert!(&d_level_5.exists());
+
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+ fs_extra::file::write_all(&file3, "content3").unwrap();
+ fs_extra::file::write_all(&file4, "content4").unwrap();
+ fs_extra::file::write_all(&file5, "content5").unwrap();
+
+ let mut options = DirOptions::new();
+ let result = get_dir_content2(&d_level_1, &options).unwrap();
+
+ assert_eq!(get_dir_size() * 5 + 40, result.dir_size);
+ assert_eq!(5, result.files.len());
+ assert_eq!(5, result.directories.len());
+
+ let mut directories = Vec::new();
+ directories.push(file1.parent().unwrap().to_str().unwrap().to_string());
+ directories.push(file2.parent().unwrap().to_str().unwrap().to_string());
+ directories.push(file3.parent().unwrap().to_str().unwrap().to_string());
+ directories.push(file4.parent().unwrap().to_str().unwrap().to_string());
+ directories.push(file5.parent().unwrap().to_str().unwrap().to_string());
+
+ let mut files = Vec::new();
+ files.push(file1.to_str().unwrap().to_string());
+ files.push(file2.to_str().unwrap().to_string());
+ files.push(file3.to_str().unwrap().to_string());
+ files.push(file4.to_str().unwrap().to_string());
+ files.push(file5.to_str().unwrap().to_string());
+
+ let mut files_correct = true;
+ for file in result.files {
+ if !files.contains(&file) {
+ files_correct = false;
+ }
+ }
+ assert!(files_correct);
+
+ let mut directories_correct = true;
+ for dir in result.directories {
+ if !directories.contains(&dir) {
+ directories_correct = false;
+ }
+ }
+ assert!(directories_correct);
+
+ // first level
+ options.depth = 1;
+ let result = get_dir_content2(&d_level_1, &options).unwrap();
+
+ assert_eq!(get_dir_size() * 2 + 8, result.dir_size);
+ assert_eq!(1, result.files.len());
+ assert_eq!(2, result.directories.len());
+ files_correct = true;
+ for file in &result.files {
+ if !files.contains(&file) {
+ files_correct = false;
+ }
+ }
+ assert!(files_correct);
+ assert!(result.files.contains(&file1.to_str().unwrap().to_string()));
+
+ directories_correct = true;
+ for dir in &result.directories {
+ if !directories.contains(&dir) {
+ directories_correct = false;
+ }
+ }
+ assert!(directories_correct);
+ assert!(result
+ .directories
+ .contains(&file1.parent().unwrap().to_str().unwrap().to_string(),));
+ assert!(result
+ .directories
+ .contains(&file2.parent().unwrap().to_str().unwrap().to_string(),));
+
+ // fourth level
+ options.depth = 4;
+ let result = get_dir_content2(&d_level_1, &options).unwrap();
+
+ assert_eq!(get_dir_size() * 5 + 32, result.dir_size);
+ assert_eq!(4, result.files.len());
+ assert_eq!(5, result.directories.len());
+ files_correct = true;
+ for file in &result.files {
+ if !files.contains(&file) {
+ files_correct = false;
+ }
+ }
+ assert!(files_correct);
+ assert!(result.files.contains(&file1.to_str().unwrap().to_string()));
+ assert!(result.files.contains(&file2.to_str().unwrap().to_string()));
+ assert!(result.files.contains(&file3.to_str().unwrap().to_string()));
+ assert!(result.files.contains(&file4.to_str().unwrap().to_string()));
+
+ directories_correct = true;
+ for dir in &result.directories {
+ if !directories.contains(&dir) {
+ directories_correct = false;
+ }
+ }
+ assert!(directories_correct);
+ assert!(result
+ .directories
+ .contains(&file1.parent().unwrap().to_str().unwrap().to_string(),));
+ assert!(result
+ .directories
+ .contains(&file2.parent().unwrap().to_str().unwrap().to_string(),));
+ assert!(result
+ .directories
+ .contains(&file3.parent().unwrap().to_str().unwrap().to_string(),));
+ assert!(result
+ .directories
+ .contains(&file4.parent().unwrap().to_str().unwrap().to_string(),));
+ assert!(result
+ .directories
+ .contains(&file5.parent().unwrap().to_str().unwrap().to_string(),));
+}
+
+#[test]
+fn it_get_dir_content_path_file() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_dir_content_path_file");
+
+ create_all(&path, true).unwrap();
+ assert!(path.exists());
+
+ let mut file = path.clone();
+ file.push("test1.txt");
+ fs_extra::file::write_all(&file, "content1").unwrap();
+ assert!(file.exists());
+
+ let result = get_dir_content(&file).unwrap();
+
+ assert_eq!(8, result.dir_size);
+ assert_eq!(1, result.files.len());
+ assert_eq!(0, result.directories.len());
+ assert_eq!(file.to_str().unwrap().to_string(), result.files[0]);
+}
+
+#[test]
+fn it_get_dir_content_not_found() {
+ let mut path = PathBuf::from(TEST_FOLDER);
+ path.push("it_get_dir_content_not_found");
+
+ assert!(!path.exists());
+
+ match get_dir_content(&path) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => panic!("Wrong error!"),
+ },
+ }
+}
+
+#[test]
+fn it_details_item_dir() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_details_item_dir");
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ let mut config = HashSet::new();
+ config.insert(DirEntryAttr::Name);
+ config.insert(DirEntryAttr::Ext);
+ config.insert(DirEntryAttr::FullName);
+ config.insert(DirEntryAttr::Path);
+ config.insert(DirEntryAttr::DosPath);
+ config.insert(DirEntryAttr::Size);
+ config.insert(DirEntryAttr::IsDir);
+ config.insert(DirEntryAttr::IsFile);
+ config.insert(DirEntryAttr::Modified);
+ config.insert(DirEntryAttr::Accessed);
+ let item = get_details_entry(test_dir, &config).unwrap();
+ assert_eq!(10, item.len());
+
+ let mut fields = 0;
+ if let Some(name) = item.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!("it_details_item_dir", name);
+ fields += 1;
+ }
+ }
+ if let Some(ext) = item.get(&DirEntryAttr::Ext) {
+ if let &DirEntryValue::String(ref ext) = ext {
+ assert_eq!("", ext);
+ fields += 1;
+ }
+ }
+ if let Some(fname) = item.get(&DirEntryAttr::FullName) {
+ if let &DirEntryValue::String(ref fname) = fname {
+ assert_eq!("it_details_item_dir", fname);
+ fields += 1;
+ }
+ }
+ if let Some(path) = item.get(&DirEntryAttr::Path) {
+ if let &DirEntryValue::String(ref path) = path {
+ if !path.is_empty() {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(path) = item.get(&DirEntryAttr::DosPath) {
+ if let &DirEntryValue::String(ref path) = path {
+ if !path.is_empty() {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(0, size);
+ fields += 1;
+ }
+ }
+ if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) {
+ if let &DirEntryValue::Boolean(is_dir) = is_dir {
+ assert_eq!(true, is_dir);
+ fields += 1;
+ }
+ }
+
+ if let Some(is_file) = item.get(&DirEntryAttr::IsFile) {
+ if let &DirEntryValue::Boolean(is_file) = is_file {
+ assert_eq!(false, is_file);
+ fields += 1;
+ }
+ }
+
+ if let Some(modified) = item.get(&DirEntryAttr::Modified) {
+ if let &DirEntryValue::SystemTime(modified) = modified {
+ if modified.elapsed().unwrap().as_secs() == 0 {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(accessed) = item.get(&DirEntryAttr::Accessed) {
+ if let &DirEntryValue::SystemTime(accessed) = accessed {
+ if accessed.elapsed().unwrap().as_secs() == 0 {
+ fields += 1;
+ }
+ }
+ }
+
+ assert_eq!(10, fields);
+}
+
+#[test]
+fn it_details_file_item() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_details_file_item");
+ create_all(&test_dir, true).unwrap();
+ let file = test_dir.join("file.txt");
+ fs_extra::file::write_all(&file, "content").unwrap();
+ assert!(file.exists());
+ let mut config = HashSet::new();
+ config.insert(DirEntryAttr::Name);
+ config.insert(DirEntryAttr::Ext);
+ config.insert(DirEntryAttr::FullName);
+ config.insert(DirEntryAttr::Path);
+ config.insert(DirEntryAttr::DosPath);
+ config.insert(DirEntryAttr::Size);
+ config.insert(DirEntryAttr::FileSize);
+ config.insert(DirEntryAttr::IsDir);
+ config.insert(DirEntryAttr::IsFile);
+ config.insert(DirEntryAttr::Modified);
+ config.insert(DirEntryAttr::Accessed);
+ let item = get_details_entry(file, &config).unwrap();
+ assert_eq!(11, item.len());
+
+ let mut fields = 0;
+ if let Some(name) = item.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!("file", name);
+ fields += 1;
+ }
+ }
+ if let Some(ext) = item.get(&DirEntryAttr::Ext) {
+ if let &DirEntryValue::String(ref ext) = ext {
+ assert_eq!("txt", ext);
+ fields += 1;
+ }
+ }
+ if let Some(fname) = item.get(&DirEntryAttr::FullName) {
+ if let &DirEntryValue::String(ref fname) = fname {
+ assert_eq!("file.txt", fname);
+ fields += 1;
+ }
+ }
+ if let Some(path) = item.get(&DirEntryAttr::Path) {
+ if let &DirEntryValue::String(ref path) = path {
+ if !path.is_empty() {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(path) = item.get(&DirEntryAttr::DosPath) {
+ if let &DirEntryValue::String(ref path) = path {
+ if !path.is_empty() {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(7, size);
+ fields += 1;
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::FileSize) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(7, size);
+ fields += 1;
+ }
+ }
+ if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) {
+ if let &DirEntryValue::Boolean(is_dir) = is_dir {
+ assert_eq!(false, is_dir);
+ fields += 1;
+ }
+ }
+
+ if let Some(is_file) = item.get(&DirEntryAttr::IsFile) {
+ if let &DirEntryValue::Boolean(is_file) = is_file {
+ assert_eq!(true, is_file);
+ fields += 1;
+ }
+ }
+
+ if let Some(modified) = item.get(&DirEntryAttr::Modified) {
+ if let &DirEntryValue::SystemTime(modified) = modified {
+ if modified.elapsed().unwrap().as_secs() == 0 {
+ fields += 1;
+ }
+ }
+ }
+ if let Some(accessed) = item.get(&DirEntryAttr::Accessed) {
+ if let &DirEntryValue::SystemTime(accessed) = accessed {
+ if accessed.elapsed().unwrap().as_secs() == 0 {
+ fields += 1;
+ }
+ }
+ }
+
+ assert_eq!(11, fields);
+}
+
+#[test]
+fn it_details_item_dir_short() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_details_item_dir_short");
+ create_all(&test_dir, true).unwrap();
+ assert!(test_dir.exists());
+ let mut config = HashSet::new();
+ config.insert(DirEntryAttr::Name);
+ config.insert(DirEntryAttr::Size);
+ let item = get_details_entry(test_dir, &config).unwrap();
+ assert_eq!(2, item.len());
+
+ if let Some(name) = item.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!("it_details_item_dir_short", name);
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(0, size);
+ }
+ }
+}
+
+#[test]
+fn it_details_item_file_short() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_details_item_short");
+ create_all(&test_dir, true).unwrap();
+ let file = test_dir.join("file.txt");
+ fs_extra::file::write_all(&file, "content").unwrap();
+ assert!(file.exists());
+ let mut config = HashSet::new();
+ config.insert(DirEntryAttr::Name);
+ config.insert(DirEntryAttr::Size);
+ let item = get_details_entry(file, &config).unwrap();
+ assert_eq!(2, item.len());
+
+ if let Some(name) = item.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!("file", name);
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(7, size);
+ }
+ }
+}
+
+#[test]
+fn it_ls() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_ls");
+ create_all(&test_dir, true).unwrap();
+ let file1 = test_dir.join("file1.txt");
+ let file2 = test_dir.join("file2.txt");
+ fs_extra::file::write_all(&file1, "content").unwrap();
+ fs_extra::file::write_all(&file2, "content").unwrap();
+ assert!(file1.exists());
+ assert!(file2.exists());
+ let mut config = HashSet::new();
+ config.insert(DirEntryAttr::Name);
+ config.insert(DirEntryAttr::Size);
+ config.insert(DirEntryAttr::IsDir);
+ config.insert(DirEntryAttr::BaseInfo);
+ let ls_result = ls(&test_dir, &config).unwrap();
+ assert_eq!(2, ls_result.items.len());
+ assert_eq!(3, ls_result.base.len());
+
+ if let Some(name) = ls_result.base.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!("it_ls", name);
+ }
+ }
+ if let Some(size) = ls_result.base.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(14, size);
+ }
+ }
+ if let Some(is_dir) = ls_result.base.get(&DirEntryAttr::IsDir) {
+ if let &DirEntryValue::Boolean(is_dir) = is_dir {
+ assert_eq!(true, is_dir);
+ }
+ }
+ for item in ls_result.items {
+ if let Some(name) = item.get(&DirEntryAttr::Name) {
+ if let &DirEntryValue::String(ref name) = name {
+ assert_eq!(String::from("file"), name[..4]);
+ }
+ }
+ if let Some(size) = item.get(&DirEntryAttr::Size) {
+ if let &DirEntryValue::U64(size) = size {
+ assert_eq!(7, size);
+ }
+ }
+ if let Some(is_dir) = item.get(&DirEntryAttr::IsDir) {
+ if let &DirEntryValue::Boolean(is_dir) = is_dir {
+ assert_eq!(false, is_dir);
+ }
+ }
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::Overwrite;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(2, count_exist_files);
+
+ assert_eq!(16, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ assert!(compare_dir(&dir.0, &out));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_overwrite_all() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite_all");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::OverwriteAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(16, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ assert!(compare_dir(&dir.0, &out));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::Skip;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(2, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ assert!(!compare_dir(&dir.0, &out));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_skip_all() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip_all");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::SkipAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ assert!(!compare_dir(&dir.0, &out));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_retry() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_retry");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ if count_exist_files == 3 || count_exist_files == 6 {
+ result = TransitProcessResult::Skip;
+ } else {
+ result = TransitProcessResult::Retry;
+ }
+ count_exist_files += 1;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = copy_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(7, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ assert!(!compare_dir(&dir.0, &out));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_inside_work_target_dir_not_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_copy_with_progress_inside_work_target_dir_not_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+
+ if root_dir2.exists() {
+ remove(&root_dir2).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(!root_dir2.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(15, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(compare_dir_recursively(&root_dir1, &root_dir2));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(7, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join(
+ "it_copy_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir",
+ );
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+
+ if root_dir2_dir1.exists() {
+ remove(&root_dir2_dir1).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(!root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(17, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(compare_dir(&root_dir1, &root_dir2));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join(
+ "it_copy_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist",
+ );
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content22").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::Skip
+ };
+ let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(0, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(!files_eq(file1, old_file1));
+ assert!(!files_eq(file2, old_file2));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root
+ .join("it_copy_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content22").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ options.overwrite = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(17, result);
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(compare_dir(&root_dir1, &root_dir2));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::Overwrite;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(2, count_exist_files);
+
+ assert_eq!(16, result);
+ assert!(!dir.0.exists());
+ assert!(dir.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_overwrite_all() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite_all");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::OverwriteAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(16, result);
+ assert!(!dir.0.exists());
+ assert!(dir.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::Skip;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(2, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_skip_all() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip_all");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ count_exist_files += 1;
+ result = TransitProcessResult::SkipAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_retry() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_retry");
+ let out = test_dir.join("out");
+ let dir = (test_dir.join("dir"), out.join("dir"));
+ let file1 = (dir.0.join("file1.txt"), dir.1.join("file1.txt"));
+ let file2 = (dir.0.join("file2.txt"), dir.1.join("file2.txt"));
+
+ create_all(&dir.0, true).unwrap();
+ create_all(&dir.1, true).unwrap();
+
+ assert!(&dir.0.exists());
+ assert!(&dir.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content7").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+
+ let mut options = CopyOptions::new();
+ assert!(!compare_dir(&dir.0, &out));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: TransitProcessResult;
+ match process_info.state {
+ TransitState::Exists => {
+ if count_exist_files == 3 || count_exist_files == 6 {
+ result = TransitProcessResult::Skip;
+ } else {
+ result = TransitProcessResult::Retry;
+ }
+ count_exist_files += 1;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = TransitProcessResult::Abort,
+ };
+ result
+ };
+ result = move_dir_with_progress(&dir.0, &out, &options, func_test).unwrap();
+ }
+ assert_eq!(7, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir.0.exists());
+ assert!(dir.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_dir_with_progress_inside_work_target_dir_not_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join("it_move_dir_with_progress_inside_work_target_dir_not_exist");
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content").unwrap();
+ fs_extra::file::write_all(&file2, "content2").unwrap();
+
+ if root_dir2.exists() {
+ remove(&root_dir2).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(!root_dir2.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(15, result);
+ assert!(!root_dir1.exists());
+ let root_dir2_sub = root_dir2.join("sub");
+ let root_dir2_file1 = root_dir2.join("file1.txt");
+ let root_dir2_sub_file2 = root_dir2_sub.join("file2.txt");
+ assert!(root_dir2.exists());
+ assert!(root_dir2_sub.exists());
+ assert!(root_dir2_file1.exists());
+ assert!(root_dir2_sub_file2.exists());
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(7, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 15, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_dir_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join(
+ "it_move_dir_with_progress_inside_work_target_dir_exist_with_no_source_dir_named_sub_dir",
+ );
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+
+ if root_dir2_dir1.exists() {
+ remove(&root_dir2_dir1).unwrap();
+ }
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(!root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(17, result);
+ assert!(!root_dir1.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir3.exists());
+ let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt");
+ let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt");
+ assert!(root_dir2_dir1_file1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir1_sub_file2.exists());
+ assert!(root_dir2_dir3_file3.exists());
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_dir_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join(
+ "it_move_dir_with_progress_inside_no_overwrite_work_target_dir_exist_with_source_dir_exist",
+ );
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content22").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::Skip
+ };
+ let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(0, result);
+
+ assert!(root_dir1.exists());
+ assert!(file1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(file2.exists());
+
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt");
+ let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt");
+ let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt");
+ assert!(root_dir2_dir1_file1.exists());
+ assert!(root_dir2_dir1_sub_file2.exists());
+ assert!(root_dir2_dir3_file3.exists());
+ assert!(!files_eq(file1, old_file1));
+ assert!(!files_eq(file2, old_file2));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_dir_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist() {
+ let path_root = Path::new(TEST_FOLDER);
+ let root = path_root.join(
+ "it_move_dir_with_progress_inside_overwrite_work_target_dir_exist_with_source_dir_exist",
+ );
+ let root_dir1 = root.join("dir1");
+ let root_dir1_sub = root_dir1.join("sub");
+ let root_dir2 = root.join("dir2");
+ let root_dir2_dir1 = root_dir2.join("dir1");
+ let root_dir2_dir1_sub = root_dir2_dir1.join("sub");
+ let root_dir2_dir3 = root_dir2.join("dir3");
+ let file1 = root_dir1.join("file1.txt");
+ let file2 = root_dir1_sub.join("file2.txt");
+ let file3 = root_dir2_dir3.join("file3.txt");
+ let old_file1 = root_dir2_dir1.join("file1.txt");
+ let old_file2 = root_dir2_dir1_sub.join("file2.txt");
+
+ create_all(&root_dir1_sub, true).unwrap();
+ create_all(&root_dir2_dir3, true).unwrap();
+ create_all(&root_dir2_dir1, true).unwrap();
+ create_all(&root_dir2_dir1_sub, true).unwrap();
+ fs_extra::file::write_all(&file1, "content1").unwrap();
+ fs_extra::file::write_all(&file2, "content22").unwrap();
+ fs_extra::file::write_all(&file3, "content333").unwrap();
+ fs_extra::file::write_all(&old_file1, "old_content1").unwrap();
+ fs_extra::file::write_all(&old_file2, "old_content22").unwrap();
+
+ assert!(root_dir1.exists());
+ assert!(root_dir1_sub.exists());
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(old_file1.exists());
+ assert!(old_file2.exists());
+
+ let mut options = CopyOptions::new();
+ options.copy_inside = true;
+ options.overwrite = true;
+
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_dir_with_progress(&root_dir1, &root_dir2, &options, func_test).unwrap();
+
+ assert_eq!(17, result);
+
+ assert!(!root_dir1.exists());
+
+ assert!(root_dir2.exists());
+ assert!(root_dir2_dir1.exists());
+ assert!(root_dir2_dir1_sub.exists());
+ assert!(root_dir2_dir3.exists());
+ let root_dir2_dir1_file1 = root_dir2_dir1.join("file1.txt");
+ let root_dir2_dir1_sub_file2 = root_dir2_dir1_sub.join("file2.txt");
+ let root_dir2_dir3_file3 = root_dir2_dir3.join("file3.txt");
+ assert!(root_dir2_dir1_file1.exists());
+ assert!(root_dir2_dir1_sub_file2.exists());
+ assert!(root_dir2_dir3_file3.exists());
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(get_dir_size() * 2 + 17, process_info.total_bytes);
+ } else {
+ panic!("Unknow file name!");
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+#[test]
+fn it_move_with_progress_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_content_only_option");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.clone());
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+
+ create_all(&d_level_1.0, true).unwrap();
+ create_all(&d_level_2.0, true).unwrap();
+ create_all(&d_level_3.0, true).unwrap();
+ create_all(&path_to, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+
+ let mut options = CopyOptions::new();
+ options.content_only = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = move_dir_with_progress(&d_level_1.0, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(24, result);
+
+ assert!(!d_level_1.0.exists());
+ assert!(!d_level_2.0.exists());
+ assert!(!d_level_3.0.exists());
+
+ assert!(d_level_1.1.exists());
+ assert!(d_level_2.1.exists());
+ assert!(d_level_3.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
diff --git a/vendor/fs_extra/tests/file.rs b/vendor/fs_extra/tests/file.rs
new file mode 100644
index 000000000..67840a532
--- /dev/null
+++ b/vendor/fs_extra/tests/file.rs
@@ -0,0 +1,1036 @@
+// use std::io::{ErrorKind, Result};
+use std::path::{Path, PathBuf};
+use std::sync::mpsc;
+use std::thread;
+
+extern crate fs_extra;
+use fs_extra::error::*;
+use fs_extra::file::*;
+
+const TEST_FOLDER: &'static str = "./tests/temp/file";
+
+fn files_eq<P, Q>(file1: P, file2: Q) -> Result<bool>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let content1 = read_to_string(file1)?;
+ let content2 = read_to_string(file2)?;
+ Ok(content1 == content2)
+}
+
+#[test]
+fn it_read_and_write_work() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_read_and_write_work");
+ test_file.push("test.txt");
+ fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap();
+ let content1 = "test_1";
+ let content2 = "test_2";
+ write_all(&test_file, &content1).unwrap();
+ assert!(test_file.exists());
+ let read1 = read_to_string(&test_file).unwrap();
+ assert_eq!(content1, read1);
+ write_all(&test_file, &content2).unwrap();
+ let read2 = read_to_string(&test_file).unwrap();
+ assert_eq!(content2, read2);
+}
+
+#[test]
+fn it_read_not_exist_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_read_not_exist_file");
+ test_file.push("test.txt");
+ fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap();
+ assert!(!test_file.exists());
+ match read_to_string(&test_file) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_read_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_read_not_file");
+ fs_extra::dir::create_all(&test_file, true).unwrap();
+ match read_to_string(&test_file) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {}
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_write_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_write_not_file");
+ test_file.push("test.txt");
+ fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap();
+ assert!(!test_file.exists());
+ test_file.pop();
+ match write_all(test_file, "content") {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {}
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_remove_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_remove_file");
+ test_file.push("test.txt");
+ fs_extra::dir::create_all(test_file.parent().unwrap(), true).unwrap();
+ write_all(&test_file, "test").unwrap();
+ assert!(test_file.exists());
+ remove(&test_file).unwrap();
+ assert!(!test_file.exists());
+}
+
+#[test]
+fn it_copy_work() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(test_file.file_name(), test_file_out.file_name());
+ assert!(files_eq(test_file, test_file_out).unwrap());
+}
+
+#[test]
+fn it_copy_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ test_file.pop();
+ let options = CopyOptions::new();
+
+ match copy(&test_file, &test_file_out, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {
+ let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_source_not_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_source_not_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test1.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ assert!(!test_file.exists());
+ let options = CopyOptions::new();
+ match copy(&test_file, test_file_out, &options) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't have \
+ access!",
+ test_file.to_str().unwrap()
+ );
+ assert_eq!(wrong_path, err.to_string());
+ ()
+ }
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_copy_exist_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_exist_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match copy(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_copy_exist_not_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_exist_not_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.overwrite = false;
+ write_all(&test_file, "test_data2").unwrap();
+ match copy(&test_file, &test_file_out, &options) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => {
+ let file_path = format!("Path \"{}\" exists", test_file_out.to_str().unwrap());
+ assert_eq!(file_path, err.to_string());
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ }
+}
+
+#[test]
+fn it_copy_exist_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_exist_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match copy(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ Err(_) => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_copy_exist_overwrite_and_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_exist_overwrite_and_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match copy(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_work() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let mut options = CopyOptions::new();
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ };
+ copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap();
+ assert!(test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(test_file.file_name(), test_file_out.file_name());
+ assert!(files_eq(test_file, test_file_out).unwrap());
+ });
+ for i in 1..10 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(9, process_info.total_bytes);
+ }
+}
+
+#[test]
+fn it_copy_progress_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_progress_not_file");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ test_file.pop();
+ let options = CopyOptions::new();
+ let func_test = |process_info: TransitProcess| println!("{}", process_info.total_bytes);
+
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {
+ let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_with_progress_work_dif_buf_size() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_work_dif_buf_size");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data_").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let mut options = CopyOptions::new();
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ };
+ copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap();
+ assert!(test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(test_file.file_name(), test_file_out.file_name());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+
+ let mut options = CopyOptions::new();
+ options.buffer_size = 2;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ };
+ copy_with_progress(&test_file, &test_file_out, &options, func_test).unwrap();
+ });
+ for i in 1..6 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2, process_info.copied_bytes);
+ assert_eq!(10, process_info.total_bytes);
+ }
+ });
+ for i in 1..11 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(10, process_info.total_bytes);
+ }
+}
+
+#[test]
+fn it_copy_with_progress_source_not_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_source_not_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test1.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ assert!(!test_file.exists());
+ let options = CopyOptions::new();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't have \
+ access!",
+ test_file.to_str().unwrap()
+ );
+
+ assert_eq!(wrong_path, err.to_string());
+ ()
+ }
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_exist_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_not_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_exist_not_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.overwrite = false;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => {
+ let file_path = format!("Path \"{}\" exists", test_file_out.to_str().unwrap());
+
+ assert_eq!(file_path, err.to_string());
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_exist_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ Err(_) => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite_and_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_copy_with_progress_exist_overwrite_and_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match copy_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_move_work() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let options = CopyOptions::new();
+ let old_name = test_file.file_name();
+ let old_content = read_to_string(&test_file).unwrap();
+ move_file(&test_file, &test_file_out, &options).unwrap();
+ assert!(!test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(old_name, test_file_out.file_name());
+ let new_content = read_to_string(&test_file_out).unwrap();
+ assert_eq!(old_content, new_content);
+}
+
+#[test]
+fn it_move_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ test_file.pop();
+ let options = CopyOptions::new();
+
+ match move_file(&test_file, &test_file_out, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {
+ let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_source_not_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_source_not_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test1.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ assert!(!test_file.exists());
+ let options = CopyOptions::new();
+ match move_file(&test_file, &test_file_out, &options) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't have \
+ access!",
+ test_file.to_str().unwrap()
+ );
+
+ assert_eq!(wrong_path, err.to_string());
+ ()
+ }
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_move_exist_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_exist_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match move_file(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(!test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_move_exist_not_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_exist_not_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.overwrite = false;
+ write_all(&test_file, "test_data2").unwrap();
+ match move_file(&test_file, &test_file_out, &options) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => {
+ let file_path = format!("Path \"{}\" exists", test_file_out.to_str().unwrap());
+
+ assert_eq!(file_path, err.to_string());
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ }
+}
+
+#[test]
+fn it_move_exist_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_exist_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match move_file(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ Err(_) => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_move_exist_overwrite_and_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_exist_overwrite_and_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ match move_file(&test_file, &test_file_out, &options) {
+ Ok(_) => {
+ assert!(!test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_move_with_progress_work() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_work");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let mut options = CopyOptions::new();
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || {
+ let old_name = test_file.file_name();
+ let old_content = read_to_string(&test_file).unwrap();
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ };
+ move_file_with_progress(&test_file, &test_file_out, &options, func_test).unwrap();
+ assert!(!test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(old_name, test_file_out.file_name());
+ let new_content = read_to_string(&test_file_out).unwrap();
+ assert_eq!(old_content, new_content);
+ });
+ for i in 1..10 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(9, process_info.total_bytes);
+ }
+}
+
+#[test]
+fn it_move_progress_not_file() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_progress_not_file");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ test_file.pop();
+ let options = CopyOptions::new();
+ let func_test = |process_info: TransitProcess| println!("{}", process_info.total_bytes);
+
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Err(err) => match err.kind {
+ ErrorKind::InvalidFile => {
+ let wrong_path = format!("Path \"{}\" is not a file!", test_file.to_str().unwrap());
+ assert_eq!(wrong_path, err.to_string());
+ }
+ _ => {
+ panic!("wrong error");
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_with_progress_work_dif_buf_size() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_work_dif_buf_size");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data_").unwrap();
+ assert!(test_file.exists());
+ assert!(!test_file_out.exists());
+ let mut options = CopyOptions::new();
+ options.buffer_size = 2;
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || {
+ let old_name = test_file.file_name();
+ let old_content = read_to_string(&test_file).unwrap();
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ };
+ move_file_with_progress(&test_file, &test_file_out, &options, func_test).unwrap();
+ assert!(!test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(old_name, test_file_out.file_name());
+ let new_content = read_to_string(&test_file_out).unwrap();
+ assert_eq!(old_content, new_content);
+ });
+ for i in 1..6 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2, process_info.copied_bytes);
+ assert_eq!(10, process_info.total_bytes);
+ }
+}
+
+#[test]
+fn it_move_with_progress_source_not_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_source_not_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test1.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ assert!(!test_file.exists());
+ let options = CopyOptions::new();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {
+ let wrong_path = format!(
+ "Path \"{}\" does not exist or you don't have \
+ access!",
+ test_file.to_str().unwrap()
+ );
+
+ assert_eq!(wrong_path, err.to_string());
+ ()
+ }
+ _ => panic!("wrong error"),
+ },
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_exist_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(!test_file.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_not_overwrite() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_exist_not_overwrite");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.overwrite = false;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => panic!("should be error"),
+ Err(err) => {
+ let file_path = format!("Path \"{}\" exists", test_file_out.to_str().unwrap());
+
+ assert_eq!(file_path, err.to_string());
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_exist_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(!files_eq(test_file, test_file_out).unwrap());
+ ()
+ }
+ Err(_) => panic!("should be error"),
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite_and_skip_exist() {
+ let mut test_file = PathBuf::from(TEST_FOLDER);
+ test_file.push("it_move_with_progress_exist_overwrite_and_skip_exist");
+ let mut test_file_out = test_file.clone();
+ test_file.push("test.txt");
+ test_file_out.push("out");
+ test_file_out.push("test.txt");
+ fs_extra::dir::create_all(&test_file.parent().unwrap(), true).unwrap();
+ fs_extra::dir::create_all(&test_file_out.parent().unwrap(), true).unwrap();
+
+ write_all(&test_file, "test_data").unwrap();
+ let mut options = CopyOptions::new();
+ copy(&test_file, &test_file_out, &options).unwrap();
+ assert!(test_file.exists());
+ assert!(files_eq(&test_file, &test_file_out).unwrap());
+ options.overwrite = true;
+ options.skip_exist = true;
+ write_all(&test_file, "test_data2").unwrap();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ };
+ match move_file_with_progress(&test_file, &test_file_out, &options, func_test) {
+ Ok(_) => {
+ assert!(!test_file.exists());
+ assert!(test_file_out.exists());
+ assert_eq!(read_to_string(test_file_out).unwrap(), "test_data2");
+ ()
+ }
+ Err(err) => panic!(err.to_string()),
+ }
+}
diff --git a/vendor/fs_extra/tests/lib.rs b/vendor/fs_extra/tests/lib.rs
new file mode 100644
index 000000000..2d8bfd024
--- /dev/null
+++ b/vendor/fs_extra/tests/lib.rs
@@ -0,0 +1,3883 @@
+use std::fs::read_dir;
+use std::path::Path;
+use std::sync::mpsc::{self, TryRecvError};
+use std::thread;
+
+extern crate fs_extra;
+use fs_extra::error::*;
+use fs_extra::*;
+
+fn files_eq<P, Q>(file1: P, file2: Q) -> bool
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let content1 = fs_extra::file::read_to_string(file1).unwrap();
+ let content2 = fs_extra::file::read_to_string(file2).unwrap();
+ content1 == content2
+}
+
+fn compare_dir<P, Q>(path_from: P, path_to: Q) -> bool
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>,
+{
+ let mut path_to = path_to.as_ref().to_path_buf();
+ match path_from.as_ref().components().last() {
+ None => panic!("Invalid folder from"),
+ Some(dir_name) => {
+ path_to.push(dir_name.as_os_str());
+ if !path_to.exists() {
+ return false;
+ }
+ }
+ }
+
+ for entry in read_dir(&path_from).unwrap() {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ if path.is_dir() {
+ if !compare_dir(path, &path_to) {
+ return false;
+ }
+ } else {
+ let mut path_to = path_to.to_path_buf();
+ match path.file_name() {
+ None => panic!("No file name"),
+ Some(file_name) => {
+ path_to.push(file_name);
+ if !path_to.exists() {
+ return false;
+ } else if !files_eq(&path, path_to.clone()) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+
+ true
+}
+
+const TEST_FOLDER: &'static str = "./tests/temp/lib";
+
+#[test]
+fn it_copy_work() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_work");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(!sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ let result = copy_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+}
+
+#[test]
+fn it_copy_source_not_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_source_not_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ assert!(!dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(!dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(!sub.0.exists());
+ assert!(!sub.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file1.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ match copy_items(&from_paths, &path_to, &options) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => {}
+ },
+ };
+}
+
+#[test]
+fn it_copy_exist_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ let result = copy_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+}
+
+#[test]
+fn it_copy_exist_not_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_not_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ match copy_items(&from_paths, &path_to, &options) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!(format!("{}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_copy_exist_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_skip");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.skip_exist = true;
+ let result = copy_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+}
+
+#[test]
+fn it_copy_exist_overwrite_and_skip_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_exist_overwrite_and_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ let result = copy_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+}
+
+#[test]
+fn it_copy_using_first_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_first_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1"));
+ let d2_level_2 = (
+ d_level_1.0.join("d2_level_2"),
+ d_level_1.1.join("d2_level_2"),
+ );
+ let d2_level_3 = (
+ d_level_2.0.join("d2_level_3"),
+ d_level_2.1.join("d2_level_3"),
+ );
+ let d2_level_4 = (
+ d_level_3.0.join("d2_level_4"),
+ d_level_3.1.join("d2_level_4"),
+ );
+ let d2_level_5 = (
+ d_level_4.0.join("d2_level_5"),
+ d_level_4.1.join("d2_level_5"),
+ );
+
+ let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ let file21 = (
+ d2_level_1.0.join("file21.txt"),
+ d2_level_1.1.join("file21.txt"),
+ );
+ let file22 = (
+ d2_level_2.0.join("file22.txt"),
+ d2_level_2.1.join("file22.txt"),
+ );
+ let file23 = (
+ d2_level_3.0.join("file23.txt"),
+ d2_level_3.1.join("file23.txt"),
+ );
+ let file24 = (
+ d2_level_4.0.join("file24.txt"),
+ d2_level_4.1.join("file24.txt"),
+ );
+ let file25 = (
+ d2_level_5.0.join("file25.txt"),
+ d2_level_5.1.join("file25.txt"),
+ );
+
+ let file31 = (
+ d3_level_1.0.join("file31.txt"),
+ d3_level_1.1.join("file31.txt"),
+ );
+
+ dir::create_all(&d_level_1.0, true).unwrap();
+ dir::create_all(&d_level_2.0, true).unwrap();
+ dir::create_all(&d_level_3.0, true).unwrap();
+ dir::create_all(&d_level_4.0, true).unwrap();
+ dir::create_all(&d_level_5.0, true).unwrap();
+ dir::create_all(&path_to, true).unwrap();
+
+ dir::create_all(&d2_level_1.0, true).unwrap();
+ dir::create_all(&d2_level_2.0, true).unwrap();
+ dir::create_all(&d2_level_3.0, true).unwrap();
+ dir::create_all(&d2_level_4.0, true).unwrap();
+ dir::create_all(&d2_level_5.0, true).unwrap();
+
+ dir::create_all(&d3_level_1.0, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d2_level_1.0.exists());
+ assert!(d2_level_2.0.exists());
+ assert!(d2_level_3.0.exists());
+ assert!(d2_level_4.0.exists());
+ assert!(d2_level_5.0.exists());
+
+ assert!(d3_level_1.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(!d2_level_1.1.exists());
+ assert!(!d2_level_2.1.exists());
+ assert!(!d2_level_3.1.exists());
+ assert!(!d2_level_4.1.exists());
+ assert!(!d2_level_5.1.exists());
+
+ assert!(!d3_level_1.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file21.0, "2content1").unwrap();
+ fs_extra::file::write_all(&file22.0, "2content2").unwrap();
+ fs_extra::file::write_all(&file23.0, "2content3").unwrap();
+ fs_extra::file::write_all(&file24.0, "2content4").unwrap();
+ fs_extra::file::write_all(&file25.0, "2content5").unwrap();
+
+ fs_extra::file::write_all(&file31.0, "3content1").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(!file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(!file31.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(d_level_1.0.as_path());
+ from_paths.push(d2_level_1.0.as_path());
+ from_paths.push(d3_level_1.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.depth = 1;
+ let result = copy_items(&from_paths, path_to, &options).unwrap();
+
+ assert_eq!(26, result);
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(file31.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file21.0, &file21.1));
+ assert!(files_eq(&file31.0, &file31.1));
+}
+
+#[test]
+fn it_copy_using_four_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_using_four_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1"));
+ let d2_level_2 = (
+ d_level_1.0.join("d2_level_2"),
+ d_level_1.1.join("d2_level_2"),
+ );
+ let d2_level_3 = (
+ d_level_2.0.join("d2_level_3"),
+ d_level_2.1.join("d2_level_3"),
+ );
+ let d2_level_4 = (
+ d_level_3.0.join("d2_level_4"),
+ d_level_3.1.join("d2_level_4"),
+ );
+ let d2_level_5 = (
+ d_level_4.0.join("d2_level_5"),
+ d_level_4.1.join("d2_level_5"),
+ );
+
+ let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ let file21 = (
+ d2_level_1.0.join("file21.txt"),
+ d2_level_1.1.join("file21.txt"),
+ );
+ let file22 = (
+ d2_level_2.0.join("file22.txt"),
+ d2_level_2.1.join("file22.txt"),
+ );
+ let file23 = (
+ d2_level_3.0.join("file23.txt"),
+ d2_level_3.1.join("file23.txt"),
+ );
+ let file24 = (
+ d2_level_4.0.join("file24.txt"),
+ d2_level_4.1.join("file24.txt"),
+ );
+ let file25 = (
+ d2_level_5.0.join("file25.txt"),
+ d2_level_5.1.join("file25.txt"),
+ );
+
+ let file31 = (
+ d3_level_1.0.join("file31.txt"),
+ d3_level_1.1.join("file31.txt"),
+ );
+
+ dir::create_all(&d_level_1.0, true).unwrap();
+ dir::create_all(&d_level_2.0, true).unwrap();
+ dir::create_all(&d_level_3.0, true).unwrap();
+ dir::create_all(&d_level_4.0, true).unwrap();
+ dir::create_all(&d_level_5.0, true).unwrap();
+ dir::create_all(&path_to, true).unwrap();
+
+ dir::create_all(&d2_level_1.0, true).unwrap();
+ dir::create_all(&d2_level_2.0, true).unwrap();
+ dir::create_all(&d2_level_3.0, true).unwrap();
+ dir::create_all(&d2_level_4.0, true).unwrap();
+ dir::create_all(&d2_level_5.0, true).unwrap();
+
+ dir::create_all(&d3_level_1.0, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d2_level_1.0.exists());
+ assert!(d2_level_2.0.exists());
+ assert!(d2_level_3.0.exists());
+ assert!(d2_level_4.0.exists());
+ assert!(d2_level_5.0.exists());
+
+ assert!(d3_level_1.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(!d2_level_1.1.exists());
+ assert!(!d2_level_2.1.exists());
+ assert!(!d2_level_3.1.exists());
+ assert!(!d2_level_4.1.exists());
+ assert!(!d2_level_5.1.exists());
+
+ assert!(!d3_level_1.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file21.0, "2content1").unwrap();
+ fs_extra::file::write_all(&file22.0, "2content2").unwrap();
+ fs_extra::file::write_all(&file23.0, "2content3").unwrap();
+ fs_extra::file::write_all(&file24.0, "2content4").unwrap();
+ fs_extra::file::write_all(&file25.0, "2content5").unwrap();
+
+ fs_extra::file::write_all(&file31.0, "3content1").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(!file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(!file31.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(d_level_1.0.as_path());
+ from_paths.push(d2_level_1.0.as_path());
+ from_paths.push(d3_level_1.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.depth = 4;
+ let result = copy_items(&from_paths, path_to, &options).unwrap();
+
+ assert_eq!(77, result);
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(file21.1.exists());
+ assert!(file22.1.exists());
+ assert!(file23.1.exists());
+ assert!(file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(file31.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file21.0, &file21.1));
+ assert!(files_eq(&file31.0, &file31.1));
+}
+#[test]
+
+fn it_copy_content_only_opton() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_content_only_opton");
+ let path_to = test_dir.join("out");
+
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ let mut options = dir::CopyOptions::new();
+ options.content_only = true;
+ match copy_items(&vec![&file1.0], &file1.1, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::Other => {
+ assert_eq!(1, 1);
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_copy_progress_work() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_progress_work");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(!sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content22").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let options = dir::CopyOptions::new();
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(41, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(41, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(41, process_info.total_bytes);
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_work_dif_buf_size() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_work_dif_buf_size");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(!sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(file1.0.as_path().to_str().unwrap().to_string());
+ from_paths.push(file2.0.as_path().to_str().unwrap().to_string());
+ from_paths.push(dir1.0.as_path().to_str().unwrap().to_string());
+ from_paths.push(dir2.0.as_path().to_str().unwrap().to_string());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+
+ let mut options = dir::CopyOptions::new();
+ options.buffer_size = 2;
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result =
+ copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(i * 2, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(40, process_info.total_bytes);
+ }
+ for i in 1..5 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i * 2 + 8, process_info.copied_bytes);
+ assert_eq!(i * 2, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(40, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ })
+ .join();
+
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(i, process_info.copied_bytes);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(40, process_info.total_bytes);
+ }
+ for i in 1..9 {
+ let process_info: TransitProcess = rx.recv().unwrap();
+ assert_eq!(i + 8, process_info.copied_bytes);
+ assert_eq!(i, process_info.file_bytes_copied);
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(40, process_info.total_bytes);
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_copy_with_progress_source_not_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_source_not_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ assert!(!dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(!dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(!sub.0.exists());
+ assert!(!sub.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file1.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let options = dir::CopyOptions::new();
+ match copy_items_with_progress(&from_paths, &path_to, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => {}
+ },
+ };
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_not_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_not_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ match copy_items_with_progress(&from_paths, &path_to, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!(format!("{}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_copy_with_progress_exist_skip_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_exist_overwrite_and_skip_exist() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_overwrite_and_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_using_first_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_first_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1"));
+ let d2_level_2 = (
+ d_level_1.0.join("d2_level_2"),
+ d_level_1.1.join("d2_level_2"),
+ );
+ let d2_level_3 = (
+ d_level_2.0.join("d2_level_3"),
+ d_level_2.1.join("d2_level_3"),
+ );
+ let d2_level_4 = (
+ d_level_3.0.join("d2_level_4"),
+ d_level_3.1.join("d2_level_4"),
+ );
+ let d2_level_5 = (
+ d_level_4.0.join("d2_level_5"),
+ d_level_4.1.join("d2_level_5"),
+ );
+
+ let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ let file21 = (
+ d2_level_1.0.join("file21.txt"),
+ d2_level_1.1.join("file21.txt"),
+ );
+ let file22 = (
+ d2_level_2.0.join("file22.txt"),
+ d2_level_2.1.join("file22.txt"),
+ );
+ let file23 = (
+ d2_level_3.0.join("file23.txt"),
+ d2_level_3.1.join("file23.txt"),
+ );
+ let file24 = (
+ d2_level_4.0.join("file24.txt"),
+ d2_level_4.1.join("file24.txt"),
+ );
+ let file25 = (
+ d2_level_5.0.join("file25.txt"),
+ d2_level_5.1.join("file25.txt"),
+ );
+
+ let file31 = (
+ d3_level_1.0.join("file31.txt"),
+ d3_level_1.1.join("file31.txt"),
+ );
+
+ dir::create_all(&d_level_1.0, true).unwrap();
+ dir::create_all(&d_level_2.0, true).unwrap();
+ dir::create_all(&d_level_3.0, true).unwrap();
+ dir::create_all(&d_level_4.0, true).unwrap();
+ dir::create_all(&d_level_5.0, true).unwrap();
+ dir::create_all(&path_to, true).unwrap();
+
+ dir::create_all(&d2_level_1.0, true).unwrap();
+ dir::create_all(&d2_level_2.0, true).unwrap();
+ dir::create_all(&d2_level_3.0, true).unwrap();
+ dir::create_all(&d2_level_4.0, true).unwrap();
+ dir::create_all(&d2_level_5.0, true).unwrap();
+
+ dir::create_all(&d3_level_1.0, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d2_level_1.0.exists());
+ assert!(d2_level_2.0.exists());
+ assert!(d2_level_3.0.exists());
+ assert!(d2_level_4.0.exists());
+ assert!(d2_level_5.0.exists());
+
+ assert!(d3_level_1.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(!d2_level_1.1.exists());
+ assert!(!d2_level_2.1.exists());
+ assert!(!d2_level_3.1.exists());
+ assert!(!d2_level_4.1.exists());
+ assert!(!d2_level_5.1.exists());
+
+ assert!(!d3_level_1.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file21.0, "2content1").unwrap();
+ fs_extra::file::write_all(&file22.0, "2content2").unwrap();
+ fs_extra::file::write_all(&file23.0, "2content3").unwrap();
+ fs_extra::file::write_all(&file24.0, "2content4").unwrap();
+ fs_extra::file::write_all(&file25.0, "2content5").unwrap();
+
+ fs_extra::file::write_all(&file31.0, "3content1").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(!file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(!file31.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.depth = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(d_level_1.0.as_path());
+ from_paths.push(d2_level_1.0.as_path());
+ from_paths.push(d3_level_1.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(26, result);
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(file31.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file21.0, &file21.1));
+ assert!(files_eq(&file31.0, &file31.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_using_four_levels() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_using_four_levels");
+ let path_to = test_dir.join("out");
+ let d_level_1 = (test_dir.join("d_level_1"), path_to.join("d_level_1"));
+ let d_level_2 = (d_level_1.0.join("d_level_2"), d_level_1.1.join("d_level_2"));
+ let d_level_3 = (d_level_2.0.join("d_level_3"), d_level_2.1.join("d_level_3"));
+ let d_level_4 = (d_level_3.0.join("d_level_4"), d_level_3.1.join("d_level_4"));
+ let d_level_5 = (d_level_4.0.join("d_level_5"), d_level_4.1.join("d_level_5"));
+
+ let d2_level_1 = (test_dir.join("d2_level_1"), path_to.join("d2_level_1"));
+ let d2_level_2 = (
+ d_level_1.0.join("d2_level_2"),
+ d_level_1.1.join("d2_level_2"),
+ );
+ let d2_level_3 = (
+ d_level_2.0.join("d2_level_3"),
+ d_level_2.1.join("d2_level_3"),
+ );
+ let d2_level_4 = (
+ d_level_3.0.join("d2_level_4"),
+ d_level_3.1.join("d2_level_4"),
+ );
+ let d2_level_5 = (
+ d_level_4.0.join("d2_level_5"),
+ d_level_4.1.join("d2_level_5"),
+ );
+
+ let d3_level_1 = (test_dir.join("d3_level_1"), path_to.join("d3_level_1"));
+
+ let file1 = (d_level_1.0.join("file1.txt"), d_level_1.1.join("file1.txt"));
+ let file2 = (d_level_2.0.join("file2.txt"), d_level_2.1.join("file2.txt"));
+ let file3 = (d_level_3.0.join("file3.txt"), d_level_3.1.join("file3.txt"));
+ let file4 = (d_level_4.0.join("file4.txt"), d_level_4.1.join("file4.txt"));
+ let file5 = (d_level_5.0.join("file5.txt"), d_level_5.1.join("file5.txt"));
+
+ let file21 = (
+ d2_level_1.0.join("file21.txt"),
+ d2_level_1.1.join("file21.txt"),
+ );
+ let file22 = (
+ d2_level_2.0.join("file22.txt"),
+ d2_level_2.1.join("file22.txt"),
+ );
+ let file23 = (
+ d2_level_3.0.join("file23.txt"),
+ d2_level_3.1.join("file23.txt"),
+ );
+ let file24 = (
+ d2_level_4.0.join("file24.txt"),
+ d2_level_4.1.join("file24.txt"),
+ );
+ let file25 = (
+ d2_level_5.0.join("file25.txt"),
+ d2_level_5.1.join("file25.txt"),
+ );
+
+ let file31 = (
+ d3_level_1.0.join("file31.txt"),
+ d3_level_1.1.join("file31.txt"),
+ );
+
+ dir::create_all(&d_level_1.0, true).unwrap();
+ dir::create_all(&d_level_2.0, true).unwrap();
+ dir::create_all(&d_level_3.0, true).unwrap();
+ dir::create_all(&d_level_4.0, true).unwrap();
+ dir::create_all(&d_level_5.0, true).unwrap();
+ dir::create_all(&path_to, true).unwrap();
+
+ dir::create_all(&d2_level_1.0, true).unwrap();
+ dir::create_all(&d2_level_2.0, true).unwrap();
+ dir::create_all(&d2_level_3.0, true).unwrap();
+ dir::create_all(&d2_level_4.0, true).unwrap();
+ dir::create_all(&d2_level_5.0, true).unwrap();
+
+ dir::create_all(&d3_level_1.0, true).unwrap();
+
+ assert!(path_to.exists());
+ assert!(d_level_1.0.exists());
+ assert!(d_level_2.0.exists());
+ assert!(d_level_3.0.exists());
+ assert!(d_level_4.0.exists());
+ assert!(d_level_5.0.exists());
+
+ assert!(d2_level_1.0.exists());
+ assert!(d2_level_2.0.exists());
+ assert!(d2_level_3.0.exists());
+ assert!(d2_level_4.0.exists());
+ assert!(d2_level_5.0.exists());
+
+ assert!(d3_level_1.0.exists());
+
+ assert!(!d_level_1.1.exists());
+ assert!(!d_level_2.1.exists());
+ assert!(!d_level_3.1.exists());
+ assert!(!d_level_4.1.exists());
+ assert!(!d_level_5.1.exists());
+
+ assert!(!d2_level_1.1.exists());
+ assert!(!d2_level_2.1.exists());
+ assert!(!d2_level_3.1.exists());
+ assert!(!d2_level_4.1.exists());
+ assert!(!d2_level_5.1.exists());
+
+ assert!(!d3_level_1.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file21.0, "2content1").unwrap();
+ fs_extra::file::write_all(&file22.0, "2content2").unwrap();
+ fs_extra::file::write_all(&file23.0, "2content3").unwrap();
+ fs_extra::file::write_all(&file24.0, "2content4").unwrap();
+ fs_extra::file::write_all(&file25.0, "2content5").unwrap();
+
+ fs_extra::file::write_all(&file31.0, "3content1").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(!file21.1.exists());
+ assert!(!file22.1.exists());
+ assert!(!file23.1.exists());
+ assert!(!file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(!file31.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.depth = 4;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(d_level_1.0.as_path());
+ from_paths.push(d2_level_1.0.as_path());
+ from_paths.push(d3_level_1.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+
+ let result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(77, result);
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+
+ assert!(file21.0.exists());
+ assert!(file22.0.exists());
+ assert!(file23.0.exists());
+ assert!(file24.0.exists());
+ assert!(file25.0.exists());
+
+ assert!(file31.0.exists());
+
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ assert!(file21.1.exists());
+ assert!(file22.1.exists());
+ assert!(file23.1.exists());
+ assert!(file24.1.exists());
+ assert!(!file25.1.exists());
+
+ assert!(file31.1.exists());
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file21.0, &file21.1));
+ assert!(files_eq(&file31.0, &file31.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_copy_with_progress_content_only_opton() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_content_only_opton");
+ let path_to = test_dir.join("out");
+
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ let mut options = dir::CopyOptions::new();
+ options.content_only = true;
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ match copy_items_with_progress(&vec![&file1.0], &file1.1, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::Other => {}
+ _ => panic!(format!("wrong error {}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_move_work() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_work");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(!sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ let result = move_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+}
+
+#[test]
+fn it_move_source_not_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_source_not_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ assert!(!dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(!dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(!sub.0.exists());
+ assert!(!sub.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file1.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ match move_items(&from_paths, &path_to, &options) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => {}
+ },
+ };
+}
+
+#[test]
+fn it_move_exist_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ let result = move_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+}
+
+#[test]
+fn it_move_exist_not_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_not_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ match move_items(&from_paths, &path_to, &options) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!(format!("{}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_move_exist_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_skip");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.skip_exist = true;
+ let result = move_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(16, result);
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!file2.0.exists());
+ assert!(!files_eq(&file3.0, &file3.1));
+ assert!(!files_eq(&file4.0, &file4.1));
+ assert!(!file5.0.exists());
+}
+
+#[test]
+fn it_move_exist_overwrite_and_skip_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_exist_overwrite_and_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ let result = move_items(&from_paths, &path_to, &options).unwrap();
+
+ assert_eq!(40, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+}
+#[test]
+fn it_move_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_content_only_option");
+ let path_to = test_dir.join("out");
+
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ let mut options = dir::CopyOptions::new();
+ options.content_only = true;
+ match move_items(&vec![&file1.0], &file1.1, &options) {
+ Err(err) => match err.kind {
+ ErrorKind::Other => {
+ assert_eq!(1, 1);
+ }
+ _ => {
+ panic!(format!("wrong error {}", err.to_string()));
+ }
+ },
+ Ok(_) => {
+ panic!("should be error");
+ }
+ }
+}
+
+#[test]
+fn it_move_progress_work() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_progress_work");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(!sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content22").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(!file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(!file3.1.exists());
+ assert!(!file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let options = dir::CopyOptions::new();
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(41, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+ })
+ .join();
+
+ loop {
+ match rx.try_recv() {
+ Ok(process_info) => {
+ if process_info.file_name == "file2.txt" {
+ assert_eq!(9, process_info.file_total_bytes);
+ assert_eq!(41, process_info.total_bytes);
+ } else if process_info.file_name == "file1.txt" {
+ assert_eq!(8, process_info.file_total_bytes);
+ assert_eq!(41, process_info.total_bytes);
+ }
+ }
+ Err(TryRecvError::Disconnected) => {
+ break;
+ }
+ Err(TryRecvError::Empty) => {}
+ }
+ }
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+}
+
+#[test]
+fn it_move_with_progress_source_not_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_source_not_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ assert!(!dir1.0.exists());
+ assert!(!dir1.1.exists());
+ assert!(!dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(!sub.0.exists());
+ assert!(!sub.1.exists());
+
+ assert!(!file1.0.exists());
+ assert!(!file1.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let options = dir::CopyOptions::new();
+ match move_items_with_progress(&from_paths, &path_to, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::NotFound => {}
+ _ => {}
+ },
+ };
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_not_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_not_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let options = dir::CopyOptions::new();
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ match move_items_with_progress(&from_paths, &path_to, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::AlreadyExists => {}
+ _ => panic!(format!("{}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_move_with_progress_exist_skip_exist() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+ file::write_all(&file5.1, "old content5").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.skip_exist = true;
+ options.overwrite = false;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(8, result);
+ assert!(file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+ assert!(!files_eq(&file1.0, &file1.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_move_with_progress_exist_overwrite_and_skip_exist() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_move_with_progress_exist_overwrite_and_skip_exist");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ match dir::create_all(&path_to, true) {
+ Ok(_) => {}
+ Err(_) => {}
+ };
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(!dir2.1.exists());
+ assert!(sub.0.exists());
+ assert!(sub.1.exists());
+
+ file::write_all(&file1.0, "content1").unwrap();
+ file::write_all(&file2.0, "content2").unwrap();
+ file::write_all(&file3.0, "content3").unwrap();
+ file::write_all(&file4.0, "content4").unwrap();
+ file::write_all(&file5.0, "content5").unwrap();
+
+ file::write_all(&file1.1, "old content1").unwrap();
+ file::write_all(&file3.1, "old content3").unwrap();
+ file::write_all(&file4.1, "old content4").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(!file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(!file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ options.overwrite = true;
+ options.skip_exist = true;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let func_test = |process_info: TransitProcess| {
+ tx.send(process_info).unwrap();
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ let result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+
+ assert_eq!(40, result);
+ assert!(!file1.0.exists());
+ assert!(!file2.0.exists());
+ assert!(!file3.0.exists());
+ assert!(!file4.0.exists());
+ assert!(!file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+
+ match rx.recv() {
+ Err(_) => panic!("Errors should not be!"),
+ _ => {}
+ }
+}
+
+#[test]
+fn it_move_with_progress_content_only_option() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_content_only_option");
+ let path_to = test_dir.join("out");
+
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+
+ let mut options = dir::CopyOptions::new();
+ options.content_only = true;
+ let func_test = |process_info: TransitProcess| {
+ println!("{}", process_info.total_bytes);
+ dir::TransitProcessResult::ContinueOrAbort
+ };
+ match move_items_with_progress(&vec![&file1.0], &file1.1, &options, func_test) {
+ Ok(_) => panic!("Should be a error!"),
+ Err(err) => match err.kind {
+ ErrorKind::Other => {}
+ _ => panic!(format!("wrong error {}", err.to_string())),
+ },
+ };
+}
+
+#[test]
+fn it_remove_work() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_remove_work");
+ let dir1 = test_dir.join("dir1");
+ let dir2 = test_dir.join("dir2");
+ let sub = dir1.join("sub");
+ let file1 = test_dir.join("file1.txt");
+ let file2 = test_dir.join("file2.txt");
+ let file3 = dir1.join("file3.txt");
+ let file4 = sub.join("file4.txt");
+ let file5 = dir2.join("file5.txt");
+
+ dir::create_all(&dir1, true).unwrap();
+ dir::create_all(&dir2, true).unwrap();
+ dir::create_all(&sub, true).unwrap();
+
+ assert!(dir1.exists());
+ assert!(dir2.exists());
+ assert!(sub.exists());
+
+ file::write_all(&file1, "content1").unwrap();
+ file::write_all(&file2, "content2").unwrap();
+ file::write_all(&file3, "content3").unwrap();
+ file::write_all(&file4, "content4").unwrap();
+ file::write_all(&file5, "content5").unwrap();
+
+ assert!(file1.exists());
+ assert!(file2.exists());
+ assert!(file3.exists());
+ assert!(file4.exists());
+ assert!(file5.exists());
+
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.as_path());
+ from_paths.push(dir2.as_path());
+ from_paths.push(file1.as_path());
+ from_paths.push(file2.as_path());
+
+ remove_items(&from_paths).unwrap();
+ assert!(!file1.exists());
+ assert!(!file2.exists());
+ assert!(!file3.exists());
+ assert!(!file4.exists());
+ assert!(!file5.exists());
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::Overwrite;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(5, count_exist_files);
+
+ assert_eq!(40, result);
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_overwrite_all() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_overwrite_all");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::OverwriteAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(40, result);
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(compare_dir(&dir1.0, &path_to));
+ assert!(compare_dir(&dir2.0, &path_to));
+ assert!(files_eq(&file1.0, &file1.1));
+ assert!(files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::Skip;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(5, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(!compare_dir(&dir1.0, &path_to));
+ assert!(!compare_dir(&dir2.0, &path_to));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_skip_all() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_skip_all");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::SkipAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(!compare_dir(&dir1.0, &path_to));
+ assert!(!compare_dir(&dir2.0, &path_to));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_copy_with_progress_exist_user_decide_retry() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_copy_with_progress_exist_user_decide_retry");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ if count_exist_files == 3 || count_exist_files > 6 {
+ result = dir::TransitProcessResult::Skip;
+ } else {
+ result = dir::TransitProcessResult::Retry;
+ }
+
+ count_exist_files += 1;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = copy_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(11, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.0.exists());
+ assert!(dir2.1.exists());
+ assert!(!compare_dir(&dir1.0, &path_to));
+ assert!(!compare_dir(&dir2.0, &path_to));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_overwrite() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::Overwrite;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(5, count_exist_files);
+
+ assert_eq!(40, result);
+ assert!(!dir1.0.exists());
+ assert!(!dir2.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_overwrite_all() {
+ let test_dir =
+ Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_overwrite_all");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::OverwriteAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(40, result);
+ assert!(!dir1.0.exists());
+ assert!(!dir2.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_skip() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::Skip;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(5, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir2.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_skip_all() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_skip_all");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ count_exist_files += 1;
+ result = dir::TransitProcessResult::SkipAll;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(1, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir2.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.1.exists());
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}
+
+#[test]
+fn it_move_with_progress_exist_user_decide_retry() {
+ let test_dir = Path::new(TEST_FOLDER).join("it_move_with_progress_exist_user_decide_retry");
+ let path_to = test_dir.join("out");
+ let dir1 = (test_dir.join("dir1"), path_to.join("dir1"));
+ let dir2 = (test_dir.join("dir2"), path_to.join("dir2"));
+ let sub = (dir1.0.join("sub"), dir1.1.join("sub"));
+ let file1 = (test_dir.join("file1.txt"), path_to.join("file1.txt"));
+ let file2 = (test_dir.join("file2.txt"), path_to.join("file2.txt"));
+ let file3 = (dir1.0.join("file3.txt"), dir1.1.join("file3.txt"));
+ let file4 = (sub.0.join("file4.txt"), sub.1.join("file4.txt"));
+ let file5 = (dir2.0.join("file5.txt"), dir2.1.join("file5.txt"));
+
+ dir::create_all(&dir1.0, true).unwrap();
+ dir::create_all(&dir1.1, true).unwrap();
+ dir::create_all(&dir2.0, true).unwrap();
+ dir::create_all(&dir2.1, true).unwrap();
+ dir::create_all(&sub.0, true).unwrap();
+ dir::create_all(&sub.1, true).unwrap();
+
+ assert!(&dir1.0.exists());
+ assert!(&dir1.1.exists());
+ assert!(&dir2.0.exists());
+ assert!(&dir2.1.exists());
+ assert!(&sub.0.exists());
+ assert!(&sub.1.exists());
+
+ fs_extra::file::write_all(&file1.0, "content1").unwrap();
+ fs_extra::file::write_all(&file2.0, "content2").unwrap();
+ fs_extra::file::write_all(&file3.0, "content3").unwrap();
+ fs_extra::file::write_all(&file4.0, "content4").unwrap();
+ fs_extra::file::write_all(&file5.0, "content5").unwrap();
+
+ fs_extra::file::write_all(&file1.1, "old content11").unwrap();
+ fs_extra::file::write_all(&file2.1, "old content12").unwrap();
+ fs_extra::file::write_all(&file3.1, "old content13").unwrap();
+ fs_extra::file::write_all(&file4.1, "old content14").unwrap();
+ fs_extra::file::write_all(&file5.1, "old content15").unwrap();
+
+ assert!(file1.0.exists());
+ assert!(file2.0.exists());
+ assert!(file3.0.exists());
+ assert!(file4.0.exists());
+ assert!(file5.0.exists());
+ assert!(file1.1.exists());
+ assert!(file2.1.exists());
+ assert!(file3.1.exists());
+ assert!(file4.1.exists());
+ assert!(file5.1.exists());
+
+ let mut options = dir::CopyOptions::new();
+ assert!(!compare_dir(&dir1.0, &dir1.1));
+ assert!(!compare_dir(&dir2.0, &dir2.1));
+ assert!(!files_eq(&file1.0, &file1.1));
+ assert!(!files_eq(&file2.0, &file2.1));
+ options.buffer_size = 1;
+ let (tx, rx) = mpsc::channel();
+ let result = thread::spawn(move || {
+ let mut count_exist_files = 0;
+ let mut from_paths = Vec::new();
+ from_paths.push(dir1.0.as_path());
+ from_paths.push(dir2.0.as_path());
+ from_paths.push(file1.0.as_path());
+ from_paths.push(file2.0.as_path());
+
+ let result: u64;
+ {
+ let func_test = |process_info: TransitProcess| {
+ let result: dir::TransitProcessResult;
+ match process_info.state {
+ dir::TransitState::Exists => {
+ if count_exist_files == 3 || count_exist_files > 6 {
+ result = dir::TransitProcessResult::Skip;
+ } else {
+ result = dir::TransitProcessResult::Retry;
+ }
+
+ count_exist_files += 1;
+ tx.send(process_info).unwrap();
+ }
+ _ => result = dir::TransitProcessResult::Abort,
+ };
+ result
+ };
+
+ result = move_items_with_progress(&from_paths, &path_to, &options, func_test).unwrap();
+ }
+ assert_eq!(11, count_exist_files);
+
+ assert_eq!(0, result);
+ assert!(dir1.0.exists());
+ assert!(dir2.0.exists());
+ assert!(dir1.1.exists());
+ assert!(dir2.1.exists());
+ })
+ .join();
+
+ match result {
+ Ok(_) => {}
+ Err(err) => panic!(err),
+ }
+ rx.try_recv().unwrap();
+}