@cryptotaxi247 / kubo / commits / f6223605e

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"