fs_extra-1.3.0/.cargo_vcs_info.json0000644000000001120000000000000126410ustar { "git": { "sha1": "1754296075e7cc4a25feaa876a3f4b9daccc0b98" } } fs_extra-1.3.0/Cargo.toml0000644000000020600000000000000106430ustar # 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 "] 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] fs_extra-1.3.0/Cargo.toml.orig000064400000000000000000000010720000000000000143040ustar 00000000000000[package] name = "fs_extra" version = "1.3.0" edition = "2018" description = "Expanding std::fs and std::io. Recursively copy folders with information about process and much more." license = "MIT" authors = ["Denis Kurilenko "] keywords = ["filesystem", "recursion", "copy", "dir", "file"] homepage = "https://github.com/webdesus/fs_extra" documentation = "https://docs.rs/fs_extra" repository = "https://github.com/webdesus/fs_extra" include = [ "**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md", ] [dependencies] fs_extra-1.3.0/LICENSE000064400000000000000000000020600000000000000124200ustar 00000000000000MIT 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. fs_extra-1.3.0/README.md000064400000000000000000000156040000000000000127020ustar 00000000000000# 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(); } ``` fs_extra-1.3.0/src/dir.rs000064400000000000000000001316100000000000000133320ustar 00000000000000use 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, /// List all folders and sub folders directory. pub directories: Vec, } /// 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, /// Collection directory entry with information. pub items: Vec>, } /// 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

( path: P, config: &HashSet, ) -> Result> where P: AsRef, { let path = path.as_ref(); let metadata = path.metadata()?; get_details_entry_with_meta(path, config, metadata) } fn get_details_entry_with_meta

( path: P, config: &HashSet, metadata: Metadata, ) -> Result> where P: AsRef, { 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

(path: P, config: &HashSet) -> Result where P: AsRef, { 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

(path: P, erase: bool) -> Result<()> where P: AsRef, { 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

(path: P, erase: bool) -> Result<()> where P: AsRef, { 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(from: P, to: Q, options: &CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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; 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

(path: P) -> Result where P: AsRef, { 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

(path: P, options: &DirOptions) -> Result where P: AsRef, { let mut depth = 0; if options.depth != 0 { depth = options.depth + 1; } _get_dir_content(path, depth) } fn _get_dir_content

(path: P, mut depth: u64) -> Result where P: AsRef, { 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

(path: P) -> Result where P: AsRef, { // 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( from: P, to: Q, options: &CopyOptions, mut progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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; 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(from: P, to: Q, options: &CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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; 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( from: P, to: Q, options: &CopyOptions, mut progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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; 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>(path: P) -> Result<()> { if path.as_ref().exists() { Ok(remove_dir_all(path)?) } else { Ok(()) } } fs_extra-1.3.0/src/error.rs000064400000000000000000000110660000000000000137070ustar 00000000000000use 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 = ::std::result::Result; /// 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 for Error { fn from(err: StripPrefixError) -> Error { Error::new( ErrorKind::StripPrefix(err), "StripPrefixError. Look inside for more details", ) } } impl From for Error { fn from(err: OsString) -> Error { Error::new( ErrorKind::OsString(err), "OsString. Look inside for more details", ) } } impl From 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()) } } fs_extra-1.3.0/src/file.rs000064400000000000000000000271000000000000000134710ustar 00000000000000use 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(from: P, to: Q, options: &CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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( from: P, to: Q, options: &CopyOptions, mut progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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(from: P, to: Q, options: &CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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( from: P, to: Q, options: &CopyOptions, progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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

(path: P) -> Result<()> where P: AsRef, { 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

(path: P) -> Result where P: AsRef, { 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

(path: P, content: &str) -> Result<()> where P: AsRef, { 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())?) } fs_extra-1.3.0/src/lib.rs000064400000000000000000000710010000000000000133170ustar 00000000000000macro_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(from: &[P], to: Q, options: &dir::CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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( from: &[P], to: Q, options: &dir::CopyOptions, mut progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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; 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(from_items: &[P], to: Q, options: &dir::CopyOptions) -> Result where P: AsRef, Q: AsRef, { 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( from_items: &[P], to: Q, options: &dir::CopyOptions, mut progress_handler: F, ) -> Result where P: AsRef, Q: AsRef, 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; 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

(from_items: &[P]) -> Result<()> where P: AsRef, { for item in from_items { let item = item.as_ref(); if item.is_dir() { dir::remove(item)?; } else { file::remove(item)? } } Ok(()) } fs_extra-1.3.0/tests/dir.rs000064400000000000000000004720370000000000000137200ustar 00000000000000use 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(file1: P, file2: Q) -> bool where P: AsRef, Q: AsRef, { 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(path_from: P, path_to: Q) -> bool where P: AsRef, Q: AsRef, { 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, Q: AsRef>( original: P, link: Q, ) -> std::io::Result<()> { std::os::unix::fs::symlink(original.as_ref(), link.as_ref()) } #[cfg(windows)] fn create_file_symlink, Q: AsRef>( 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(path_from: P, path_to: Q) -> bool where P: AsRef, Q: AsRef, { 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!"), _ => {} } } fs_extra-1.3.0/tests/file.rs000064400000000000000000001117720000000000000140550ustar 00000000000000// 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(file1: P, file2: Q) -> Result where P: AsRef, Q: AsRef, { 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()), } } fs_extra-1.3.0/tests/lib.rs000064400000000000000000004116470000000000000137100ustar 00000000000000use 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(file1: P, file2: Q) -> bool where P: AsRef, Q: AsRef, { 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(path_from: P, path_to: Q) -> bool where P: AsRef, Q: AsRef, { 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(); }