github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/seafile/object.go (about)

     1  package seafile
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"time"
     7  
     8  	"github.com/rclone/rclone/fs"
     9  	"github.com/rclone/rclone/fs/hash"
    10  )
    11  
    12  // Object describes a seafile object (also commonly called a file)
    13  type Object struct {
    14  	fs            *Fs       // what this object is part of
    15  	id            string    // internal ID of object
    16  	remote        string    // The remote path (full path containing library name if target at root)
    17  	pathInLibrary string    // Path of the object without the library name
    18  	size          int64     // size of the object
    19  	modTime       time.Time // modification time of the object
    20  	libraryID     string    // Needed to download the file
    21  }
    22  
    23  // ==================== Interface fs.DirEntry ====================
    24  
    25  // Return a string version
    26  func (o *Object) String() string {
    27  	if o == nil {
    28  		return "<nil>"
    29  	}
    30  	return o.remote
    31  }
    32  
    33  // Remote returns the remote string
    34  func (o *Object) Remote() string {
    35  	return o.remote
    36  }
    37  
    38  // ModTime returns last modified time
    39  func (o *Object) ModTime(context.Context) time.Time {
    40  	return o.modTime
    41  }
    42  
    43  // Size returns the size of an object in bytes
    44  func (o *Object) Size() int64 {
    45  	return o.size
    46  }
    47  
    48  // ==================== Interface fs.ObjectInfo ====================
    49  
    50  // Fs returns the parent Fs
    51  func (o *Object) Fs() fs.Info {
    52  	return o.fs
    53  }
    54  
    55  // Hash returns the selected checksum of the file
    56  // If no checksum is available it returns ""
    57  func (o *Object) Hash(ctx context.Context, ty hash.Type) (string, error) {
    58  	return "", hash.ErrUnsupported
    59  }
    60  
    61  // Storable says whether this object can be stored
    62  func (o *Object) Storable() bool {
    63  	return true
    64  }
    65  
    66  // ==================== Interface fs.Object ====================
    67  
    68  // SetModTime sets the metadata on the object to set the modification date
    69  func (o *Object) SetModTime(ctx context.Context, t time.Time) error {
    70  	return fs.ErrorCantSetModTime
    71  }
    72  
    73  // Open opens the file for read.  Call Close() on the returned io.ReadCloser
    74  func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
    75  	downloadLink, err := o.fs.getDownloadLink(ctx, o.libraryID, o.pathInLibrary)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	reader, err := o.fs.download(ctx, downloadLink, o.Size(), options...)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	return reader, nil
    84  }
    85  
    86  // Update in to the object with the modTime given of the given size
    87  //
    88  // When called from outside an Fs by rclone, src.Size() will always be >= 0.
    89  // But for unknown-sized objects (indicated by src.Size() == -1), Upload should either
    90  // return an error or update the object properly (rather than e.g. calling panic).
    91  func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
    92  	// The upload sometimes return a temporary 500 error
    93  	// We cannot use the pacer to retry uploading the file as the upload link is single use only
    94  	for retry := 0; retry <= 3; retry++ {
    95  		uploadLink, err := o.fs.getUploadLink(ctx, o.libraryID)
    96  		if err != nil {
    97  			return err
    98  		}
    99  
   100  		uploaded, err := o.fs.upload(ctx, in, uploadLink, o.pathInLibrary)
   101  		if err == ErrorInternalDuringUpload {
   102  			// This is a temporary error, try again with a new upload link
   103  			continue
   104  		}
   105  		if err != nil {
   106  			return err
   107  		}
   108  		// Set the properties from the upload back to the object
   109  		o.size = uploaded.Size
   110  		o.id = uploaded.ID
   111  
   112  		return nil
   113  	}
   114  	return ErrorInternalDuringUpload
   115  }
   116  
   117  // Remove this object
   118  func (o *Object) Remove(ctx context.Context) error {
   119  	return o.fs.deleteFile(ctx, o.libraryID, o.pathInLibrary)
   120  }
   121  
   122  // ==================== Optional Interface fs.IDer ====================
   123  
   124  // ID returns the ID of the Object if known, or "" if not
   125  func (o *Object) ID() string {
   126  	return o.id
   127  }