Skip to content

Commit 8754833

Browse files
committed
progress
1 parent 5584b24 commit 8754833

File tree

1 file changed

+98
-95
lines changed

1 file changed

+98
-95
lines changed

src/uu/rm/src/rm.rs

Lines changed: 98 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,88 @@ enum RmError {
4747

4848
impl UError for RmError {}
4949

50+
/// Helper function to print verbose message for removed file
51+
fn verbose_removed_file(path: &Path, options: &Options) {
52+
if options.verbose {
53+
println!(
54+
"{}",
55+
translate!("rm-verbose-removed", "file" => normalize(path).quote())
56+
);
57+
}
58+
}
59+
60+
/// Helper function to print verbose message for removed directory
61+
fn verbose_removed_directory(path: &Path, options: &Options) {
62+
if options.verbose {
63+
println!(
64+
"{}",
65+
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
66+
);
67+
}
68+
}
69+
70+
/// Helper function to show error with context and return error status
71+
fn show_removal_error(error: std::io::Error, path: &Path) -> bool {
72+
let e = error.map_err_context(|| translate!("rm-error-cannot-remove", "file" => path.quote()));
73+
show_error!("{e}");
74+
true
75+
}
76+
77+
/// Helper function for permission denied errors
78+
fn show_permission_denied_error(path: &Path) -> bool {
79+
show_error!("cannot remove {}: Permission denied", path.quote());
80+
true
81+
}
82+
83+
/// Helper function to show generic removal error
84+
fn show_generic_removal_error(error: std::io::Error, path: &Path) -> bool {
85+
show_error!("cannot remove {}: {error}", path.quote());
86+
true
87+
}
88+
89+
/// Helper function to remove a directory and handle results
90+
fn remove_dir_with_feedback(path: &Path, options: &Options) -> bool {
91+
match fs::remove_dir(path) {
92+
Ok(_) => {
93+
verbose_removed_directory(path, options);
94+
false
95+
}
96+
Err(e) => show_removal_error(e, path),
97+
}
98+
}
99+
100+
/// Helper function to remove directory handling special cases
101+
#[cfg(target_os = "linux")]
102+
fn remove_dir_with_special_cases(path: &Path, options: &Options, error_occurred: bool) -> bool {
103+
match fs::remove_dir(path) {
104+
Err(_) if !error_occurred && !is_readable(path) => {
105+
// For compatibility with GNU test case
106+
// `tests/rm/unread2.sh`, show "Permission denied" in this
107+
// case instead of "Directory not empty".
108+
show_permission_denied_error(path);
109+
true
110+
}
111+
Err(_) if !error_occurred && path.read_dir().is_err() => {
112+
// For compatibility with GNU test case on Linux
113+
// Check if directory is readable by attempting to read it
114+
show_permission_denied_error(path);
115+
true
116+
}
117+
Err(e) if !error_occurred => show_removal_error(e, path),
118+
Err(_) => {
119+
// If we already had errors while
120+
// trying to remove the children, then there is no need to
121+
// show another error message as we return from each level
122+
// of the recursion.
123+
error_occurred
124+
}
125+
Ok(_) => {
126+
verbose_removed_directory(path, options);
127+
false
128+
}
129+
}
130+
}
131+
50132
#[derive(Eq, PartialEq, Clone, Copy)]
51133
/// Enum, determining when the `rm` will prompt the user about the file deletion
52134
pub enum InteractiveMode {
@@ -473,22 +555,13 @@ fn unsafe_remove_dir_recursive(path: &Path, options: &Options) -> bool {
473555
// If it's empty, this should succeed. If not, we'll get a different error.
474556
match fs::remove_dir(path) {
475557
Ok(_) => {
476-
if options.verbose {
477-
println!(
478-
"{}",
479-
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
480-
);
481-
}
558+
verbose_removed_directory(path, options);
482559
return false; // Success
483560
}
484561
Err(_remove_err) => {
485562
// Could not remove the directory. Always show the original permission denied error
486563
// since this indicates a fundamental access issue, even with force flag
487-
let e = e.map_err_context(
488-
|| translate!("rm-error-cannot-remove", "file" => path.quote()),
489-
);
490-
show_error!("{}", e);
491-
error = true;
564+
return show_removal_error(e, path);
492565
}
493566
}
494567
}
@@ -542,19 +615,9 @@ fn unsafe_remove_dir_recursive(path: &Path, options: &Options) -> bool {
542615
}
543616
true
544617
}
545-
Err(e) => {
546-
let e =
547-
e.map_err_context(|| translate!("rm-error-cannot-remove", "file" => path.quote()));
548-
show_error!("{e}");
549-
true
550-
}
618+
Err(e) => show_removal_error(e, path),
551619
Ok(_) => {
552-
if options.verbose {
553-
println!(
554-
"{}",
555-
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
556-
);
557-
}
620+
verbose_removed_directory(path, options);
558621
false
559622
}
560623
}
@@ -584,31 +647,7 @@ fn safe_remove_dir_recursive(path: &Path, options: &Options) -> bool {
584647
}
585648

