mirror of
				https://github.com/rclone/rclone.git
				synced 2025-10-30 23:17:59 +02:00 
			
		
		
		
	Implement pcloud remote - #418
This commit is contained in:
		| @@ -241,10 +241,11 @@ Research | ||||
| Getting going | ||||
|  | ||||
|   * Create `remote/remote.go` (copy this from a similar remote) | ||||
|     * onedrive is a good one to start from if you have a directory based remote | ||||
|     * box is a good one to start from if you have a directory based remote | ||||
|     * b2 is a good one to start from if you have a bucket based remote | ||||
|   * Add your remote to the imports in `fs/all/all.go` | ||||
|   * HTTP based remotes are easiest to maintain if they use rclone's rest module, but if there is a really good go SDK then use that instead. | ||||
|   * Try to implement as many optional methods as possible as it makes the remote more usable. | ||||
|  | ||||
| Unit tests | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ Rclone is a command line program to sync files and directories to and from | ||||
|   * Microsoft Azure Blob Storage | ||||
|   * Microsoft OneDrive | ||||
|   * Openstack Swift / Rackspace cloud files / Memset Memstore / OVH / Oracle Cloud Storage | ||||
|   * pCloud | ||||
|   * QingStor | ||||
|   * SFTP | ||||
|   * Yandex Disk | ||||
|   | ||||
| @@ -36,6 +36,7 @@ docs = [ | ||||
|     "onedrive.md", | ||||
|     "qingstor.md", | ||||
|     "swift.md", | ||||
|     "pcloud.md", | ||||
|     "sftp.md", | ||||
|     "yandex.md", | ||||
|  | ||||
|   | ||||
| @@ -54,6 +54,7 @@ from various cloud storage systems and using file transfer services, such as: | ||||
|   * Microsoft Azure Blob Storage | ||||
|   * Microsoft OneDrive | ||||
|   * Openstack Swift / Rackspace cloud files / Memset Memstore | ||||
|   * pCloud | ||||
|   * QingStor | ||||
|   * SFTP | ||||
|   * Yandex Disk | ||||
|   | ||||
| @@ -31,6 +31,7 @@ Rclone is a command line program to sync files and directories to and from: | ||||
| * {{< provider name="Minio" home="https://www.minio.io/" config="/s3/#minio" >}} | ||||
| * {{< provider name="OVH" home="https://www.ovh.co.uk/public-cloud/storage/object-storage/" config="/swift/" >}} | ||||
| * {{< provider name="Openstack Swift" home="https://docs.openstack.org/swift/latest/" config="/swift/" >}} | ||||
| * {{< provider name="pCloud" home="https://www.pcloud.com/" config="/pcloud/" >}} | ||||
| * {{< provider name="Oracle Cloud Storage" home="https://cloud.oracle.com/storage-opc" config="/swift/" >}} | ||||
| * {{< provider name="QingStor" home="https://www.qingcloud.com/products/storage" config="/qingstor/" >}} | ||||
| * {{< provider name="Rackspace Cloud Files" home="https://www.rackspace.com/cloud/files" config="/swift/" >}} | ||||
|   | ||||
| @@ -33,6 +33,7 @@ See the following for detailed instructions for | ||||
|   * [Microsoft Azure Blob Storage](/azureblob/) | ||||
|   * [Microsoft OneDrive](/onedrive/) | ||||
|   * [Openstack Swift / Rackspace Cloudfiles / Memset Memstore](/swift/) | ||||
|   * [Pcloud](/pcloud/) | ||||
|   * [QingStor](/qingstor/) | ||||
|   * [SFTP](/sftp/) | ||||
|   * [Yandex Disk](/yandex/) | ||||
|   | ||||
| @@ -30,6 +30,7 @@ Here is an overview of the major features of each cloud storage system. | ||||
| | Microsoft Azure Blob Storage | MD5         | Yes     | No               | No              | R/W       | | ||||
| | Microsoft OneDrive           | SHA1        | Yes     | Yes              | No              | R         | | ||||
| | Openstack Swift              | MD5         | Yes     | No               | No              | R/W       | | ||||
| | pCloud                       | MD5, SHA1   | Yes     | No               | No              | W         | | ||||
| | QingStor                     | MD5         | No      | No               | No              | R/W       | | ||||
| | SFTP                         | MD5, SHA1 ‡ | Yes     | Depends          | No              | -         | | ||||
| | Yandex Disk                  | MD5         | Yes     | No               | No              | R/W       | | ||||
| @@ -130,6 +131,7 @@ operations more efficient. | ||||
| | Microsoft Azure Blob Storage | Yes   | Yes  | No   | No      | No      | Yes   | No           | | ||||
| | Microsoft OneDrive           | Yes   | Yes  | Yes  | No [#197](https://github.com/ncw/rclone/issues/197) | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | | ||||
| | Openstack Swift              | Yes † | Yes  | No   | No      | No      | Yes   | Yes          | | ||||
| | pCloud                       | Yes   | Yes  | Yes  | Yes     | Yes     | No    | No           | | ||||
| | QingStor                     | No    | Yes  | No   | No      | No      | Yes   | No           | | ||||
| | SFTP                         | No    | No   | Yes  | Yes     | No      | No    | Yes          | | ||||
| | Yandex Disk                  | Yes   | No   | No   | No      | Yes     | Yes   | Yes          | | ||||
|   | ||||
							
								
								
									
										135
									
								
								docs/content/pcloud.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								docs/content/pcloud.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| --- | ||||
| title: "pCloud" | ||||
| description: "Rclone docs for pCloud" | ||||
| date: "2017-10-01" | ||||
| --- | ||||
|  | ||||
| <i class="fa fa-cloud"></i> pCloud | ||||
| ----------------------------------------- | ||||
|  | ||||
| Paths are specified as `remote:path` | ||||
|  | ||||
| Paths may be as deep as required, eg `remote:directory/subdirectory`. | ||||
|  | ||||
| The initial setup for pCloud involves getting a token from pCloud which you | ||||
| need to do in your browser.  `rclone config` walks you through it. | ||||
|  | ||||
| Here is an example of how to make a remote called `remote`.  First run: | ||||
|  | ||||
|      rclone config | ||||
|  | ||||
| This will guide you through an interactive setup process: | ||||
|  | ||||
| ``` | ||||
| No remotes found - make a new one | ||||
| n) New remote | ||||
| s) Set configuration password | ||||
| q) Quit config | ||||
| n/s/q> n | ||||
| name> remote | ||||
| Type of storage to configure. | ||||
| Choose a number from below, or type in your own value | ||||
|  1 / Amazon Drive | ||||
|    \ "amazon cloud drive" | ||||
|  2 / Amazon S3 (also Dreamhost, Ceph, Minio) | ||||
|    \ "s3" | ||||
|  3 / Backblaze B2 | ||||
|    \ "b2" | ||||
|  4 / Box | ||||
|    \ "box" | ||||
|  5 / Dropbox | ||||
|    \ "dropbox" | ||||
|  6 / Encrypt/Decrypt a remote | ||||
|    \ "crypt" | ||||
|  7 / FTP Connection | ||||
|    \ "ftp" | ||||
|  8 / Google Cloud Storage (this is not Google Drive) | ||||
|    \ "google cloud storage" | ||||
|  9 / Google Drive | ||||
|    \ "drive" | ||||
| 10 / Hubic | ||||
|    \ "hubic" | ||||
| 11 / Local Disk | ||||
|    \ "local" | ||||
| 12 / Microsoft Azure Blob Storage | ||||
|    \ "azureblob" | ||||
| 13 / Microsoft OneDrive | ||||
|    \ "onedrive" | ||||
| 14 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH) | ||||
|    \ "swift" | ||||
| 15 / Pcloud | ||||
|    \ "pcloud" | ||||
| 16 / QingClound Object Storage | ||||
|    \ "qingstor" | ||||
| 17 / SSH/SFTP Connection | ||||
|    \ "sftp" | ||||
| 18 / Yandex Disk | ||||
|    \ "yandex" | ||||
| 19 / http Connection | ||||
|    \ "http" | ||||
| Storage> pcloud | ||||
| Pcloud App Client Id - leave blank normally. | ||||
| client_id>  | ||||
| Pcloud App Client Secret - leave blank normally. | ||||
| client_secret>  | ||||
| Remote config | ||||
| Use auto config? | ||||
|  * Say Y if not sure | ||||
|  * Say N if you are working on a remote or headless machine | ||||
| y) Yes | ||||
| n) No | ||||
| y/n> y | ||||
| If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth | ||||
| Log in and authorize rclone for access | ||||
| Waiting for code... | ||||
| Got code | ||||
| -------------------- | ||||
| [remote] | ||||
| client_id =  | ||||
| client_secret =  | ||||
| token = {"access_token":"XXX","token_type":"bearer","expiry":"0001-01-01T00:00:00Z"} | ||||
| -------------------- | ||||
| y) Yes this is OK | ||||
| e) Edit this remote | ||||
| d) Delete this remote | ||||
| y/e/d> y | ||||
| ``` | ||||
|  | ||||
| See the [remote setup docs](/remote_setup/) for how to set it up on a | ||||
| machine with no Internet browser available. | ||||
|  | ||||
| Note that rclone runs a webserver on your local machine to collect the | ||||
| token as returned from pCloud. This only runs from the moment it opens | ||||
| your browser to the moment you get back the verification code.  This | ||||
| is on `http://127.0.0.1:53682/` and this it may require you to unblock | ||||
| it temporarily if you are running a host firewall. | ||||
|  | ||||
| Once configured you can then use `rclone` like this, | ||||
|  | ||||
| List directories in top level of your pCloud | ||||
|  | ||||
|     rclone lsd remote: | ||||
|  | ||||
| List all the files in your pCloud | ||||
|  | ||||
|     rclone ls remote: | ||||
|  | ||||
| To copy a local directory to an pCloud directory called backup | ||||
|  | ||||
|     rclone copy /home/source remote:backup | ||||
|  | ||||
| ### Modified time and hashes ### | ||||
|  | ||||
| pCloud allows modification times to be set on objects accurate to 1 | ||||
| second.  These will be used to detect whether objects need syncing or | ||||
| not.  In order to set a Modification time pCloud requires the object | ||||
| be re-uploaded. | ||||
|  | ||||
| pCloud supports MD5 and SHA1 type hashes, so you can use the | ||||
| `--checksum` flag. | ||||
|  | ||||
| ### Deleting files ### | ||||
|  | ||||
| Deleted files will be moved to the trash.  Your subscription level | ||||
| will determine how long items stay in the trash.  `rclone cleanup` can | ||||
| be used to empty the trash. | ||||
| @@ -64,6 +64,7 @@ | ||||
|                     <li><a href="/onedrive/"><i class="fa fa-windows"></i> Microsoft OneDrive</a></li> | ||||
|                     <li><a href="/qingstor/"><i class="fa fa-hdd-o"></i> QingStor</a></li> | ||||
|                     <li><a href="/swift/"><i class="fa fa-space-shuttle"></i> Openstack Swift</a></li> | ||||
|                     <li><a href="/pcloud/"><i class="fa fa-cloud"></i> pCloud</a></li> | ||||
|                     <li><a href="/sftp/"><i class="fa fa-server"></i> SFTP</a></li> | ||||
|                     <li><a href="/yandex/"><i class="fa fa-space-shuttle"></i> Yandex Disk</a></li> | ||||
|                     <li><a href="/local/"><i class="fa fa-file"></i> The local filesystem</a></li> | ||||
|   | ||||
| @@ -15,6 +15,7 @@ import ( | ||||
| 	_ "github.com/ncw/rclone/hubic" | ||||
| 	_ "github.com/ncw/rclone/local" | ||||
| 	_ "github.com/ncw/rclone/onedrive" | ||||
| 	_ "github.com/ncw/rclone/pcloud" | ||||
| 	_ "github.com/ncw/rclone/qingstor" | ||||
| 	_ "github.com/ncw/rclone/s3" | ||||
| 	_ "github.com/ncw/rclone/sftp" | ||||
|   | ||||
| @@ -113,6 +113,11 @@ var ( | ||||
| 			SubDir:   true, | ||||
| 			FastList: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:     "TestPcloud:", | ||||
| 			SubDir:   false, | ||||
| 			FastList: false, | ||||
| 		}, | ||||
| 	} | ||||
| 	binary = "fs.test" | ||||
| 	// Flags | ||||
|   | ||||
| @@ -164,5 +164,6 @@ func main() { | ||||
| 	generateTestProgram(t, fns, "Box") | ||||
| 	generateTestProgram(t, fns, "QingStor", buildConstraint("!plan9")) | ||||
| 	generateTestProgram(t, fns, "AzureBlob", buildConstraint("go1.7")) | ||||
| 	generateTestProgram(t, fns, "Pcloud") | ||||
| 	log.Printf("Done") | ||||
| } | ||||
|   | ||||
							
								
								
									
										153
									
								
								pcloud/api/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								pcloud/api/types.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| // Package api has type definitions for pcloud | ||||
| // | ||||
| // Converted from the API docs with help from https://mholt.github.io/json-to-go/ | ||||
| package api | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Sun, 16 Mar 2014 17:26:04 +0000 | ||||
| 	timeFormat = `"` + time.RFC1123Z + `"` | ||||
| ) | ||||
|  | ||||
| // Time represents represents date and time information for the | ||||
| // pcloud API, by using RFC1123Z | ||||
| type Time time.Time | ||||
|  | ||||
| // MarshalJSON turns a Time into JSON (in UTC) | ||||
| func (t *Time) MarshalJSON() (out []byte, err error) { | ||||
| 	timeString := (*time.Time)(t).Format(timeFormat) | ||||
| 	return []byte(timeString), nil | ||||
| } | ||||
|  | ||||
| // UnmarshalJSON turns JSON into a Time | ||||
| func (t *Time) UnmarshalJSON(data []byte) error { | ||||
| 	newT, err := time.Parse(timeFormat, string(data)) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	*t = Time(newT) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Error is returned from pcloud when things go wrong | ||||
| // | ||||
| // If result is 0 then everything is OK | ||||
| type Error struct { | ||||
| 	Result      int    `json:"result"` | ||||
| 	ErrorString string `json:"error"` | ||||
| } | ||||
|  | ||||
| // Error returns a string for the error and statistifes the error interface | ||||
| func (e *Error) Error() string { | ||||
| 	return fmt.Sprintf("pcloud error: %s (%d)", e.ErrorString, e.Result) | ||||
| } | ||||
|  | ||||
| // Update returns err directly if it was != nil, otherwise it returns | ||||
| // an Error or nil if no error was detected | ||||
| func (e *Error) Update(err error) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if e.Result == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // Check Error statisfies the error interface | ||||
| var _ error = (*Error)(nil) | ||||
|  | ||||
| // Item describes a folder or a file as returned by Get Folder Items and others | ||||
| type Item struct { | ||||
| 	Path           string `json:"path"` | ||||
| 	Name           string `json:"name"` | ||||
| 	Created        Time   `json:"created"` | ||||
| 	IsMine         bool   `json:"ismine"` | ||||
| 	Thumb          bool   `json:"thumb"` | ||||
| 	Modified       Time   `json:"modified"` | ||||
| 	Comments       int    `json:"comments"` | ||||
| 	ID             string `json:"id"` | ||||
| 	IsShared       bool   `json:"isshared"` | ||||
| 	IsDeleted      bool   `json:"isdeleted"` | ||||
| 	Icon           string `json:"icon"` | ||||
| 	IsFolder       bool   `json:"isfolder"` | ||||
| 	ParentFolderID int64  `json:"parentfolderid"` | ||||
| 	FolderID       int64  `json:"folderid,omitempty"` | ||||
| 	Height         int    `json:"height,omitempty"` | ||||
| 	FileID         int64  `json:"fileid,omitempty"` | ||||
| 	Width          int    `json:"width,omitempty"` | ||||
| 	Hash           uint64 `json:"hash,omitempty"` | ||||
| 	Category       int    `json:"category,omitempty"` | ||||
| 	Size           int64  `json:"size,omitempty"` | ||||
| 	ContentType    string `json:"contenttype,omitempty"` | ||||
| 	Contents       []Item `json:"contents"` | ||||
| } | ||||
|  | ||||
| // ModTime returns the modification time of the item | ||||
| func (i *Item) ModTime() (t time.Time) { | ||||
| 	t = time.Time(i.Modified) | ||||
| 	if t.IsZero() { | ||||
| 		t = time.Time(i.Created) | ||||
| 	} | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| // ItemResult is returned from the /listfolder, /createfolder, /deletefolder, /deletefile etc methods | ||||
| type ItemResult struct { | ||||
| 	Error | ||||
| 	Metadata Item `json:"metadata"` | ||||
| } | ||||
|  | ||||
| // Hashes contains the supported hashes | ||||
| type Hashes struct { | ||||
| 	SHA1 string `json:"sha1"` | ||||
| 	MD5  string `json:"md5"` | ||||
| } | ||||
|  | ||||
| // UploadFileResponse is the response from /uploadfile | ||||
| type UploadFileResponse struct { | ||||
| 	Error | ||||
| 	Items     []Item   `json:"metadata"` | ||||
| 	Checksums []Hashes `json:"checksums"` | ||||
| 	Fileids   []int64  `json:"fileids"` | ||||
| } | ||||
|  | ||||
| // GetFileLinkResult is returned from /getfilelink | ||||
| type GetFileLinkResult struct { | ||||
| 	Error | ||||
| 	Dwltag  string   `json:"dwltag"` | ||||
| 	Hash    uint64   `json:"hash"` | ||||
| 	Size    int64    `json:"size"` | ||||
| 	Expires Time     `json:"expires"` | ||||
| 	Path    string   `json:"path"` | ||||
| 	Hosts   []string `json:"hosts"` | ||||
| } | ||||
|  | ||||
| // IsValid returns whether the link is valid and has not expired | ||||
| func (g *GetFileLinkResult) IsValid() bool { | ||||
| 	if g == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	if len(g.Hosts) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
| 	return time.Until(time.Time(g.Expires)) > 30*time.Second | ||||
| } | ||||
|  | ||||
| // URL returns a URL from the Path and Hosts.  Check with IsValid | ||||
| // before calling. | ||||
| func (g *GetFileLinkResult) URL() string { | ||||
| 	// FIXME rotate the hosts? | ||||
| 	return "https://" + g.Hosts[0] + g.Path | ||||
| } | ||||
|  | ||||
| // ChecksumFileResult is returned from /checksumfile | ||||
| type ChecksumFileResult struct { | ||||
| 	Error | ||||
| 	Hashes | ||||
| 	Metadata Item `json:"metadata"` | ||||
| } | ||||
							
								
								
									
										1111
									
								
								pcloud/pcloud.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1111
									
								
								pcloud/pcloud.go
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										73
									
								
								pcloud/pcloud_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								pcloud/pcloud_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| // Test Pcloud filesystem interface | ||||
| // | ||||
| // Automatically generated - DO NOT EDIT | ||||
| // Regenerate with: make gen_tests | ||||
| package pcloud_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/ncw/rclone/fs" | ||||
| 	"github.com/ncw/rclone/fstest/fstests" | ||||
| 	"github.com/ncw/rclone/pcloud" | ||||
| ) | ||||
|  | ||||
| func TestSetup(t *testing.T) { | ||||
| 	fstests.NilObject = fs.Object((*pcloud.Object)(nil)) | ||||
| 	fstests.RemoteName = "TestPcloud:" | ||||
| } | ||||
|  | ||||
| // Generic tests for the Fs | ||||
| func TestInit(t *testing.T)                { fstests.TestInit(t) } | ||||
| func TestFsString(t *testing.T)            { fstests.TestFsString(t) } | ||||
| func TestFsName(t *testing.T)              { fstests.TestFsName(t) } | ||||
| func TestFsRoot(t *testing.T)              { fstests.TestFsRoot(t) } | ||||
| func TestFsRmdirEmpty(t *testing.T)        { fstests.TestFsRmdirEmpty(t) } | ||||
| func TestFsRmdirNotFound(t *testing.T)     { fstests.TestFsRmdirNotFound(t) } | ||||
| func TestFsMkdir(t *testing.T)             { fstests.TestFsMkdir(t) } | ||||
| func TestFsMkdirRmdirSubdir(t *testing.T)  { fstests.TestFsMkdirRmdirSubdir(t) } | ||||
| func TestFsListEmpty(t *testing.T)         { fstests.TestFsListEmpty(t) } | ||||
| func TestFsListDirEmpty(t *testing.T)      { fstests.TestFsListDirEmpty(t) } | ||||
| func TestFsListRDirEmpty(t *testing.T)     { fstests.TestFsListRDirEmpty(t) } | ||||
| func TestFsNewObjectNotFound(t *testing.T) { fstests.TestFsNewObjectNotFound(t) } | ||||
| func TestFsPutFile1(t *testing.T)          { fstests.TestFsPutFile1(t) } | ||||
| func TestFsPutError(t *testing.T)          { fstests.TestFsPutError(t) } | ||||
| func TestFsPutFile2(t *testing.T)          { fstests.TestFsPutFile2(t) } | ||||
| func TestFsUpdateFile1(t *testing.T)       { fstests.TestFsUpdateFile1(t) } | ||||
| func TestFsListDirFile2(t *testing.T)      { fstests.TestFsListDirFile2(t) } | ||||
| func TestFsListRDirFile2(t *testing.T)     { fstests.TestFsListRDirFile2(t) } | ||||
| func TestFsListDirRoot(t *testing.T)       { fstests.TestFsListDirRoot(t) } | ||||
| func TestFsListRDirRoot(t *testing.T)      { fstests.TestFsListRDirRoot(t) } | ||||
| func TestFsListSubdir(t *testing.T)        { fstests.TestFsListSubdir(t) } | ||||
| func TestFsListRSubdir(t *testing.T)       { fstests.TestFsListRSubdir(t) } | ||||
| func TestFsListLevel2(t *testing.T)        { fstests.TestFsListLevel2(t) } | ||||
| func TestFsListRLevel2(t *testing.T)       { fstests.TestFsListRLevel2(t) } | ||||
| func TestFsListFile1(t *testing.T)         { fstests.TestFsListFile1(t) } | ||||
| func TestFsNewObject(t *testing.T)         { fstests.TestFsNewObject(t) } | ||||
| func TestFsListFile1and2(t *testing.T)     { fstests.TestFsListFile1and2(t) } | ||||
| func TestFsNewObjectDir(t *testing.T)      { fstests.TestFsNewObjectDir(t) } | ||||
| func TestFsCopy(t *testing.T)              { fstests.TestFsCopy(t) } | ||||
| func TestFsMove(t *testing.T)              { fstests.TestFsMove(t) } | ||||
| func TestFsDirMove(t *testing.T)           { fstests.TestFsDirMove(t) } | ||||
| func TestFsRmdirFull(t *testing.T)         { fstests.TestFsRmdirFull(t) } | ||||
| func TestFsPrecision(t *testing.T)         { fstests.TestFsPrecision(t) } | ||||
| func TestFsDirChangeNotify(t *testing.T)   { fstests.TestFsDirChangeNotify(t) } | ||||
| func TestObjectString(t *testing.T)        { fstests.TestObjectString(t) } | ||||
| func TestObjectFs(t *testing.T)            { fstests.TestObjectFs(t) } | ||||
| func TestObjectRemote(t *testing.T)        { fstests.TestObjectRemote(t) } | ||||
| func TestObjectHashes(t *testing.T)        { fstests.TestObjectHashes(t) } | ||||
| func TestObjectModTime(t *testing.T)       { fstests.TestObjectModTime(t) } | ||||
| func TestObjectMimeType(t *testing.T)      { fstests.TestObjectMimeType(t) } | ||||
| func TestObjectSetModTime(t *testing.T)    { fstests.TestObjectSetModTime(t) } | ||||
| func TestObjectSize(t *testing.T)          { fstests.TestObjectSize(t) } | ||||
| func TestObjectOpen(t *testing.T)          { fstests.TestObjectOpen(t) } | ||||
| func TestObjectOpenSeek(t *testing.T)      { fstests.TestObjectOpenSeek(t) } | ||||
| func TestObjectPartialRead(t *testing.T)   { fstests.TestObjectPartialRead(t) } | ||||
| func TestObjectUpdate(t *testing.T)        { fstests.TestObjectUpdate(t) } | ||||
| func TestObjectStorable(t *testing.T)      { fstests.TestObjectStorable(t) } | ||||
| func TestFsIsFile(t *testing.T)            { fstests.TestFsIsFile(t) } | ||||
| func TestFsIsFileNotFound(t *testing.T)    { fstests.TestFsIsFileNotFound(t) } | ||||
| func TestObjectRemove(t *testing.T)        { fstests.TestObjectRemove(t) } | ||||
| func TestFsPutStream(t *testing.T)         { fstests.TestFsPutStream(t) } | ||||
| func TestObjectPurge(t *testing.T)         { fstests.TestObjectPurge(t) } | ||||
| func TestFinalise(t *testing.T)            { fstests.TestFinalise(t) } | ||||
		Reference in New Issue
	
	Block a user