diff --git a/services/localfile/client/client.go b/services/localfile/client/client.go index b18bf6c1..530e9345 100644 --- a/services/localfile/client/client.go +++ b/services/localfile/client/client.go @@ -1249,13 +1249,20 @@ func (i *rmCmd) SetFlags(f *flag.FlagSet) {} func (i *rmCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { state := args[0].(*util.ExecuteState) - if f.NArg() != 1 { - fmt.Fprintln(os.Stderr, "please specify a filename to rm") + if f.NArg() < 1 { + fmt.Fprintln(os.Stderr, "please specify at least one filename to rm") return subcommands.ExitUsageError } + file := f.Arg(0) + var files []string + if f.NArg() > 1 { + files = f.Args()[1:] + } + req := &pb.RmRequest{ - Filename: f.Arg(0), + Filename: file, + Filenames: files, } client := pb.NewLocalFileClientProxy(state.Conn) respChan, err := client.RmOneMany(ctx, req) @@ -1278,27 +1285,38 @@ func (i *rmCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{ } type rmdirCmd struct { + recursive bool } func (*rmdirCmd) Name() string { return "rmdir" } func (*rmdirCmd) Synopsis() string { return "Remove a directory." } func (*rmdirCmd) Usage() string { - return `rm : + return `rmdir [-r] : Remove the given directory. ` } -func (i *rmdirCmd) SetFlags(f *flag.FlagSet) {} +func (i *rmdirCmd) SetFlags(f *flag.FlagSet) { + f.BoolVar(&i.recursive, "r", false, "recursively also remove all sub-directories and files") +} func (i *rmdirCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { state := args[0].(*util.ExecuteState) - if f.NArg() != 1 { - fmt.Fprintln(os.Stderr, "please specify a directory to rm") + if f.NArg() < 1 { + fmt.Fprintln(os.Stderr, "please specify at least one directory to rm") return subcommands.ExitUsageError } + dir := f.Arg(0) + var dirs []string + if f.NArg() > 1 { + dirs = f.Args()[1:] + } + req := &pb.RmdirRequest{ - Directory: f.Arg(0), + Directory: dir, + Directories: dirs, + Recursive: i.recursive, } client := pb.NewLocalFileClientProxy(state.Conn) respChan, err := client.RmdirOneMany(ctx, req) diff --git a/services/localfile/client/utils.go b/services/localfile/client/utils.go index b3ac2936..a6e142ac 100644 --- a/services/localfile/client/utils.go +++ b/services/localfile/client/utils.go @@ -205,7 +205,7 @@ func WriteRemoteFile(ctx context.Context, conn *proxy.Conn, config *FileConfig, func RemoveRemoteFile(ctx context.Context, conn *proxy.Conn, path string) error { c := pb.NewLocalFileClientProxy(conn) resp, err := c.RmOneMany(ctx, &pb.RmRequest{ - Filename: path, + Filenames: []string{path}, }) if err != nil { return fmt.Errorf("remove error - %v", err) diff --git a/services/localfile/localfile.pb.go b/services/localfile/localfile.pb.go index 3515c319..9cb54ff7 100644 --- a/services/localfile/localfile.pb.go +++ b/services/localfile/localfile.pb.go @@ -1332,6 +1332,8 @@ type RmRequest struct { // The fully qualified path to the file to remove. Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` + // A list of fully qualified paths to the files to remove + Filenames []string `protobuf:"bytes,2,rep,name=filenames,proto3" json:"filenames,omitempty"` } func (x *RmRequest) Reset() { @@ -1373,6 +1375,13 @@ func (x *RmRequest) GetFilename() string { return "" } +func (x *RmRequest) GetFilenames() []string { + if x != nil { + return x.Filenames + } + return nil +} + type RmdirRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1381,6 +1390,11 @@ type RmdirRequest struct { // The fully qualified path to the directory to remove. // Must be empty of any entries. Directory string `protobuf:"bytes,1,opt,name=directory,proto3" json:"directory,omitempty"` + // A list of fully qualified paths to the directory to remove. + // Must be either empty of entries or the recursive flag must be specified + Directories []string `protobuf:"bytes,2,rep,name=directories,proto3" json:"directories,omitempty"` + // Delete nested files and directories if there are any + Recursive bool `protobuf:"varint,3,opt,name=recursive,proto3" json:"recursive,omitempty"` } func (x *RmdirRequest) Reset() { @@ -1422,6 +1436,20 @@ func (x *RmdirRequest) GetDirectory() string { return "" } +func (x *RmdirRequest) GetDirectories() []string { + if x != nil { + return x.Directories + } + return nil +} + +func (x *RmdirRequest) GetRecursive() bool { + if x != nil { + return x.Recursive + } + return false +} + type RenameRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1874,6 +1902,7 @@ type ShredRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // absolute path to the file to be shredded Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` // force permissions change if necessary Force bool `protobuf:"varint,2,opt,name=force,proto3" json:"force,omitempty"` @@ -2052,147 +2081,153 @@ var file_localfile_proto_rawDesc = []byte{ 0x12, 0x2f, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x05, 0x61, 0x74, 0x74, 0x72, - 0x73, 0x22, 0x27, 0x0a, 0x09, 0x52, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, + 0x73, 0x22, 0x45, 0x0a, 0x09, 0x52, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2c, 0x0a, 0x0c, 0x52, 0x6d, - 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x5f, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, - 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, - 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, - 0x0a, 0x10, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x2d, 0x0a, 0x0f, 0x52, 0x65, 0x61, - 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2d, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, - 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x6e, - 0x6b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, - 0x6e, 0x6b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x0e, 0x53, 0x79, 0x6d, 0x6c, 0x69, - 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x46, 0x0a, - 0x0c, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, - 0x09, 0x64, 0x69, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x08, 0x64, 0x69, 0x72, - 0x41, 0x74, 0x74, 0x72, 0x73, 0x22, 0x7f, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, - 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, - 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, - 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, - 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x22, 0x24, 0x0a, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd1, 0x01, 0x0a, - 0x0e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x66, - 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, - 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, - 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x6c, 0x0a, 0x0c, 0x53, 0x68, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x7a, 0x65, 0x72, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x04, 0x7a, 0x65, 0x72, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2a, 0x77, - 0x0a, 0x07, 0x53, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x55, 0x4d, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, - 0x16, 0x0a, 0x12, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x43, 0x33, - 0x32, 0x49, 0x45, 0x45, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x55, 0x4d, 0x5f, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x44, 0x35, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x55, 0x4d, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x03, 0x12, 0x17, - 0x0a, 0x13, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, - 0x32, 0x5f, 0x32, 0x35, 0x36, 0x10, 0x04, 0x2a, 0x2e, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x46, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, - 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x59, 0x4d, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x4f, 0x54, 0x45, 0x4e, 0x56, 0x10, 0x02, 0x2a, 0x5d, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53, - 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, - 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, - 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, - 0x49, 0x4e, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4c, 0x4f, - 0x41, 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x4f, 0x4f, 0x4c, - 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x04, 0x32, 0xf3, 0x07, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x46, 0x69, 0x6c, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1c, 0x2e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x16, 0x2e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, - 0x12, 0x37, 0x0a, 0x03, 0x53, 0x75, 0x6d, 0x12, 0x15, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, - 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x75, 0x6d, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x05, 0x57, 0x72, 0x69, - 0x74, 0x65, 0x12, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x38, 0x0a, 0x04, 0x43, 0x6f, 0x70, 0x79, 0x12, - 0x16, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x43, 0x6f, 0x70, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x00, 0x12, 0x38, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x11, 0x53, - 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x12, 0x23, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x74, - 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x34, 0x0a, 0x02, 0x52, 0x6d, 0x12, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, - 0x65, 0x2e, 0x52, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x52, 0x6d, 0x64, 0x69, 0x72, 0x12, 0x17, - 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x6d, 0x64, 0x69, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, - 0x00, 0x12, 0x3c, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, + 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, + 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x6c, 0x0a, 0x0c, 0x52, 0x6d, 0x64, 0x69, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x72, + 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, + 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, + 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x22, 0x5f, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, + 0x6e, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, + 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x2d, 0x0a, 0x0f, 0x52, 0x65, 0x61, 0x64, 0x6c, + 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, + 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2d, 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, + 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x69, 0x6e, 0x6b, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x6e, 0x6b, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x44, 0x0a, 0x0e, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, + 0x1a, 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x46, 0x0a, 0x0c, 0x4d, + 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x09, 0x64, + 0x69, 0x72, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x08, 0x64, 0x69, 0x72, 0x41, 0x74, + 0x74, 0x72, 0x73, 0x22, 0x7f, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x66, + 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x61, 0x74, + 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x61, 0x74, + 0x61, 0x4b, 0x65, 0x79, 0x22, 0x24, 0x0a, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x0e, 0x44, + 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x66, 0x69, 0x6c, + 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, + 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x46, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x19, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x61, 0x74, 0x61, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x6c, + 0x0a, 0x0c, 0x53, 0x68, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, + 0x72, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x7a, 0x65, 0x72, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, + 0x7a, 0x65, 0x72, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x2a, 0x77, 0x0a, 0x07, + 0x53, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x55, 0x4d, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x16, 0x0a, + 0x12, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x52, 0x43, 0x33, 0x32, 0x49, + 0x45, 0x45, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x4d, 0x44, 0x35, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x55, 0x4d, 0x5f, 0x54, + 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x32, 0x35, 0x36, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, + 0x53, 0x55, 0x4d, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x48, 0x41, 0x35, 0x31, 0x32, 0x5f, + 0x32, 0x35, 0x36, 0x10, 0x04, 0x2a, 0x2e, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x46, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, + 0x12, 0x07, 0x0a, 0x03, 0x59, 0x4d, 0x4c, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x4f, 0x54, + 0x45, 0x4e, 0x56, 0x10, 0x02, 0x2a, 0x5d, 0x0a, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x4b, + 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x54, + 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, + 0x54, 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4c, 0x4f, 0x41, 0x54, + 0x5f, 0x56, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x42, 0x4f, 0x4f, 0x4c, 0x5f, 0x56, + 0x41, 0x4c, 0x10, 0x04, 0x32, 0xf3, 0x07, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, + 0x6c, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1c, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, + 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, 0x12, 0x16, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x37, + 0x0a, 0x03, 0x53, 0x75, 0x6d, 0x12, 0x15, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, + 0x65, 0x2e, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x75, 0x6d, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x05, 0x57, 0x72, 0x69, 0x74, 0x65, + 0x12, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x38, 0x0a, 0x04, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x16, 0x2e, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x42, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, - 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x07, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x19, - 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x79, 0x6d, 0x6c, 0x69, - 0x6e, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x38, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, + 0x69, 0x6c, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x11, 0x53, 0x65, 0x74, + 0x46, 0x69, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x23, + 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x65, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x34, 0x0a, + 0x02, 0x52, 0x6d, 0x12, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, + 0x52, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x17, 0x2e, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, + 0x79, 0x22, 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x52, 0x6d, 0x64, 0x69, 0x72, 0x12, 0x17, 0x2e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x6d, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, - 0x3f, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, - 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, - 0x12, 0x3e, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, - 0x12, 0x3a, 0x0a, 0x05, 0x53, 0x68, 0x72, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x68, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x6e, 0x6f, 0x77, 0x66, - 0x6c, 0x61, 0x6b, 0x65, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x73, 0x61, 0x6e, 0x73, 0x73, 0x68, - 0x65, 0x6c, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6c, 0x6f, 0x63, - 0x61, 0x6c, 0x66, 0x69, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x3c, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, + 0x08, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, + 0x65, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x00, 0x12, 0x3e, 0x0a, 0x07, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x19, 0x2e, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x00, 0x12, 0x3a, 0x0a, 0x05, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x17, 0x2e, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x4d, 0x6b, 0x64, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3f, 0x0a, + 0x07, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, + 0x44, 0x61, 0x74, 0x61, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, + 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x12, 0x19, 0x2e, 0x4c, 0x6f, 0x63, 0x61, + 0x6c, 0x46, 0x69, 0x6c, 0x65, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3a, + 0x0a, 0x05, 0x53, 0x68, 0x72, 0x65, 0x64, 0x12, 0x17, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x46, + 0x69, 0x6c, 0x65, 0x2e, 0x53, 0x68, 0x72, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, + 0x6b, 0x65, 0x2d, 0x4c, 0x61, 0x62, 0x73, 0x2f, 0x73, 0x61, 0x6e, 0x73, 0x73, 0x68, 0x65, 0x6c, + 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x66, 0x69, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/services/localfile/localfile.proto b/services/localfile/localfile.proto index d580ab22..7e1f93b4 100644 --- a/services/localfile/localfile.proto +++ b/services/localfile/localfile.proto @@ -252,12 +252,19 @@ message SetFileAttributesRequest { FileAttributes attrs = 1; } message RmRequest { // The fully qualified path to the file to remove. string filename = 1; + // A list of fully qualified paths to the files to remove + repeated string filenames = 2; } message RmdirRequest { // The fully qualified path to the directory to remove. // Must be empty of any entries. string directory = 1; + // A list of fully qualified paths to the directory to remove. + // Must be either empty of entries or the recursive flag must be specified + repeated string directories = 2; + // Delete nested files and directories if there are any + bool recursive = 3; } message RenameRequest { diff --git a/services/localfile/server/localfile.go b/services/localfile/server/localfile.go index 0b6846da..f5a6384e 100644 --- a/services/localfile/server/localfile.go +++ b/services/localfile/server/localfile.go @@ -26,6 +26,7 @@ import ( "fmt" app "github.com/Snowflake-Labs/sansshell/services/localfile/server/application" "github.com/Snowflake-Labs/sansshell/services/localfile/server/infrastructure/output/file-data" + "github.com/pkg/errors" "hash" "hash/crc32" "io" @@ -715,35 +716,84 @@ func (s *server) SetFileAttributes(ctx context.Context, req *pb.SetFileAttribute func (s *server) Rm(ctx context.Context, req *pb.RmRequest) (*emptypb.Empty, error) { logger := logr.FromContextOrDiscard(ctx) recorder := metrics.RecorderFromContextOrNoop(ctx) - logger.Info("rm request", "filename", req.Filename) - if err := util.ValidPath(req.Filename); err != nil { - recorder.CounterOrLog(ctx, localfileRmFailureCounter, 1, attribute.String("reason", "invalid_path")) - return nil, err + logger.Info("rm request", "filenames", req.Filenames) + + files := make([]string, 0, len(req.Filenames)+1) + if len(req.Filename) > 0 { + files = append(files, req.Filename) } - err := unix.Unlink(req.Filename) - if err != nil { - recorder.CounterOrLog(ctx, localfileRmFailureCounter, 1, attribute.String("reason", "unlink_err")) - return nil, status.Errorf(codes.Internal, "unlink error: %v", err) + files = append(files, req.Filenames...) + + for _, filename := range files { + if err := util.ValidPath(filename); err != nil { + recorder.CounterOrLog(ctx, localfileRmFailureCounter, 1, attribute.String("reason", "invalid_path")) + return nil, err + } } + rmErrors := make([]error, 0, len(files)) + for _, filename := range files { + err := unix.Unlink(filename) + if err != nil { + rmErrors = append(rmErrors, err) + } + } + + if len(rmErrors) > 0 { + recorder.CounterOrLog(ctx, localfileRmFailureCounter, int64(len(rmErrors)), attribute.String("reason", "unlink_err")) + return nil, status.Errorf(codes.Internal, "unlink error: %v", rmErrors) + } + return &emptypb.Empty{}, nil } func (s *server) Rmdir(ctx context.Context, req *pb.RmdirRequest) (*emptypb.Empty, error) { logger := logr.FromContextOrDiscard(ctx) recorder := metrics.RecorderFromContextOrNoop(ctx) - logger.Info("rmdir request", "directory", req.Directory) - if err := util.ValidPath(req.Directory); err != nil { - recorder.CounterOrLog(ctx, localfileRmDirFailureCounter, 1, attribute.String("reason", "invalid_path")) - return nil, err + logger.Info("rmdir request", "directories", req.Directories) + + dirs := make([]string, 0, len(req.Directories)+1) + if len(req.Directory) > 0 { + dirs = append(dirs, req.Directory) } - err := unix.Rmdir(req.Directory) - if err != nil { - recorder.CounterOrLog(ctx, localfileRmDirFailureCounter, 1, attribute.String("reason", "rmdir_err")) - return nil, status.Errorf(codes.Internal, "rmdir error: %v", err) + dirs = append(dirs, req.Directories...) + + for _, dir := range dirs { + if err := util.ValidPath(dir); err != nil { + recorder.CounterOrLog(ctx, localfileRmDirFailureCounter, 1, attribute.String("reason", "invalid_path")) + // fail fast on any invalid path + return nil, err + } + } + rmdirErrors := make([]error, 0, len(dirs)) + for _, dir := range dirs { + var err error + if req.Recursive { + err = RmdirRecursive(dir) + } else { + err = unix.Rmdir(dir) + } + if err != nil { + rmdirErrors = append(rmdirErrors, errors.Errorf("path: %s error: %s", dir, err)) + } } + + if len(rmdirErrors) > 0 { + recorder.CounterOrLog(ctx, localfileRmDirFailureCounter, int64(len(rmdirErrors)), attribute.String("reason", "rmdir_err")) + return nil, status.Errorf(codes.Internal, "rmdir errors: %v", rmdirErrors) + } + return &emptypb.Empty{}, nil } +// RmdirRecursive is an os.RemoveAll wrapper that also checks for file existence since RemoveAll is silent +func RmdirRecursive(path string) error { + _, err := os.Stat(path) + if err != nil { + return unix.ENOENT + } + return os.RemoveAll(path) +} + func (s *server) Rename(ctx context.Context, req *pb.RenameRequest) (*emptypb.Empty, error) { logger := logr.FromContextOrDiscard(ctx) recorder := metrics.RecorderFromContextOrNoop(ctx) diff --git a/services/localfile/server/localfile_test.go b/services/localfile/server/localfile_test.go index 97099219..4f26d17b 100644 --- a/services/localfile/server/localfile_test.go +++ b/services/localfile/server/localfile_test.go @@ -1722,6 +1722,16 @@ func TestRm(t *testing.T) { testutil.FatalOnErr("os.CreateTemp", err, t) err = unix.Chmod(badDir, 0) testutil.FatalOnErr("Chmod", err, t) + f3, err := os.CreateTemp(temp, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) + f4, err := os.CreateTemp(temp, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) + f5, err := os.CreateTemp(temp, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) + oldClientNewServerF1, err := os.CreateTemp(temp, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) + oldClientNewServerF2, err := os.CreateTemp(temp, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) t.Cleanup(func() { // Needed or we panic with generated cleanup trying to remove tmp directories. @@ -1730,29 +1740,44 @@ func TestRm(t *testing.T) { }) for _, tc := range []struct { - name string - filename string - wantErr bool + name string + filename string + filenames []string + wantErr bool }{ { - name: "bad path", - filename: "/tmp/foo/../../etc/passwd", - wantErr: true, + name: "bad path", + filenames: []string{"/tmp/foo/../../etc/passwd"}, + wantErr: true, }, { - name: "bad permissions to file", - filename: f2.Name(), - wantErr: true, + name: "bad permissions to file", + filenames: []string{f2.Name()}, + wantErr: true, + }, + { + name: "working remove", + filenames: []string{f1.Name()}, + }, + { + name: "multiple files", + filenames: []string{f3.Name(), f4.Name()}, + }, + { + name: "multiple files with non-existing file", + filenames: []string{f5.Name(), filepath.Join(temp, "/file-that-definitely-does-not-exist-hopefully-maybe")}, + wantErr: true, }, { - name: "working remove", - filename: f1.Name(), + name: "old client new server", + filename: oldClientNewServerF1.Name(), + filenames: []string{oldClientNewServerF2.Name()}, }, } { tc := tc t.Run(tc.name, func(t *testing.T) { client := pb.NewLocalFileClient(conn) - _, err := client.Rm(ctx, &pb.RmRequest{Filename: tc.filename}) + _, err := client.Rm(ctx, &pb.RmRequest{Filename: tc.filename, Filenames: tc.filenames}) testutil.WantErr(tc.name, err, tc.wantErr, t) }) } @@ -1776,6 +1801,25 @@ func TestRmdir(t *testing.T) { testutil.FatalOnErr("os.Mkdir", err, t) err = unix.Chmod(badDir, 0) testutil.FatalOnErr("Chmod", err, t) + nestedDir := filepath.Join(temp, "/a") + err = os.MkdirAll(filepath.Join(nestedDir, "/b/c"), fs.ModePerm) + testutil.FatalOnErr("os.MkdirAll", err, t) + dirWithFile := filepath.Join(temp, "/dir-with-file") + err = os.Mkdir(dirWithFile, fs.ModePerm) + testutil.FatalOnErr("os.Mkdir", err, t) + _, err = os.CreateTemp(dirWithFile, "testfile.*") + testutil.FatalOnErr("os.CreateTemp", err, t) + dirThatExists := filepath.Join(temp, "/dir-that-exists") + err = os.Mkdir(dirThatExists, fs.ModePerm) + testutil.FatalOnErr("os.Mkdir", err, t) + dirThatDoesNotExist := filepath.Join(temp, "/dir-that-does-not-exist") + // old client new server + oldClientDir1 := filepath.Join(temp, "/old-client-dir1") + err = os.Mkdir(oldClientDir1, fs.ModePerm) + testutil.FatalOnErr("os.Mkdir", err, t) + oldClientDir2 := filepath.Join(temp, "/old-client-dir2") + err = os.Mkdir(oldClientDir2, fs.ModePerm) + testutil.FatalOnErr("os.Mkdir", err, t) t.Cleanup(func() { // Needed or we panic with generated cleanup trying to remove tmp directories. @@ -1784,29 +1828,62 @@ func TestRmdir(t *testing.T) { }) for _, tc := range []struct { - name string - directory string - wantErr bool + name string + directory string + directories []string + recursive bool + wantErr bool }{ { - name: "bad path", - directory: "/tmp/foo/../../etc", - wantErr: true, + name: "bad path", + directories: []string{"/tmp/foo/../../etc"}, + wantErr: true, }, { - name: "bad permissions to directory", - directory: failDir, - wantErr: true, + name: "bad permissions to directory", + directories: []string{failDir}, + wantErr: true, }, { - name: "working remove", - directory: dir, + name: "working remove", + directories: []string{dir}, + }, + { + name: "nested directories failure", + directories: []string{nestedDir}, + wantErr: true, + }, + { + name: "dir with file failure", + directories: []string{dirWithFile}, + wantErr: true, + }, + { + name: "nested directories", + directories: []string{nestedDir}, + recursive: true, + }, + { + name: "dir with file", + directories: []string{dirWithFile}, + recursive: true, + }, + { + name: "dirs that exist and do not", + directories: []string{dirThatExists, dirThatDoesNotExist}, + wantErr: true, + }, + { + name: "old client new server", + directory: oldClientDir1, + directories: []string{oldClientDir2}, + wantErr: false, }, } { tc := tc t.Run(tc.name, func(t *testing.T) { client := pb.NewLocalFileClient(conn) - _, err := client.Rmdir(ctx, &pb.RmdirRequest{Directory: tc.directory}) + _, err := client.Rmdir(ctx, &pb.RmdirRequest{Directory: tc.directory, Directories: tc.directories, Recursive: tc.recursive}) testutil.WantErr(tc.name, err, tc.wantErr, t) }) }