586649
// Use regular fs::remove_dir for the root since we can't unlinkat ourselves
587-
match fs::remove_dir(path) {
588-
Ok(_) => {
589-
if options.verbose {
590-
println!(
591-
"{}",
592-
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
593-
);
594-
}
595-
false
596-
}
597-
Err(e) if !error => {
598-
let e = e.map_err_context(
599-
|| translate!("rm-error-cannot-remove", "file" => path.quote()),
600-
);
601-
show_error!("{e}");
602-
true
603-
}
604-
Err(_) => {
605-
// If there has already been at least one error when
606-
// trying to remove the children, then there is no need to
607-
// show another error message as we return from each level
608-
// of the recursion.
609-
error
610-
}
611-
}
650+
remove_dir_with_special_cases(path, options, error)
612651
}
613652
}
614653

@@ -691,11 +730,8 @@ fn safe_remove_dir_recursive_impl(path: &Path, dir_fd: &DirFd, options: &Options
691730
);
692731
show_error!("{e}");
693732
error = true;
694-
} else if options.verbose {
695-
println!(
696-
"{}",
697-
translate!("rm-verbose-removed-directory", "file" => normalize(&entry_path).quote())
698-
);
733+
} else {
734+
verbose_removed_directory(&entry_path, options);
699735
}
700736
}
701737
} else {
@@ -707,11 +743,8 @@ fn safe_remove_dir_recursive_impl(path: &Path, dir_fd: &DirFd, options: &Options
707743
);
708744
show_error!("{e}");
709745
error = true;
710-
} else if options.verbose {
711-
println!(
712-
"{}",
713-
translate!("rm-verbose-removed", "file" => normalize(&entry_path).quote())
714-
);
746+
} else {
747+
verbose_removed_file(&entry_path, options);
715748
}
716749
}
717750
}
@@ -801,7 +834,7 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
801834
// For compatibility with GNU test case
802835
// `tests/rm/unread2.sh`, show "Permission denied" in this
803836
// case instead of "Directory not empty".
804-
show_error!("cannot remove {}: Permission denied", path.quote());
837+
show_permission_denied_error(path);
805838
error = true;
806839
}
807840
Err(e) if !error => {
@@ -817,11 +850,7 @@ fn remove_dir_recursive(path: &Path, options: &Options) -> bool {
817850
// show another error message as we return from each level
818851
// of the recursion.
819852
}
820-
Ok(_) if options.verbose => println!(
821-
"{}",
822-
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
823-
),
824-
Ok(_) => {}
853+
Ok(_) => verbose_removed_directory(path, options),
825854
}
826855

827856
error
@@ -911,23 +940,7 @@ fn remove_dir(path: &Path, options: &Options) -> bool {
911940
}
912941

913942
// Fallback method for non-Linux or when safe traversal is unavailable
914-
match fs::remove_dir(path) {
915-
Ok(_) => {
916-
if options.verbose {
917-
println!(
918-
"{}",
919-
translate!("rm-verbose-removed-directory", "file" => normalize(path).quote())
920-
);
921-
}
922-
false
923-
}
924-
Err(e) => {
925-
let e =
926-
e.map_err_context(|| translate!("rm-error-cannot-remove", "file" => path.quote()));
927-
show_error!("{e}");
928-
true
929-
}
930-
}
943+
remove_dir_with_feedback(path, options)
931944
}
932945

933946
fn remove_file(path: &Path, options: &Options) -> bool {
@@ -941,12 +954,7 @@ fn remove_file(path: &Path, options: &Options) -> bool {
941954
Ok(dir_fd) => {
942955
match dir_fd.unlink_at(file_name, false) {
943956
Ok(_) => {
944-
if options.verbose {
945-
println!(
946-
"{}",
947-
translate!("rm-verbose-removed", "file" => normalize(path).quote())
948-
);
949-
}
957+
verbose_removed_file(path, options);
950958
return false;
951959
}
952960
Err(e) => {
@@ -959,7 +967,7 @@ fn remove_file(path: &Path, options: &Options) -> bool {
959967
)
960968
);
961969
} else {
962-
show_error!("cannot remove {}: {e}", path.quote());
970+
return show_generic_removal_error(e, path);
963971
}
964972
return true;
965973
}
@@ -976,12 +984,7 @@ fn remove_file(path: &Path, options: &Options) -> bool {
976984
// Fallback method for non-Linux or when safe traversal is unavailable
977985
match fs::remove_file(path) {
978986
Ok(_) => {
979-
if options.verbose {
980-
println!(
981-
"{}",
982-
translate!("rm-verbose-removed", "file" => normalize(path).quote())
983-
);
984-
}
987+
verbose_removed_file(path, options);
985988
}
986989
Err(e) => {
987990
if e.kind() == std::io::ErrorKind::PermissionDenied {
@@ -991,7 +994,7 @@ fn remove_file(path: &Path, options: &Options) -> bool {
991994
RmError::CannotRemovePermissionDenied(path.as_os_str().to_os_string())
992995
);
993996
} else {
994-
show_error!("cannot remove {}: {e}", path.quote());
997+
return show_generic_removal_error(e, path);
995998
}
996999
return true;
9971000
}

0 commit comments

Comments
 (0)