]>
git.proxmox.com Git - rustc.git/blob - vendor/fs_extra/src/lib.rs
2 ($text
:expr
, $kind
:expr
) => {
3 return Err(Error
::new($kind
, $text
));
7 err
!($text
, ErrorKind
::Other
)
11 /// The error type for fs_extra operations with files and folder.
13 /// This module include extra methods for works with files.
15 /// One of the distinguishing features is receipt information
16 /// about process work with files.
20 /// use std::path::Path;
21 /// use std::{thread, time};
22 /// use std::sync::mpsc::{self, TryRecvError};
24 /// extern crate fs_extra;
25 /// use fs_extra::file::*;
26 /// use fs_extra::error::*;
28 /// fn example_copy() -> Result<()> {
29 /// let path_from = Path::new("./temp");
30 /// let path_to = path_from.join("out");
31 /// let test_file = (path_from.join("test_file.txt"), path_to.join("test_file.txt"));
34 /// fs_extra::dir::create_all(&path_from, true)?;
35 /// fs_extra::dir::create_all(&path_to, true)?;
37 /// write_all(&test_file.0, "test_data")?;
38 /// assert!(test_file.0.exists());
39 /// assert!(!test_file.1.exists());
42 /// let options = CopyOptions {
44 /// ..Default::default()
46 /// let (tx, rx) = mpsc::channel();
47 /// thread::spawn(move || {
48 /// let handler = |process_info: TransitProcess| {
49 /// tx.send(process_info).unwrap();
50 /// thread::sleep(time::Duration::from_millis(500));
52 /// copy_with_progress(&test_file.0, &test_file.1, &options, handler).unwrap();
53 /// assert!(test_file.0.exists());
54 /// assert!(test_file.1.exists());
58 /// match rx.try_recv() {
59 /// Ok(process_info) => {
60 /// println!("{} of {} bytes",
61 /// process_info.copied_bytes,
62 /// process_info.total_bytes);
64 /// Err(TryRecvError::Disconnected) => {
65 /// println!("finished");
68 /// Err(TryRecvError::Empty) => {}
83 /// This module include extra methods for works with directories.
85 /// One of the distinguishing features is receipt information
86 /// about process work with directories and recursion operations.
90 /// use std::path::Path;
91 /// use std::{thread, time};
92 /// use std::sync::mpsc::{self, TryRecvError};
94 /// extern crate fs_extra;
95 /// use fs_extra::dir::*;
96 /// use fs_extra::error::*;
98 /// fn example_copy() -> Result<()> {
100 /// let path_from = Path::new("./temp");
101 /// let path_to = path_from.join("out");
102 /// let test_folder = path_from.join("test_folder");
103 /// let dir = test_folder.join("dir");
104 /// let sub = dir.join("sub");
105 /// let file1 = dir.join("file1.txt");
106 /// let file2 = sub.join("file2.txt");
108 /// create_all(&sub, true)?;
109 /// create_all(&path_to, true)?;
110 /// fs_extra::file::write_all(&file1, "content1")?;
111 /// fs_extra::file::write_all(&file2, "content2")?;
113 /// assert!(dir.exists());
114 /// assert!(sub.exists());
115 /// assert!(file1.exists());
116 /// assert!(file2.exists());
119 /// let options = CopyOptions {
121 /// ..Default::default(),
123 /// let (tx, rx) = mpsc::channel();
124 /// thread::spawn(move || {
125 /// let handler = |process_info: TransitProcess| {
126 /// tx.send(process_info).unwrap();
127 /// thread::sleep(time::Duration::from_millis(500));
129 /// copy_with_progress(&test_folder, &path_to, &options, handler).unwrap();
133 /// match rx.try_recv() {
134 /// Ok(process_info) => {
135 /// println!("{} of {} bytes",
136 /// process_info.copied_bytes,
137 /// process_info.total_bytes);
139 /// Err(TryRecvError::Disconnected) => {
140 /// println!("finished");
143 /// Err(TryRecvError::Empty) => {}
159 /// Copies list directories and files to another place using recursive method. This function will
160 /// also copy the permission bits of the original files to destionation files (not for
165 /// This function will return an error in the following situations, but is not limited to just
168 /// * List `from` contains file or directory does not exist.
170 /// * List `from` contains file or directory with invalid name.
172 /// * The current process does not have the permission rights to access to file from `lists from` or
178 /// extern crate fs_extra;
179 /// use fs_extra::dir::copy;
181 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
183 /// // copy dir1 and file1.txt to target/dir1 and target/file1.txt
184 /// let mut from_paths = Vec::new();
185 /// from_paths.push("source/dir1");
186 /// from_paths.push("source/file.txt");
187 /// copy_items(&from_paths, "target", &options)?;
190 pub fn copy_items
<P
, Q
>(from
: &[P
], to
: Q
, options
: &dir
::CopyOptions
) -> Result
<u64>
195 let mut result
: u64 = 0;
196 if options
.content_only
{
198 "Options 'content_only' not acccess for copy_items function",
203 let item
= item
.as_ref();
205 result
+= dir
::copy(item
, &to
, options
)?
;
207 if let Some(file_name
) = item
.file_name() {
208 if let Some(file_name
) = file_name
.to_str() {
209 let file_options
= file
::CopyOptions
{
210 overwrite
: options
.overwrite
,
211 skip_exist
: options
.skip_exist
,
214 result
+= file
::copy(item
, to
.as_ref().join(file_name
), &file_options
)?
;
217 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
225 /// A structure which include information about the current status of the copy or move directory.
226 pub struct TransitProcess
{
227 /// Copied bytes on this time for folder
228 pub copied_bytes
: u64,
229 /// All the bytes which should to copy or move (dir size).
230 pub total_bytes
: u64,
231 /// Copied bytes on this time for file.
232 pub file_bytes_copied
: u64,
233 /// Size current copied file.
234 pub file_total_bytes
: u64,
235 /// Name current copied file.
236 pub file_name
: String
,
237 /// Name current copied folder.
238 pub dir_name
: String
,
240 pub state
: dir
::TransitState
,
243 impl Clone
for TransitProcess
{
244 fn clone(&self) -> TransitProcess
{
246 copied_bytes
: self.copied_bytes
,
247 total_bytes
: self.total_bytes
,
248 file_bytes_copied
: self.file_bytes_copied
,
249 file_total_bytes
: self.file_total_bytes
,
250 file_name
: self.file_name
.clone(),
251 dir_name
: self.dir_name
.clone(),
252 state
: self.state
.clone(),
257 /// Copies list directories and files to another place using recursive method, with recept
258 /// information about process. This function will also copy the permission bits of the
259 /// original files to destionation files (not for directories).
263 /// This function will return an error in the following situations, but is not limited to just
266 /// * List `from` contains file or directory does not exist.
268 /// * List `from` contains file or directory with invalid name.
270 /// * The current process does not have the permission rights to access to file from `lists from` or
276 /// extern crate fs_extra;
277 /// use fs_extra::dir::copy;
279 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
280 /// let handle = |process_info: TransitProcess| {
281 /// println!("{}", process_info.total_bytes);
282 /// fs_extra::dir::TransitProcessResult::ContinueOrAbort
284 /// // copy dir1 and file1.txt to target/dir1 and target/file1.txt
285 /// let mut from_paths = Vec::new();
286 /// from_paths.push("source/dir1");
287 /// from_paths.push("source/file.txt");
288 /// copy_items_with_progress(&from_paths, "target", &options, handle)?;
291 pub fn copy_items_with_progress
<P
, Q
, F
>(
294 options
: &dir
::CopyOptions
,
295 mut progress_handler
: F
,
300 F
: FnMut(TransitProcess
) -> dir
::TransitProcessResult
,
302 if options
.content_only
{
304 "Options 'content_only' not acccess for copy_items_with_progress function",
308 let mut total_size
= 0;
309 let mut list_paths
= Vec
::new();
311 let item
= item
.as_ref();
312 total_size
+= dir
::get_size(item
)?
;
313 list_paths
.push(item
);
316 let mut result
: u64 = 0;
317 let mut info_process
= TransitProcess
{
319 total_bytes
: total_size
,
320 file_bytes_copied
: 0,
322 file_name
: String
::new(),
323 dir_name
: String
::new(),
324 state
: dir
::TransitState
::Normal
,
327 let mut options
= options
.clone();
328 for item
in list_paths
{
330 if let Some(dir_name
) = item
.components().last() {
331 if let Ok(dir_name
) = dir_name
.as_os_str().to_os_string().into_string() {
332 info_process
.dir_name
= dir_name
;
334 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
337 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
340 let copied_bytes
= result
;
341 let dir_options
= options
.clone();
342 let handler
= |info
: dir
::TransitProcess
| {
343 info_process
.copied_bytes
= copied_bytes
+ info
.copied_bytes
;
344 info_process
.state
= info
.state
;
345 let result
= progress_handler(info_process
.clone());
347 dir
::TransitProcessResult
::OverwriteAll
=> options
.overwrite
= true,
348 dir
::TransitProcessResult
::SkipAll
=> options
.skip_exist
= true,
353 result
+= dir
::copy_with_progress(item
, &to
, &dir_options
, handler
)?
;
355 let mut file_options
= file
::CopyOptions
{
356 overwrite
: options
.overwrite
,
357 skip_exist
: options
.skip_exist
,
358 buffer_size
: options
.buffer_size
,
362 if let Some(file_name
) = item
.file_name() {
363 if let Some(file_name
) = file_name
.to_str() {
364 info_process
.file_name
= file_name
.to_string();
366 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
369 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
372 info_process
.file_bytes_copied
= 0;
373 info_process
.file_total_bytes
= item
.metadata()?
.len();
375 let copied_bytes
= result
;
376 let file_name
= to
.as_ref().join(info_process
.file_name
.clone());
379 let mut result_copy
: Result
<u64>;
382 let handler
= |info
: file
::TransitProcess
| {
383 info_process
.copied_bytes
= copied_bytes
+ info
.copied_bytes
;
384 info_process
.file_bytes_copied
= info
.copied_bytes
;
385 progress_handler(info_process
.clone());
388 file
::copy_with_progress(item
, &file_name
, &file_options
, handler
);
395 Err(err
) => match err
.kind
{
396 ErrorKind
::AlreadyExists
=> {
397 let mut info_process
= info_process
.clone();
398 info_process
.state
= dir
::TransitState
::Exists
;
399 let user_decide
= progress_handler(info_process
);
401 dir
::TransitProcessResult
::Overwrite
=> {
402 file_options
.overwrite
= true;
404 dir
::TransitProcessResult
::OverwriteAll
=> {
405 file_options
.overwrite
= true;
406 options
.overwrite
= true;
408 dir
::TransitProcessResult
::Skip
=> {
409 file_options
.skip_exist
= true;
411 dir
::TransitProcessResult
::SkipAll
=> {
412 file_options
.skip_exist
= true;
413 options
.skip_exist
= true;
415 dir
::TransitProcessResult
::Retry
=> {}
416 dir
::TransitProcessResult
::ContinueOrAbort
=> {
417 let err_msg
= err
.to_string();
418 err
!(err_msg
.as_str(), err
.kind
)
420 dir
::TransitProcessResult
::Abort
=> {
421 let err_msg
= err
.to_string();
422 err
!(err_msg
.as_str(), err
.kind
)
426 ErrorKind
::PermissionDenied
=> {
427 let mut info_process
= info_process
.clone();
428 info_process
.state
= dir
::TransitState
::Exists
;
429 let user_decide
= progress_handler(info_process
);
431 dir
::TransitProcessResult
::Overwrite
=> {
432 err
!("Overwrite denied for this situation!", ErrorKind
::Other
);
434 dir
::TransitProcessResult
::OverwriteAll
=> {
435 err
!("Overwrite denied for this situation!", ErrorKind
::Other
);
437 dir
::TransitProcessResult
::Skip
=> {
438 file_options
.skip_exist
= true;
440 dir
::TransitProcessResult
::SkipAll
=> {
441 file_options
.skip_exist
= true;
442 options
.skip_exist
= true;
444 dir
::TransitProcessResult
::Retry
=> {}
445 dir
::TransitProcessResult
::ContinueOrAbort
=> {
446 let err_msg
= err
.to_string();
447 err
!(err_msg
.as_str(), err
.kind
)
449 dir
::TransitProcessResult
::Abort
=> {
450 let err_msg
= err
.to_string();
451 err
!(err_msg
.as_str(), err
.kind
)
456 let err_msg
= err
.to_string();
457 err
!(err_msg
.as_str(), err
.kind
)
468 /// Moves list directories and files to another place using recursive method. This function will
469 /// also copy the permission bits of the original files to destionation files (not for
474 /// This function will return an error in the following situations, but is not limited to just
477 /// * List `from` contains file or directory does not exist.
479 /// * List `from` contains file or directory with invalid name.
481 /// * The current process does not have the permission rights to access to file from `lists from` or
487 /// extern crate fs_extra;
488 /// use fs_extra::dir::copy;
490 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
492 /// // move dir1 and file1.txt to target/dir1 and target/file1.txt
493 /// let mut from_paths = Vec::new();
494 /// from_paths.push("source/dir1");
495 /// from_paths.push("source/file.txt");
496 /// move_items(&from_paths, "target", &options)?;
499 pub fn move_items
<P
, Q
>(from_items
: &[P
], to
: Q
, options
: &dir
::CopyOptions
) -> Result
<u64>
504 if options
.content_only
{
506 "Options 'content_only' not acccess for move_items function",
510 let mut total_size
= 0;
511 let mut list_paths
= Vec
::new();
512 for item
in from_items
{
513 let item
= item
.as_ref();
514 total_size
+= dir
::get_size(item
)?
;
515 list_paths
.push(item
);
519 let mut info_process
= TransitProcess
{
521 total_bytes
: total_size
,
522 file_bytes_copied
: 0,
524 file_name
: String
::new(),
525 dir_name
: String
::new(),
526 state
: dir
::TransitState
::Normal
,
529 for item
in list_paths
{
531 if let Some(dir_name
) = item
.components().last() {
532 if let Ok(dir_name
) = dir_name
.as_os_str().to_os_string().into_string() {
533 info_process
.dir_name
= dir_name
;
535 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
538 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
541 result
+= dir
::move_dir(item
, &to
, options
)?
;
543 let file_options
= file
::CopyOptions
{
544 overwrite
: options
.overwrite
,
545 skip_exist
: options
.skip_exist
,
546 buffer_size
: options
.buffer_size
,
550 if let Some(file_name
) = item
.file_name() {
551 if let Some(file_name
) = file_name
.to_str() {
552 info_process
.file_name
= file_name
.to_string();
554 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
557 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
560 info_process
.file_bytes_copied
= 0;
561 info_process
.file_total_bytes
= item
.metadata()?
.len();
563 let file_name
= to
.as_ref().join(info_process
.file_name
.clone());
564 result
+= file
::move_file(item
, &file_name
, &file_options
)?
;
571 /// Moves list directories and files to another place using recursive method, with recept
572 /// information about process. This function will also copy the permission bits of the
573 /// original files to destionation files (not for directories).
577 /// This function will return an error in the following situations, but is not limited to just
580 /// * List `from` contains file or directory does not exist.
582 /// * List `from` contains file or directory with invalid name.
584 /// * The current process does not have the permission rights to access to file from `lists from` or
590 /// extern crate fs_extra;
591 /// use fs_extra::dir::copy;
593 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
594 /// let handle = |process_info: TransitProcess| {
595 /// println!("{}", process_info.total_bytes);
596 /// fs_extra::dir::TransitProcessResult::ContinueOrAbort
598 /// // move dir1 and file1.txt to target/dir1 and target/file1.txt
599 /// let mut from_paths = Vec::new();
600 /// from_paths.push("source/dir1");
601 /// from_paths.push("source/file.txt");
602 /// move_items_with_progress(&from_paths, "target", &options, handle)?;
605 pub fn move_items_with_progress
<P
, Q
, F
>(
608 options
: &dir
::CopyOptions
,
609 mut progress_handler
: F
,
614 F
: FnMut(TransitProcess
) -> dir
::TransitProcessResult
,
616 if options
.content_only
{
618 "Options 'content_only' not acccess for move_items_with_progress function",
622 let mut total_size
= 0;
623 let mut list_paths
= Vec
::new();
624 for item
in from_items
{
625 let item
= item
.as_ref();
626 total_size
+= dir
::get_size(item
)?
;
627 list_paths
.push(item
);
631 let mut info_process
= TransitProcess
{
633 total_bytes
: total_size
,
634 file_bytes_copied
: 0,
636 file_name
: String
::new(),
637 dir_name
: String
::new(),
638 state
: dir
::TransitState
::Normal
,
640 let mut options
= options
.clone();
642 for item
in list_paths
{
644 if let Some(dir_name
) = item
.components().last() {
645 if let Ok(dir_name
) = dir_name
.as_os_str().to_os_string().into_string() {
646 info_process
.dir_name
= dir_name
;
648 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
651 err
!("Invalid folder from", ErrorKind
::InvalidFolder
);
654 let copied_bytes
= result
;
655 let dir_options
= options
.clone();
656 let handler
= |info
: dir
::TransitProcess
| {
657 info_process
.copied_bytes
= copied_bytes
+ info
.copied_bytes
;
658 info_process
.state
= info
.state
;
659 let result
= progress_handler(info_process
.clone());
661 dir
::TransitProcessResult
::OverwriteAll
=> options
.overwrite
= true,
662 dir
::TransitProcessResult
::SkipAll
=> options
.skip_exist
= true,
667 result
+= dir
::move_dir_with_progress(item
, &to
, &dir_options
, handler
)?
;
669 let mut file_options
= file
::CopyOptions
{
670 overwrite
: options
.overwrite
,
671 skip_exist
: options
.skip_exist
,
672 buffer_size
: options
.buffer_size
,
676 if let Some(file_name
) = item
.file_name() {
677 if let Some(file_name
) = file_name
.to_str() {
678 info_process
.file_name
= file_name
.to_string();
680 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
683 err
!("Invalid file name", ErrorKind
::InvalidFileName
);
686 info_process
.file_bytes_copied
= 0;
687 info_process
.file_total_bytes
= item
.metadata()?
.len();
689 let copied_bytes
= result
;
690 let file_name
= to
.as_ref().join(info_process
.file_name
.clone());
693 let mut result_copy
: Result
<u64>;
696 let handler
= |info
: file
::TransitProcess
| {
697 info_process
.copied_bytes
= copied_bytes
+ info
.copied_bytes
;
698 info_process
.file_bytes_copied
= info
.copied_bytes
;
699 progress_handler(info_process
.clone());
702 file
::move_file_with_progress(item
, &file_name
, &file_options
, handler
);
709 Err(err
) => match err
.kind
{
710 ErrorKind
::AlreadyExists
=> {
711 let mut info_process
= info_process
.clone();
712 info_process
.state
= dir
::TransitState
::Exists
;
713 let user_decide
= progress_handler(info_process
);
715 dir
::TransitProcessResult
::Overwrite
=> {
716 file_options
.overwrite
= true;
718 dir
::TransitProcessResult
::OverwriteAll
=> {
719 file_options
.overwrite
= true;
720 options
.overwrite
= true;
722 dir
::TransitProcessResult
::Skip
=> {
723 file_options
.skip_exist
= true;
725 dir
::TransitProcessResult
::SkipAll
=> {
726 file_options
.skip_exist
= true;
727 options
.skip_exist
= true;
729 dir
::TransitProcessResult
::Retry
=> {}
730 dir
::TransitProcessResult
::ContinueOrAbort
=> {
731 let err_msg
= err
.to_string();
732 err
!(err_msg
.as_str(), err
.kind
)
734 dir
::TransitProcessResult
::Abort
=> {
735 let err_msg
= err
.to_string();
736 err
!(err_msg
.as_str(), err
.kind
)
740 ErrorKind
::PermissionDenied
=> {
741 let mut info_process
= info_process
.clone();
742 info_process
.state
= dir
::TransitState
::Exists
;
743 let user_decide
= progress_handler(info_process
);
745 dir
::TransitProcessResult
::Overwrite
=> {
746 err
!("Overwrite denied for this situation!", ErrorKind
::Other
);
748 dir
::TransitProcessResult
::OverwriteAll
=> {
749 err
!("Overwrite denied for this situation!", ErrorKind
::Other
);
751 dir
::TransitProcessResult
::Skip
=> {
752 file_options
.skip_exist
= true;
754 dir
::TransitProcessResult
::SkipAll
=> {
755 file_options
.skip_exist
= true;
756 options
.skip_exist
= true;
758 dir
::TransitProcessResult
::Retry
=> {}
759 dir
::TransitProcessResult
::ContinueOrAbort
=> {
760 let err_msg
= err
.to_string();
761 err
!(err_msg
.as_str(), err
.kind
)
763 dir
::TransitProcessResult
::Abort
=> {
764 let err_msg
= err
.to_string();
765 err
!(err_msg
.as_str(), err
.kind
)
770 let err_msg
= err
.to_string();
771 err
!(err_msg
.as_str(), err
.kind
)
781 /// Removes list files or directories.
786 /// let mut from_paths = Vec::new();
787 /// from_paths.push("source/dir1");
788 /// from_paths.push("source/file.txt");
790 /// remove_items(&from_paths).unwrap();
793 pub fn remove_items
<P
>(from_items
: &[P
]) -> Result
<()>
797 for item
in from_items
{
798 let item
= item
.as_ref();