]> git.proxmox.com Git - rustc.git/blob - vendor/fs_extra/src/lib.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / fs_extra / src / lib.rs
1 macro_rules! err {
2 ($text:expr, $kind:expr) => {
3 return Err(Error::new($kind, $text));
4 };
5
6 ($text:expr) => {
7 err!($text, ErrorKind::Other)
8 };
9 }
10
11 /// The error type for fs_extra operations with files and folder.
12 pub mod error;
13 /// This module include extra methods for works with files.
14 ///
15 /// One of the distinguishing features is receipt information
16 /// about process work with files.
17 ///
18 /// # Example
19 /// ```rust,ignore
20 /// use std::path::Path;
21 /// use std::{thread, time};
22 /// use std::sync::mpsc::{self, TryRecvError};
23 ///
24 /// extern crate fs_extra;
25 /// use fs_extra::file::*;
26 /// use fs_extra::error::*;
27 ///
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"));
32 ///
33 ///
34 /// fs_extra::dir::create_all(&path_from, true)?;
35 /// fs_extra::dir::create_all(&path_to, true)?;
36 ///
37 /// write_all(&test_file.0, "test_data")?;
38 /// assert!(test_file.0.exists());
39 /// assert!(!test_file.1.exists());
40 ///
41 ///
42 /// let options = CopyOptions {
43 /// buffer_size: 1,
44 /// ..Default::default()
45 /// }
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));
51 /// };
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());
55 ///
56 /// });
57 /// loop {
58 /// match rx.try_recv() {
59 /// Ok(process_info) => {
60 /// println!("{} of {} bytes",
61 /// process_info.copied_bytes,
62 /// process_info.total_bytes);
63 /// }
64 /// Err(TryRecvError::Disconnected) => {
65 /// println!("finished");
66 /// break;
67 /// }
68 /// Err(TryRecvError::Empty) => {}
69 /// }
70 /// }
71 /// Ok(())
72 ///
73 /// }
74 ///
75 ///
76 /// fn main() {
77 /// example_copy();
78 ///
79 ///
80 /// ```
81 pub mod file;
82
83 /// This module include extra methods for works with directories.
84 ///
85 /// One of the distinguishing features is receipt information
86 /// about process work with directories and recursion operations.
87 ///
88 /// # Example
89 /// ```rust,ignore
90 /// use std::path::Path;
91 /// use std::{thread, time};
92 /// use std::sync::mpsc::{self, TryRecvError};
93 ///
94 /// extern crate fs_extra;
95 /// use fs_extra::dir::*;
96 /// use fs_extra::error::*;
97 ///
98 /// fn example_copy() -> Result<()> {
99 ///
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");
107 ///
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")?;
112 ///
113 /// assert!(dir.exists());
114 /// assert!(sub.exists());
115 /// assert!(file1.exists());
116 /// assert!(file2.exists());
117 ///
118 ///
119 /// let options = CopyOptions {
120 /// buffer_size: 1,
121 /// ..Default::default(),
122 /// };
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));
128 /// };
129 /// copy_with_progress(&test_folder, &path_to, &options, handler).unwrap();
130 /// });
131 ///
132 /// loop {
133 /// match rx.try_recv() {
134 /// Ok(process_info) => {
135 /// println!("{} of {} bytes",
136 /// process_info.copied_bytes,
137 /// process_info.total_bytes);
138 /// }
139 /// Err(TryRecvError::Disconnected) => {
140 /// println!("finished");
141 /// break;
142 /// }
143 /// Err(TryRecvError::Empty) => {}
144 /// }
145 /// }
146 /// Ok(())
147 ///
148 /// }
149 /// fn main() {
150 /// example_copy();
151 /// }
152 /// ```
153 ///
154 pub mod dir;
155
156 use error::*;
157 use std::path::Path;
158
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
161 /// directories).
162 ///
163 /// # Errors
164 ///
165 /// This function will return an error in the following situations, but is not limited to just
166 /// these case:
167 ///
168 /// * List `from` contains file or directory does not exist.
169 ///
170 /// * List `from` contains file or directory with invalid name.
171 ///
172 /// * The current process does not have the permission rights to access to file from `lists from` or
173 /// `to`.
174 ///
175 /// # Example
176 ///
177 /// ```rust,ignore
178 /// extern crate fs_extra;
179 /// use fs_extra::dir::copy;
180 ///
181 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
182 ///
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)?;
188 /// ```
189 ///
190 pub fn copy_items<P, Q>(from: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
191 where
192 P: AsRef<Path>,
193 Q: AsRef<Path>,
194 {
195 let mut result: u64 = 0;
196 if options.content_only {
197 err!(
198 "Options 'content_only' not acccess for copy_items function",
199 ErrorKind::Other
200 );
201 }
202 for item in from {
203 let item = item.as_ref();
204 if item.is_dir() {
205 result += dir::copy(item, &to, options)?;
206 } else {
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,
212 ..Default::default()
213 };
214 result += file::copy(item, to.as_ref().join(file_name), &file_options)?;
215 }
216 } else {
217 err!("Invalid file name", ErrorKind::InvalidFileName);
218 }
219 }
220 }
221
222 Ok(result)
223 }
224
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,
239 /// Transit state
240 pub state: dir::TransitState,
241 }
242
243 impl Clone for TransitProcess {
244 fn clone(&self) -> TransitProcess {
245 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(),
253 }
254 }
255 }
256
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).
260 ///
261 /// # Errors
262 ///
263 /// This function will return an error in the following situations, but is not limited to just
264 /// these case:
265 ///
266 /// * List `from` contains file or directory does not exist.
267 ///
268 /// * List `from` contains file or directory with invalid name.
269 ///
270 /// * The current process does not have the permission rights to access to file from `lists from` or
271 /// `to`.
272 ///
273 /// # Example
274 /// ```rust,ignore
275 ///
276 /// extern crate fs_extra;
277 /// use fs_extra::dir::copy;
278 ///
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
283 /// }
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)?;
289 /// ```
290 ///
291 pub fn copy_items_with_progress<P, Q, F>(
292 from: &[P],
293 to: Q,
294 options: &dir::CopyOptions,
295 mut progress_handler: F,
296 ) -> Result<u64>
297 where
298 P: AsRef<Path>,
299 Q: AsRef<Path>,
300 F: FnMut(TransitProcess) -> dir::TransitProcessResult,
301 {
302 if options.content_only {
303 err!(
304 "Options 'content_only' not acccess for copy_items_with_progress function",
305 ErrorKind::Other
306 );
307 }
308 let mut total_size = 0;
309 let mut list_paths = Vec::new();
310 for item in from {
311 let item = item.as_ref();
312 total_size += dir::get_size(item)?;
313 list_paths.push(item);
314 }
315
316 let mut result: u64 = 0;
317 let mut info_process = TransitProcess {
318 copied_bytes: 0,
319 total_bytes: total_size,
320 file_bytes_copied: 0,
321 file_total_bytes: 0,
322 file_name: String::new(),
323 dir_name: String::new(),
324 state: dir::TransitState::Normal,
325 };
326
327 let mut options = options.clone();
328 for item in list_paths {
329 if item.is_dir() {
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;
333 } else {
334 err!("Invalid folder from", ErrorKind::InvalidFolder);
335 }
336 } else {
337 err!("Invalid folder from", ErrorKind::InvalidFolder);
338 }
339
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());
346 match result {
347 dir::TransitProcessResult::OverwriteAll => options.overwrite = true,
348 dir::TransitProcessResult::SkipAll => options.skip_exist = true,
349 _ => {}
350 }
351 result
352 };
353 result += dir::copy_with_progress(item, &to, &dir_options, handler)?;
354 } else {
355 let mut file_options = file::CopyOptions {
356 overwrite: options.overwrite,
357 skip_exist: options.skip_exist,
358 buffer_size: options.buffer_size,
359 ..Default::default()
360 };
361
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();
365 } else {
366 err!("Invalid file name", ErrorKind::InvalidFileName);
367 }
368 } else {
369 err!("Invalid file name", ErrorKind::InvalidFileName);
370 }
371
372 info_process.file_bytes_copied = 0;
373 info_process.file_total_bytes = item.metadata()?.len();
374
375 let copied_bytes = result;
376 let file_name = to.as_ref().join(info_process.file_name.clone());
377 let mut work = true;
378
379 let mut result_copy: Result<u64>;
380 while work {
381 {
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());
386 };
387 result_copy =
388 file::copy_with_progress(item, &file_name, &file_options, handler);
389 }
390 match result_copy {
391 Ok(val) => {
392 result += val;
393 work = false;
394 }
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);
400 match user_decide {
401 dir::TransitProcessResult::Overwrite => {
402 file_options.overwrite = true;
403 }
404 dir::TransitProcessResult::OverwriteAll => {
405 file_options.overwrite = true;
406 options.overwrite = true;
407 }
408 dir::TransitProcessResult::Skip => {
409 file_options.skip_exist = true;
410 }
411 dir::TransitProcessResult::SkipAll => {
412 file_options.skip_exist = true;
413 options.skip_exist = true;
414 }
415 dir::TransitProcessResult::Retry => {}
416 dir::TransitProcessResult::ContinueOrAbort => {
417 let err_msg = err.to_string();
418 err!(err_msg.as_str(), err.kind)
419 }
420 dir::TransitProcessResult::Abort => {
421 let err_msg = err.to_string();
422 err!(err_msg.as_str(), err.kind)
423 }
424 }
425 }
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);
430 match user_decide {
431 dir::TransitProcessResult::Overwrite => {
432 err!("Overwrite denied for this situation!", ErrorKind::Other);
433 }
434 dir::TransitProcessResult::OverwriteAll => {
435 err!("Overwrite denied for this situation!", ErrorKind::Other);
436 }
437 dir::TransitProcessResult::Skip => {
438 file_options.skip_exist = true;
439 }
440 dir::TransitProcessResult::SkipAll => {
441 file_options.skip_exist = true;
442 options.skip_exist = true;
443 }
444 dir::TransitProcessResult::Retry => {}
445 dir::TransitProcessResult::ContinueOrAbort => {
446 let err_msg = err.to_string();
447 err!(err_msg.as_str(), err.kind)
448 }
449 dir::TransitProcessResult::Abort => {
450 let err_msg = err.to_string();
451 err!(err_msg.as_str(), err.kind)
452 }
453 }
454 }
455 _ => {
456 let err_msg = err.to_string();
457 err!(err_msg.as_str(), err.kind)
458 }
459 },
460 }
461 }
462 }
463 }
464
465 Ok(result)
466 }
467
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
470 /// directories).
471 ///
472 /// # Errors
473 ///
474 /// This function will return an error in the following situations, but is not limited to just
475 /// these case:
476 ///
477 /// * List `from` contains file or directory does not exist.
478 ///
479 /// * List `from` contains file or directory with invalid name.
480 ///
481 /// * The current process does not have the permission rights to access to file from `lists from` or
482 /// `to`.
483 ///
484 /// # Example
485 ///
486 /// ```rust,ignore
487 /// extern crate fs_extra;
488 /// use fs_extra::dir::copy;
489 ///
490 /// let options = dir::CopyOptions::new(); //Initialize default values for CopyOptions
491 ///
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)?;
497 /// ```
498 ///
499 pub fn move_items<P, Q>(from_items: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
500 where
501 P: AsRef<Path>,
502 Q: AsRef<Path>,
503 {
504 if options.content_only {
505 err!(
506 "Options 'content_only' not acccess for move_items function",
507 ErrorKind::Other
508 );
509 }
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);
516 }
517
518 let mut result = 0;
519 let mut info_process = TransitProcess {
520 copied_bytes: 0,
521 total_bytes: total_size,
522 file_bytes_copied: 0,
523 file_total_bytes: 0,
524 file_name: String::new(),
525 dir_name: String::new(),
526 state: dir::TransitState::Normal,
527 };
528
529 for item in list_paths {
530 if item.is_dir() {
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;
534 } else {
535 err!("Invalid folder from", ErrorKind::InvalidFolder);
536 }
537 } else {
538 err!("Invalid folder from", ErrorKind::InvalidFolder);
539 }
540
541 result += dir::move_dir(item, &to, options)?;
542 } else {
543 let file_options = file::CopyOptions {
544 overwrite: options.overwrite,
545 skip_exist: options.skip_exist,
546 buffer_size: options.buffer_size,
547 ..Default::default()
548 };
549
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();
553 } else {
554 err!("Invalid file name", ErrorKind::InvalidFileName);
555 }
556 } else {
557 err!("Invalid file name", ErrorKind::InvalidFileName);
558 }
559
560 info_process.file_bytes_copied = 0;
561 info_process.file_total_bytes = item.metadata()?.len();
562
563 let file_name = to.as_ref().join(info_process.file_name.clone());
564 result += file::move_file(item, &file_name, &file_options)?;
565 }
566 }
567
568 Ok(result)
569 }
570
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).
574 ///
575 /// # Errors
576 ///
577 /// This function will return an error in the following situations, but is not limited to just
578 /// these case:
579 ///
580 /// * List `from` contains file or directory does not exist.
581 ///
582 /// * List `from` contains file or directory with invalid name.
583 ///
584 /// * The current process does not have the permission rights to access to file from `lists from` or
585 /// `to`.
586 ///
587 /// # Example
588 ///
589 /// ```rust,ignore
590 /// extern crate fs_extra;
591 /// use fs_extra::dir::copy;
592 ///
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
597 /// }
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)?;
603 /// ```
604 ///
605 pub fn move_items_with_progress<P, Q, F>(
606 from_items: &[P],
607 to: Q,
608 options: &dir::CopyOptions,
609 mut progress_handler: F,
610 ) -> Result<u64>
611 where
612 P: AsRef<Path>,
613 Q: AsRef<Path>,
614 F: FnMut(TransitProcess) -> dir::TransitProcessResult,
615 {
616 if options.content_only {
617 err!(
618 "Options 'content_only' not acccess for move_items_with_progress function",
619 ErrorKind::Other
620 );
621 }
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);
628 }
629
630 let mut result = 0;
631 let mut info_process = TransitProcess {
632 copied_bytes: 0,
633 total_bytes: total_size,
634 file_bytes_copied: 0,
635 file_total_bytes: 0,
636 file_name: String::new(),
637 dir_name: String::new(),
638 state: dir::TransitState::Normal,
639 };
640 let mut options = options.clone();
641
642 for item in list_paths {
643 if item.is_dir() {
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;
647 } else {
648 err!("Invalid folder from", ErrorKind::InvalidFolder);
649 }
650 } else {
651 err!("Invalid folder from", ErrorKind::InvalidFolder);
652 }
653
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());
660 match result {
661 dir::TransitProcessResult::OverwriteAll => options.overwrite = true,
662 dir::TransitProcessResult::SkipAll => options.skip_exist = true,
663 _ => {}
664 }
665 result
666 };
667 result += dir::move_dir_with_progress(item, &to, &dir_options, handler)?;
668 } else {
669 let mut file_options = file::CopyOptions {
670 overwrite: options.overwrite,
671 skip_exist: options.skip_exist,
672 buffer_size: options.buffer_size,
673 ..Default::default()
674 };
675
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();
679 } else {
680 err!("Invalid file name", ErrorKind::InvalidFileName);
681 }
682 } else {
683 err!("Invalid file name", ErrorKind::InvalidFileName);
684 }
685
686 info_process.file_bytes_copied = 0;
687 info_process.file_total_bytes = item.metadata()?.len();
688
689 let copied_bytes = result;
690 let file_name = to.as_ref().join(info_process.file_name.clone());
691 let mut work = true;
692
693 let mut result_copy: Result<u64>;
694 while work {
695 {
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());
700 };
701 result_copy =
702 file::move_file_with_progress(item, &file_name, &file_options, handler);
703 }
704 match result_copy {
705 Ok(val) => {
706 result += val;
707 work = false;
708 }
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);
714 match user_decide {
715 dir::TransitProcessResult::Overwrite => {
716 file_options.overwrite = true;
717 }
718 dir::TransitProcessResult::OverwriteAll => {
719 file_options.overwrite = true;
720 options.overwrite = true;
721 }
722 dir::TransitProcessResult::Skip => {
723 file_options.skip_exist = true;
724 }
725 dir::TransitProcessResult::SkipAll => {
726 file_options.skip_exist = true;
727 options.skip_exist = true;
728 }
729 dir::TransitProcessResult::Retry => {}
730 dir::TransitProcessResult::ContinueOrAbort => {
731 let err_msg = err.to_string();
732 err!(err_msg.as_str(), err.kind)
733 }
734 dir::TransitProcessResult::Abort => {
735 let err_msg = err.to_string();
736 err!(err_msg.as_str(), err.kind)
737 }
738 }
739 }
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);
744 match user_decide {
745 dir::TransitProcessResult::Overwrite => {
746 err!("Overwrite denied for this situation!", ErrorKind::Other);
747 }
748 dir::TransitProcessResult::OverwriteAll => {
749 err!("Overwrite denied for this situation!", ErrorKind::Other);
750 }
751 dir::TransitProcessResult::Skip => {
752 file_options.skip_exist = true;
753 }
754 dir::TransitProcessResult::SkipAll => {
755 file_options.skip_exist = true;
756 options.skip_exist = true;
757 }
758 dir::TransitProcessResult::Retry => {}
759 dir::TransitProcessResult::ContinueOrAbort => {
760 let err_msg = err.to_string();
761 err!(err_msg.as_str(), err.kind)
762 }
763 dir::TransitProcessResult::Abort => {
764 let err_msg = err.to_string();
765 err!(err_msg.as_str(), err.kind)
766 }
767 }
768 }
769 _ => {
770 let err_msg = err.to_string();
771 err!(err_msg.as_str(), err.kind)
772 }
773 },
774 }
775 }
776 }
777 }
778 Ok(result)
779 }
780
781 /// Removes list files or directories.
782 ///
783 /// # Example
784 ///
785 /// ```rust,ignore
786 /// let mut from_paths = Vec::new();
787 /// from_paths.push("source/dir1");
788 /// from_paths.push("source/file.txt");
789 ///
790 /// remove_items(&from_paths).unwrap();
791 /// ```
792 ///
793 pub fn remove_items<P>(from_items: &[P]) -> Result<()>
794 where
795 P: AsRef<Path>,
796 {
797 for item in from_items {
798 let item = item.as_ref();
799 if item.is_dir() {
800 dir::remove(item)?;
801 } else {
802 file::remove(item)?
803 }
804 }
805
806 Ok(())
807 }