]> git.proxmox.com Git - rustc.git/blame - vendor/fs_extra/src/lib.rs
New upstream version 1.52.1+dfsg1
[rustc.git] / vendor / fs_extra / src / lib.rs
CommitLineData
a1dfa0c6
XL
1macro_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.
12pub 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///
5869c6ff
XL
42/// let options = CopyOptions {
43/// buffer_size: 1,
44/// ..Default::default()
45/// }
a1dfa0c6
XL
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/// ```
81pub 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///
5869c6ff
XL
119/// let options = CopyOptions {
120/// buffer_size: 1,
121/// ..Default::default(),
122/// };
a1dfa0c6
XL
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///
154pub mod dir;
155
a1dfa0c6
XL
156use error::*;
157use std::path::Path;
158
a1dfa0c6
XL
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///
5869c6ff 190pub fn copy_items<P, Q>(from: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
a1dfa0c6
XL
191where
192 P: AsRef<Path>,
193 Q: AsRef<Path>,
194{
195 let mut result: u64 = 0;
5869c6ff
XL
196 if options.content_only {
197 err!(
198 "Options 'content_only' not acccess for copy_items function",
199 ErrorKind::Other
200 );
201 }
a1dfa0c6
XL
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() {
5869c6ff
XL
209 let file_options = file::CopyOptions {
210 overwrite: options.overwrite,
211 skip_exist: options.skip_exist,
212 ..Default::default()
213 };
a1dfa0c6
XL
214 result += file::copy(item, to.as_ref().join(file_name), &file_options)?;
215 }
216 } else {
217 err!("Invalid file name", ErrorKind::InvalidFileName);
218 }
a1dfa0c6
XL
219 }
220 }
221
222 Ok(result)
223}
224
225/// A structure which include information about the current status of the copy or move directory.
226pub 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
243impl 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
a1dfa0c6
XL
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///
291pub fn copy_items_with_progress<P, Q, F>(
5869c6ff 292 from: &[P],
a1dfa0c6
XL
293 to: Q,
294 options: &dir::CopyOptions,
295 mut progress_handler: F,
296) -> Result<u64>
297where
298 P: AsRef<Path>,
299 Q: AsRef<Path>,
300 F: FnMut(TransitProcess) -> dir::TransitProcessResult,
301{
5869c6ff
XL
302 if options.content_only {
303 err!(
304 "Options 'content_only' not acccess for copy_items_with_progress function",
305 ErrorKind::Other
306 );
307 }
a1dfa0c6
XL
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 {
5869c6ff
XL
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 };
a1dfa0c6
XL
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 }
a1dfa0c6
XL
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 }
5869c6ff
XL
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;
a1dfa0c6 403 }
5869c6ff
XL
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)
a1dfa0c6
XL
423 }
424 }
5869c6ff
XL
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 }
a1dfa0c6 453 }
a1dfa0c6 454 }
5869c6ff
XL
455 _ => {
456 let err_msg = err.to_string();
457 err!(err_msg.as_str(), err.kind)
458 }
459 },
a1dfa0c6
XL
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///
5869c6ff 499pub fn move_items<P, Q>(from_items: &[P], to: Q, options: &dir::CopyOptions) -> Result<u64>
a1dfa0c6
XL
500where
501 P: AsRef<Path>,
502 Q: AsRef<Path>,
503{
5869c6ff
XL
504 if options.content_only {
505 err!(
506 "Options 'content_only' not acccess for move_items function",
507 ErrorKind::Other
508 );
509 }
a1dfa0c6
XL
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 {
5869c6ff
XL
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 };
a1dfa0c6
XL
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 }
a1dfa0c6
XL
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)
a1dfa0c6
XL
569}
570
a1dfa0c6
XL
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///
605pub fn move_items_with_progress<P, Q, F>(
5869c6ff 606 from_items: &[P],
a1dfa0c6
XL
607 to: Q,
608 options: &dir::CopyOptions,
609 mut progress_handler: F,
610) -> Result<u64>
611where
612 P: AsRef<Path>,
613 Q: AsRef<Path>,
614 F: FnMut(TransitProcess) -> dir::TransitProcessResult,
615{
5869c6ff
XL
616 if options.content_only {
617 err!(
618 "Options 'content_only' not acccess for move_items_with_progress function",
619 ErrorKind::Other
620 );
621 }
a1dfa0c6
XL
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)?;
a1dfa0c6 668 } else {
5869c6ff
XL
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 };
a1dfa0c6
XL
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 }
a1dfa0c6
XL
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 }
5869c6ff
XL
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;
a1dfa0c6 717 }
5869c6ff
XL
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)
a1dfa0c6
XL
737 }
738 }
5869c6ff
XL
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 }
a1dfa0c6 767 }
a1dfa0c6 768 }
5869c6ff
XL
769 _ => {
770 let err_msg = err.to_string();
771 err!(err_msg.as_str(), err.kind)
772 }
773 },
a1dfa0c6
XL
774 }
775 }
776 }
a1dfa0c6
XL
777 }
778 Ok(result)
a1dfa0c6
XL
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///
5869c6ff 793pub fn remove_items<P>(from_items: &[P]) -> Result<()>
a1dfa0c6
XL
794where
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}