github.com/cs3org/reva/v2@v2.27.7/pkg/sdk/action/fileops.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package action
    20  
    21  import (
    22  	"fmt"
    23  	p "path"
    24  	"strings"
    25  
    26  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    27  	storage "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    28  
    29  	"github.com/cs3org/reva/v2/pkg/sdk"
    30  	"github.com/cs3org/reva/v2/pkg/sdk/common/net"
    31  )
    32  
    33  // FileOperationsAction offers basic file operations.
    34  type FileOperationsAction struct {
    35  	action
    36  }
    37  
    38  // Stat queries the file information of the specified remote resource.
    39  func (action *FileOperationsAction) Stat(path string) (*storage.ResourceInfo, error) {
    40  	ref := &provider.Reference{Path: path}
    41  	req := &provider.StatRequest{Ref: ref}
    42  	res, err := action.session.Client().Stat(action.session.Context(), req)
    43  	if err := net.CheckRPCInvocation("querying resource information", res, err); err != nil {
    44  		return nil, err
    45  	}
    46  	return res.Info, nil
    47  }
    48  
    49  // FileExists checks whether the specified file exists.
    50  func (action *FileOperationsAction) FileExists(path string) bool {
    51  	// Stat the file and see if that succeeds; if so, check if the resource is indeed a file
    52  	info, err := action.Stat(path)
    53  	if err != nil {
    54  		return false
    55  	}
    56  	return info.Type == provider.ResourceType_RESOURCE_TYPE_FILE
    57  }
    58  
    59  // DirExists checks whether the specified directory exists.
    60  func (action *FileOperationsAction) DirExists(path string) bool {
    61  	// Stat the file and see if that succeeds; if so, check if the resource is indeed a directory
    62  	info, err := action.Stat(path)
    63  	if err != nil {
    64  		return false
    65  	}
    66  	return info.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER
    67  }
    68  
    69  // ResourceExists checks whether the specified resource exists (w/o checking for its actual type).
    70  func (action *FileOperationsAction) ResourceExists(path string) bool {
    71  	// Stat the file and see if that succeeds
    72  	_, err := action.Stat(path)
    73  	return err == nil
    74  }
    75  
    76  // MakePath creates the entire directory tree specified by the given path.
    77  func (action *FileOperationsAction) MakePath(path string) error {
    78  	path = strings.TrimPrefix(path, "/")
    79  
    80  	var curPath string
    81  	for _, token := range strings.Split(path, "/") {
    82  		curPath = p.Join(curPath, "/"+token)
    83  
    84  		fileInfo, err := action.Stat(curPath)
    85  		if err != nil { // Stating failed, so the path probably doesn't exist yet
    86  			ref := &provider.Reference{Path: curPath}
    87  			req := &provider.CreateContainerRequest{Ref: ref}
    88  			res, err := action.session.Client().CreateContainer(action.session.Context(), req)
    89  			if err := net.CheckRPCInvocation("creating container", res, err); err != nil {
    90  				return err
    91  			}
    92  		} else if fileInfo.Type != provider.ResourceType_RESOURCE_TYPE_CONTAINER {
    93  			// The path exists, so make sure that is actually a directory
    94  			return fmt.Errorf("'%v' is not a directory", curPath)
    95  		}
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  // Move moves the specified source to a new location. The caller must ensure that the target directory exists.
   102  func (action *FileOperationsAction) Move(source string, target string) error {
   103  	sourceRef := &provider.Reference{Path: source}
   104  	targetRef := &provider.Reference{Path: target}
   105  	req := &provider.MoveRequest{Source: sourceRef, Destination: targetRef}
   106  	res, err := action.session.Client().Move(action.session.Context(), req)
   107  	if err := net.CheckRPCInvocation("moving resource", res, err); err != nil {
   108  		return err
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  // MoveTo moves the specified source to the target directory, creating it if necessary.
   115  func (action *FileOperationsAction) MoveTo(source string, path string) error {
   116  	if err := action.MakePath(path); err != nil {
   117  		return fmt.Errorf("unable to create the target directory '%v': %v", path, err)
   118  	}
   119  
   120  	path = p.Join(path, p.Base(source)) // Keep the original resource base name
   121  	return action.Move(source, path)
   122  }
   123  
   124  // Remove deletes the specified resource.
   125  func (action *FileOperationsAction) Remove(path string) error {
   126  	ref := &provider.Reference{Path: path}
   127  	req := &provider.DeleteRequest{Ref: ref}
   128  	res, err := action.session.Client().Delete(action.session.Context(), req)
   129  	if err := net.CheckRPCInvocation("deleting resource", res, err); err != nil {
   130  		return err
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  // NewFileOperationsAction creates a new file operations action.
   137  func NewFileOperationsAction(session *sdk.Session) (*FileOperationsAction, error) {
   138  	action := &FileOperationsAction{}
   139  	if err := action.initAction(session); err != nil {
   140  		return nil, fmt.Errorf("unable to create the FileOperationsAction: %v", err)
   141  	}
   142  	return action, nil
   143  }
   144  
   145  // MustNewFileOperationsAction creates a new file operations action and panics on failure.
   146  func MustNewFileOperationsAction(session *sdk.Session) *FileOperationsAction {
   147  	action, err := NewFileOperationsAction(session)
   148  	if err != nil {
   149  		panic(err)
   150  	}
   151  	return action
   152  }