Add support for multiple files to `ipfs files rm`.
Andrey Kostakov committed
Sep 20, 2021 at 20:47 UTC
f6223605e719c14e84d8352bac4176b5ff95c1e5
2 files changed
+107
-49
core/commands/files.go
+71
-46
@@ -1044,68 +1044,93 @@ Remove files or directories.
1044
if err != nil {
1045
return err
1046
}
1047
-
1048
- path, err := checkPath(req.Arguments[0])
1049
- if err != nil {
1050
- return err
1051
- }
1052
-
1053
- if path == "/" {
1054
- return fmt.Errorf("cannot delete root")
1055
- }
1056
-
1057
- // 'rm a/b/c/' will fail unless we trim the slash at the end
1058
- if path[len(path)-1] == '/' {
1059
- path = path[:len(path)-1]
1060
- }
1061
-
1047
// if '--force' specified, it will remove anything else,
1048
// including file, directory, corrupted node, etc
1049
force, _ := req.Options[forceOptionName].(bool)
1050
+ dashr, _ := req.Options[recursiveOptionName].(bool)
1051
+ var errs []error
1052
+ for _, arg := range req.Arguments {
1053
+ path, err := checkPath(arg)
1054
+ if err != nil {
1055
+ errs = append(errs, fmt.Errorf("%s: %w", arg, err))
1056
+ continue
1057
+ }
1058
1066
- dir, name := gopath.Split(path)
1059
+ if path == "/" {
1060
+ errs = append(errs, fmt.Errorf("%s: cannot delete root", path))
1061
+ continue
1062
+ }
1063
1068
- pdir, err := getParentDir(nd.FilesRoot, dir)
1069
- if err != nil {
1070
- if force && err == os.ErrNotExist {
1071
- return nil
1064
+ // 'rm a/b/c/' will fail unless we trim the slash at the end
1065
+ if path[len(path)-1] == '/' {
1066
+ path = path[:len(path)-1]
1067
}
1073
- return fmt.Errorf("parent lookup: %s", err)
1074
- }
1068
1076
- if force {
1077
- err := pdir.Unlink(name)
1069
+ dir, name := gopath.Split(path)
1070
+
1071
+ pdir, err := getParentDir(nd.FilesRoot, dir)
1072
if err != nil {
1079
- if err == os.ErrNotExist {
1080
- return nil
1073
+ if force && err == os.ErrNotExist {
1074
+ continue
1075
}
1082
- return err
1076
+ errs = append(errs, fmt.Errorf("%s: parent lookup: %w", path, err))
1077
+ continue
1078
}
1084
- return pdir.Flush()
1085
- }
1079
1087
- // get child node by name, when the node is corrupted and nonexistent,
1088
- // it will return specific error.
1089
- child, err := pdir.Child(name)
1090
- if err != nil {
1091
- return err
1092
- }
1080
+ if force {
1081
+ err := pdir.Unlink(name)
1082
+ if err != nil {
1083
+ if err == os.ErrNotExist {
1084
+ continue
1085
+ }
1086
+ errs = append(errs, fmt.Errorf("%s: %w", path, err))
1087
+ continue
1088
+ }
1089
+ err = pdir.Flush()
1090
+ if err != nil {
1091
+ errs = append(errs, fmt.Errorf("%s: %w", path, err))
1092
+ }
1093
+ continue
1094
+ }
1095
1094
- dashr, _ := req.Options[recursiveOptionName].(bool)
1096
+ // get child node by name, when the node is corrupted and nonexistent,
1097
+ // it will return specific error.
1098
+ child, err := pdir.Child(name)
1099
+ if err != nil {
1100
+ errs = append(errs, fmt.Errorf("%s: %w", path, err))
1101
+ continue
1102
+ }
1103
1096
- switch child.(type) {
1097
- case *mfs.Directory:
1098
- if !dashr {
1099
- return fmt.Errorf("%s is a directory, use -r to remove directories", path)
1104
+ switch child.(type) {
1105
+ case *mfs.Directory:
1106
+ if !dashr {
1107
+ errs = append(errs, fmt.Errorf("%s is a directory, use -r to remove directories", path))
1108
+ continue
1109
+ }
1110
}
1101
- }
1111
1103
- err = pdir.Unlink(name)
1104
- if err != nil {
1105
- return err
1106
- }
1112
+ err = pdir.Unlink(name)
1113
+ if err != nil {
1114
+ errs = append(errs, fmt.Errorf("%s: %w", path, err))
1115
+ continue
1116
+ }
1117
1108
- return pdir.Flush()
1118
+ err = pdir.Flush()
1119
+ if err != nil {
1120
+ errs = append(errs, fmt.Errorf("%s: %w", path, err))
1121
+ }
1122
+ continue
1123
+ }
1124
+ if len(errs) > 0 {
1125
+ for _, err = range errs {
1126
+ e := res.Emit(err.Error())
1127
+ if e != nil {
1128
+ return e
1129
+ }
1130
+ }
1131
+ return fmt.Errorf("can't remove some files")
1132
+ }
1133
+ return nil
1134
},
1135
}
1136
test/sharness/t0250-files-api.sh
+36
-3
@@ -690,9 +690,7 @@ test_files_api() {
690
'
691
692
test_expect_success "clean up $EXTRA" '
693
- ipfs files rm -r /foobar &&
694
- ipfs files rm -r /adir &&
695
- ipfs files rm -r /parents
693
+ ipfs files rm -r /foobar /adir /parents
694
'
695
696
test_expect_success "root mfs entry is empty $EXTRA" '
@@ -711,12 +709,39 @@ test_files_api() {
709
verify_dir_contents /
710
'
711
712
+ test_expect_success "remove multiple files forcibly" '
713
+ echo "hello world" | ipfs files write --create /forcibly_one &&
714
+ echo "hello world" | ipfs files write --create /forcibly_two &&
715
+ ipfs files rm --force /forcibly_one /forcibly_two &&
716
+ verify_dir_contents /
717
+ '
718
+
719
test_expect_success "remove directory forcibly" '
720
ipfs files mkdir /forcibly-dir &&
721
ipfs files rm --force /forcibly-dir &&
722
verify_dir_contents /
723
'
724
725
+ test_expect_success "remove multiple directories forcibly" '
726
+ ipfs files mkdir /forcibly-dir-one &&
727
+ ipfs files mkdir /forcibly-dir-two &&
728
+ ipfs files rm --force /forcibly-dir-one /forcibly-dir-two &&
729
+ verify_dir_contents /
730
+ '
731
+
732
+ test_expect_success "remove multiple files" '
733
+ echo "hello world" | ipfs files write --create /file_one &&
734
+ echo "hello world" | ipfs files write --create /file_two &&
735
+ ipfs files rm /file_one /file_two
736
+ '
737
+
738
+ test_expect_success "remove multiple directories" '
739
+ ipfs files mkdir /forcibly-dir-one &&
740
+ ipfs files mkdir /forcibly-dir-two &&
741
+ ipfs files rm -r /forcibly-dir-one /forcibly-dir-two &&
742
+ verify_dir_contents /
743
+ '
744
+
745
test_expect_success "remove nonexistant path forcibly" '
746
ipfs files rm --force /nonexistant
747
'
@@ -724,6 +749,14 @@ test_files_api() {
749
test_expect_success "remove deeply nonexistant path forcibly" '
750
ipfs files rm --force /deeply/nonexistant
751
'
752
+
753
+ # This one should return code 1 but still remove the rest of the valid files.
754
+ test_expect_success "remove multiple files (with nonexistent one)" '
755
+ echo "hello world" | ipfs files write --create /file_one &&
756
+ echo "hello world" | ipfs files write --create /file_two &&
757
+ test_expect_code 1 ipfs files rm /file_one /nonexistent /file_two
758
+ verify_dir_contents /
759
+ '
760
}
761
762
# test with and without the daemon (EXTRA="with-daemon" and EXTRA="no-daemon"