mirror of
https://github.com/rclone/rclone.git
synced 2025-12-11 22:14:05 +01:00
Add context propagation to rclone
- Change rclone/fs interfaces to accept context.Context - Update interface implementations to use context.Context - Change top level usage to propagate context to lover level functions Context propagation is needed for stopping transfers and passing other request-scoped values.
This commit is contained in:
committed by
Nick Craig-Wood
parent
a2c317b46e
commit
f78cd1e043
83
fs/fs.go
83
fs/fs.go
@@ -2,6 +2,7 @@
|
||||
package fs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -245,11 +246,11 @@ type Fs interface {
|
||||
//
|
||||
// This should return ErrDirNotFound if the directory isn't
|
||||
// found.
|
||||
List(dir string) (entries DirEntries, err error)
|
||||
List(ctx context.Context, dir string) (entries DirEntries, err error)
|
||||
|
||||
// NewObject finds the Object at remote. If it can't be found
|
||||
// it returns the error ErrorObjectNotFound.
|
||||
NewObject(remote string) (Object, error)
|
||||
NewObject(ctx context.Context, remote string) (Object, error)
|
||||
|
||||
// Put in to the remote path with the modTime given of the given size
|
||||
//
|
||||
@@ -260,17 +261,17 @@ type Fs interface {
|
||||
// May create the object even if it returns an error - if so
|
||||
// will return the object and the error, otherwise will return
|
||||
// nil and the error
|
||||
Put(in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
Put(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
|
||||
// Mkdir makes the directory (container, bucket)
|
||||
//
|
||||
// Shouldn't return an error if it already exists
|
||||
Mkdir(dir string) error
|
||||
Mkdir(ctx context.Context, dir string) error
|
||||
|
||||
// Rmdir removes the directory (container, bucket) if empty
|
||||
//
|
||||
// Return an error if it doesn't exist or isn't empty
|
||||
Rmdir(dir string) error
|
||||
Rmdir(ctx context.Context, dir string) error
|
||||
}
|
||||
|
||||
// Info provides a read only interface to information about a filesystem.
|
||||
@@ -299,20 +300,20 @@ type Object interface {
|
||||
ObjectInfo
|
||||
|
||||
// SetModTime sets the metadata on the object to set the modification date
|
||||
SetModTime(time.Time) error
|
||||
SetModTime(ctx context.Context, t time.Time) error
|
||||
|
||||
// Open opens the file for read. Call Close() on the returned io.ReadCloser
|
||||
Open(options ...OpenOption) (io.ReadCloser, error)
|
||||
Open(ctx context.Context, options ...OpenOption) (io.ReadCloser, error)
|
||||
|
||||
// Update in to the object with the modTime given of the given size
|
||||
//
|
||||
// When called from outside a Fs by rclone, src.Size() will always be >= 0.
|
||||
// But for unknown-sized objects (indicated by src.Size() == -1), Upload should either
|
||||
// return an error or update the object properly (rather than e.g. calling panic).
|
||||
Update(in io.Reader, src ObjectInfo, options ...OpenOption) error
|
||||
Update(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) error
|
||||
|
||||
// Removes this object
|
||||
Remove() error
|
||||
Remove(ctx context.Context) error
|
||||
}
|
||||
|
||||
// ObjectInfo provides read only information about an object.
|
||||
@@ -324,7 +325,7 @@ type ObjectInfo interface {
|
||||
|
||||
// Hash returns the selected checksum of the file
|
||||
// If no checksum is available it returns ""
|
||||
Hash(hash.Type) (string, error)
|
||||
Hash(ctx context.Context, ty hash.Type) (string, error)
|
||||
|
||||
// Storable says whether this object can be stored
|
||||
Storable() bool
|
||||
@@ -342,7 +343,7 @@ type DirEntry interface {
|
||||
|
||||
// ModTime returns the modification date of the file
|
||||
// It should return a best guess if one isn't available
|
||||
ModTime() time.Time
|
||||
ModTime(context.Context) time.Time
|
||||
|
||||
// Size returns the size of the file
|
||||
Size() int64
|
||||
@@ -365,7 +366,7 @@ type Directory interface {
|
||||
type MimeTyper interface {
|
||||
// MimeType returns the content type of the Object if
|
||||
// known, or "" if not
|
||||
MimeType() string
|
||||
MimeType(ctx context.Context) string
|
||||
}
|
||||
|
||||
// IDer is an optional interface for Object
|
||||
@@ -430,7 +431,7 @@ func ObjectOptionalInterfaces(o Object) (supported, unsupported []string) {
|
||||
type ListRCallback func(entries DirEntries) error
|
||||
|
||||
// ListRFn is defines the call used to recursively list a directory
|
||||
type ListRFn func(dir string, callback ListRCallback) error
|
||||
type ListRFn func(ctx context.Context, dir string, callback ListRCallback) error
|
||||
|
||||
// NewUsageValue makes a valid value
|
||||
func NewUsageValue(value int64) *int64 {
|
||||
@@ -476,7 +477,7 @@ type Features struct {
|
||||
// quicker than just running Remove() on the result of List()
|
||||
//
|
||||
// Return an error if it doesn't exist
|
||||
Purge func() error
|
||||
Purge func(ctx context.Context) error
|
||||
|
||||
// Copy src to this remote using server side copy operations.
|
||||
//
|
||||
@@ -487,7 +488,7 @@ type Features struct {
|
||||
// Will only be called if src.Fs().Name() == f.Name()
|
||||
//
|
||||
// If it isn't possible then return fs.ErrorCantCopy
|
||||
Copy func(src Object, remote string) (Object, error)
|
||||
Copy func(ctx context.Context, src Object, remote string) (Object, error)
|
||||
|
||||
// Move src to this remote using server side move operations.
|
||||
//
|
||||
@@ -498,7 +499,7 @@ type Features struct {
|
||||
// Will only be called if src.Fs().Name() == f.Name()
|
||||
//
|
||||
// If it isn't possible then return fs.ErrorCantMove
|
||||
Move func(src Object, remote string) (Object, error)
|
||||
Move func(ctx context.Context, src Object, remote string) (Object, error)
|
||||
|
||||
// DirMove moves src, srcRemote to this remote at dstRemote
|
||||
// using server side move operations.
|
||||
@@ -508,12 +509,12 @@ type Features struct {
|
||||
// If it isn't possible then return fs.ErrorCantDirMove
|
||||
//
|
||||
// If destination exists then return fs.ErrorDirExists
|
||||
DirMove func(src Fs, srcRemote, dstRemote string) error
|
||||
DirMove func(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
||||
|
||||
// ChangeNotify calls the passed function with a path
|
||||
// that has had changes. If the implementation
|
||||
// uses polling, it should adhere to the given interval.
|
||||
ChangeNotify func(func(string, EntryType), <-chan time.Duration)
|
||||
ChangeNotify func(context.Context, func(string, EntryType), <-chan time.Duration)
|
||||
|
||||
// UnWrap returns the Fs that this Fs is wrapping
|
||||
UnWrap func() Fs
|
||||
@@ -529,7 +530,7 @@ type Features struct {
|
||||
DirCacheFlush func()
|
||||
|
||||
// PublicLink generates a public link to the remote path (usually readable by anyone)
|
||||
PublicLink func(remote string) (string, error)
|
||||
PublicLink func(ctx context.Context, remote string) (string, error)
|
||||
|
||||
// Put in to the remote path with the modTime given of the given size
|
||||
//
|
||||
@@ -539,24 +540,24 @@ type Features struct {
|
||||
//
|
||||
// May create duplicates or return errors if src already
|
||||
// exists.
|
||||
PutUnchecked func(in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
PutUnchecked func(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
|
||||
// PutStream uploads to the remote path with the modTime given of indeterminate size
|
||||
//
|
||||
// May create the object even if it returns an error - if so
|
||||
// will return the object and the error, otherwise will return
|
||||
// nil and the error
|
||||
PutStream func(in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
PutStream func(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
|
||||
// MergeDirs merges the contents of all the directories passed
|
||||
// in into the first one and rmdirs the other directories.
|
||||
MergeDirs func([]Directory) error
|
||||
MergeDirs func(ctx context.Context, dirs []Directory) error
|
||||
|
||||
// CleanUp the trash in the Fs
|
||||
//
|
||||
// Implement this if you have a way of emptying the trash or
|
||||
// otherwise cleaning up old versions of files.
|
||||
CleanUp func() error
|
||||
CleanUp func(ctx context.Context) error
|
||||
|
||||
// ListR lists the objects and directories of the Fs starting
|
||||
// from dir recursively into out.
|
||||
@@ -577,14 +578,14 @@ type Features struct {
|
||||
ListR ListRFn
|
||||
|
||||
// About gets quota information from the Fs
|
||||
About func() (*Usage, error)
|
||||
About func(ctx context.Context) (*Usage, error)
|
||||
|
||||
// OpenWriterAt opens with a handle for random access writes
|
||||
//
|
||||
// Pass in the remote desired and the size if known.
|
||||
//
|
||||
// It truncates any existing object
|
||||
OpenWriterAt func(remote string, size int64) (WriterAtCloser, error)
|
||||
OpenWriterAt func(ctx context.Context, remote string, size int64) (WriterAtCloser, error)
|
||||
}
|
||||
|
||||
// Disable nil's out the named feature. If it isn't found then it
|
||||
@@ -803,7 +804,7 @@ type Purger interface {
|
||||
// quicker than just running Remove() on the result of List()
|
||||
//
|
||||
// Return an error if it doesn't exist
|
||||
Purge() error
|
||||
Purge(ctx context.Context) error
|
||||
}
|
||||
|
||||
// Copier is an optional interface for Fs
|
||||
@@ -817,7 +818,7 @@ type Copier interface {
|
||||
// Will only be called if src.Fs().Name() == f.Name()
|
||||
//
|
||||
// If it isn't possible then return fs.ErrorCantCopy
|
||||
Copy(src Object, remote string) (Object, error)
|
||||
Copy(ctx context.Context, src Object, remote string) (Object, error)
|
||||
}
|
||||
|
||||
// Mover is an optional interface for Fs
|
||||
@@ -831,7 +832,7 @@ type Mover interface {
|
||||
// Will only be called if src.Fs().Name() == f.Name()
|
||||
//
|
||||
// If it isn't possible then return fs.ErrorCantMove
|
||||
Move(src Object, remote string) (Object, error)
|
||||
Move(ctx context.Context, src Object, remote string) (Object, error)
|
||||
}
|
||||
|
||||
// DirMover is an optional interface for Fs
|
||||
@@ -844,7 +845,7 @@ type DirMover interface {
|
||||
// If it isn't possible then return fs.ErrorCantDirMove
|
||||
//
|
||||
// If destination exists then return fs.ErrorDirExists
|
||||
DirMove(src Fs, srcRemote, dstRemote string) error
|
||||
DirMove(ctx context.Context, src Fs, srcRemote, dstRemote string) error
|
||||
}
|
||||
|
||||
// ChangeNotifier is an optional interface for Fs
|
||||
@@ -858,7 +859,7 @@ type ChangeNotifier interface {
|
||||
// The ChangeNotify implementation must empty the channel
|
||||
// regularly. When the channel gets closed, the implementation
|
||||
// should stop polling and release resources.
|
||||
ChangeNotify(func(string, EntryType), <-chan time.Duration)
|
||||
ChangeNotify(context.Context, func(string, EntryType), <-chan time.Duration)
|
||||
}
|
||||
|
||||
// UnWrapper is an optional interfaces for Fs
|
||||
@@ -892,7 +893,7 @@ type PutUncheckeder interface {
|
||||
//
|
||||
// May create duplicates or return errors if src already
|
||||
// exists.
|
||||
PutUnchecked(in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
PutUnchecked(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
}
|
||||
|
||||
// PutStreamer is an optional interface for Fs
|
||||
@@ -902,20 +903,20 @@ type PutStreamer interface {
|
||||
// May create the object even if it returns an error - if so
|
||||
// will return the object and the error, otherwise will return
|
||||
// nil and the error
|
||||
PutStream(in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
PutStream(ctx context.Context, in io.Reader, src ObjectInfo, options ...OpenOption) (Object, error)
|
||||
}
|
||||
|
||||
// PublicLinker is an optional interface for Fs
|
||||
type PublicLinker interface {
|
||||
// PublicLink generates a public link to the remote path (usually readable by anyone)
|
||||
PublicLink(remote string) (string, error)
|
||||
PublicLink(ctx context.Context, remote string) (string, error)
|
||||
}
|
||||
|
||||
// MergeDirser is an option interface for Fs
|
||||
type MergeDirser interface {
|
||||
// MergeDirs merges the contents of all the directories passed
|
||||
// in into the first one and rmdirs the other directories.
|
||||
MergeDirs([]Directory) error
|
||||
MergeDirs(ctx context.Context, dirs []Directory) error
|
||||
}
|
||||
|
||||
// CleanUpper is an optional interfaces for Fs
|
||||
@@ -924,7 +925,7 @@ type CleanUpper interface {
|
||||
//
|
||||
// Implement this if you have a way of emptying the trash or
|
||||
// otherwise cleaning up old versions of files.
|
||||
CleanUp() error
|
||||
CleanUp(ctx context.Context) error
|
||||
}
|
||||
|
||||
// ListRer is an optional interfaces for Fs
|
||||
@@ -945,7 +946,7 @@ type ListRer interface {
|
||||
//
|
||||
// Don't implement this unless you have a more efficient way
|
||||
// of listing recursively that doing a directory traversal.
|
||||
ListR(dir string, callback ListRCallback) error
|
||||
ListR(ctx context.Context, dir string, callback ListRCallback) error
|
||||
}
|
||||
|
||||
// RangeSeeker is the interface that wraps the RangeSeek method.
|
||||
@@ -958,13 +959,13 @@ type RangeSeeker interface {
|
||||
// limiting the total length to limit.
|
||||
//
|
||||
// RangeSeek with a limit of < 0 is equivalent to a regular Seek.
|
||||
RangeSeek(offset int64, whence int, length int64) (int64, error)
|
||||
RangeSeek(ctx context.Context, offset int64, whence int, length int64) (int64, error)
|
||||
}
|
||||
|
||||
// Abouter is an optional interface for Fs
|
||||
type Abouter interface {
|
||||
// About gets quota information from the Fs
|
||||
About() (*Usage, error)
|
||||
About(ctx context.Context) (*Usage, error)
|
||||
}
|
||||
|
||||
// OpenWriterAter is an optional interface for Fs
|
||||
@@ -974,7 +975,7 @@ type OpenWriterAter interface {
|
||||
// Pass in the remote desired and the size if known.
|
||||
//
|
||||
// It truncates any existing object
|
||||
OpenWriterAt(remote string, size int64) (WriterAtCloser, error)
|
||||
OpenWriterAt(ctx context.Context, remote string, size int64) (WriterAtCloser, error)
|
||||
}
|
||||
|
||||
// ObjectsChan is a channel of Objects
|
||||
@@ -1195,8 +1196,8 @@ func CheckClose(c io.Closer, err *error) {
|
||||
|
||||
// FileExists returns true if a file remote exists.
|
||||
// If remote is a directory, FileExists returns false.
|
||||
func FileExists(fs Fs, remote string) (bool, error) {
|
||||
_, err := fs.NewObject(remote)
|
||||
func FileExists(ctx context.Context, fs Fs, remote string) (bool, error) {
|
||||
_, err := fs.NewObject(ctx, remote)
|
||||
if err != nil {
|
||||
if err == ErrorObjectNotFound || err == ErrorNotAFile || err == ErrorPermissionDenied {
|
||||
return false, nil
|
||||
|
||||
Reference in New Issue
Block a user