forked from TrueCloudLab/rclone
about: add new command 'about' to get quota info from a remote
Implemented for drive only. Relates to #1138 and #1564.
This commit is contained in:
parent
b83814082b
commit
94e277d759
9 changed files with 130 additions and 21 deletions
13
backend/cache/cache.go
vendored
13
backend/cache/cache.go
vendored
|
@ -1413,6 +1413,18 @@ func (f *Fs) CleanUp() error {
|
||||||
return do()
|
return do()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// About gets quota information from the Fs
|
||||||
|
func (f *Fs) About() error {
|
||||||
|
f.CleanUpCache(false)
|
||||||
|
|
||||||
|
do := f.Fs.Features().About
|
||||||
|
if do == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return do()
|
||||||
|
}
|
||||||
|
|
||||||
// Stats returns stats about the cache storage
|
// Stats returns stats about the cache storage
|
||||||
func (f *Fs) Stats() (map[string]map[string]interface{}, error) {
|
func (f *Fs) Stats() (map[string]map[string]interface{}, error) {
|
||||||
return f.cache.Stats()
|
return f.cache.Stats()
|
||||||
|
@ -1551,4 +1563,5 @@ var (
|
||||||
_ fs.Wrapper = (*Fs)(nil)
|
_ fs.Wrapper = (*Fs)(nil)
|
||||||
_ fs.ListRer = (*Fs)(nil)
|
_ fs.ListRer = (*Fs)(nil)
|
||||||
_ fs.ChangeNotifier = (*Fs)(nil)
|
_ fs.ChangeNotifier = (*Fs)(nil)
|
||||||
|
_ fs.Abouter = (*Fs)(nil)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1050,6 +1050,29 @@ func (f *Fs) CleanUp() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// About gets quota information
|
||||||
|
func (f *Fs) About() error {
|
||||||
|
var about *drive.About
|
||||||
|
var err error
|
||||||
|
err = f.pacer.Call(func() (bool, error) {
|
||||||
|
about, err = f.svc.About.Get().Fields("storageQuota").Do()
|
||||||
|
return shouldRetry(err)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fs.Errorf(f, "Failed to get Drive storageQuota: %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
quota := float64(about.StorageQuota.Limit) / (1 << 30)
|
||||||
|
usagetotal := float64(about.StorageQuota.Usage) / (1 << 30)
|
||||||
|
usagedrive := float64(about.StorageQuota.UsageInDrive) / (1 << 30)
|
||||||
|
usagetrash := float64(about.StorageQuota.UsageInDriveTrash) / (1 << 30)
|
||||||
|
fmt.Printf("Quota: %.0f GiB | Used: %.1f GiB (Trash: %.1f GiB) | Available: %.1f GiB | Usage: %d%%\n",
|
||||||
|
quota, usagedrive, usagetrash, quota-usagedrive, int((usagedrive/quota)*100))
|
||||||
|
fmt.Printf("Space used in other Google services (such as Gmail): %.2f GiB\n",
|
||||||
|
usagetotal-usagedrive)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Move src to this remote using server side move operations.
|
// Move src to this remote using server side move operations.
|
||||||
//
|
//
|
||||||
// This is stored with the remote path given
|
// This is stored with the remote path given
|
||||||
|
|
27
cmd/about/about.go
Normal file
27
cmd/about/about.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package about
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ncw/rclone/cmd"
|
||||||
|
"github.com/ncw/rclone/fs/operations"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
cmd.Root.AddCommand(commandDefintion)
|
||||||
|
}
|
||||||
|
|
||||||
|
var commandDefintion = &cobra.Command{
|
||||||
|
Use: "about remote:",
|
||||||
|
Short: `Get quota information from the remote.`,
|
||||||
|
Long: `
|
||||||
|
Get quota information from the remote, like bytes used/free/quota and bytes
|
||||||
|
used in the trash. Not supported by all remotes.
|
||||||
|
`,
|
||||||
|
Run: func(command *cobra.Command, args []string) {
|
||||||
|
cmd.CheckArgs(1, 1, command, args)
|
||||||
|
fsrc := cmd.NewFsSrc(args)
|
||||||
|
cmd.Run(true, false, command, func() error {
|
||||||
|
return operations.About(fsrc)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ package all
|
||||||
import (
|
import (
|
||||||
// Active commands
|
// Active commands
|
||||||
_ "github.com/ncw/rclone/cmd"
|
_ "github.com/ncw/rclone/cmd"
|
||||||
|
_ "github.com/ncw/rclone/cmd/about"
|
||||||
_ "github.com/ncw/rclone/cmd/authorize"
|
_ "github.com/ncw/rclone/cmd/authorize"
|
||||||
_ "github.com/ncw/rclone/cmd/cachestats"
|
_ "github.com/ncw/rclone/cmd/cachestats"
|
||||||
_ "github.com/ncw/rclone/cmd/cat"
|
_ "github.com/ncw/rclone/cmd/cat"
|
||||||
|
|
|
@ -98,6 +98,7 @@ The main rclone commands with most used first
|
||||||
* [rclone moveto](/commands/rclone_moveto/) - Move file or directory from source to dest.
|
* [rclone moveto](/commands/rclone_moveto/) - Move file or directory from source to dest.
|
||||||
* [rclone obscure](/commands/rclone_obscure/) - Obscure password for use in the rclone.conf
|
* [rclone obscure](/commands/rclone_obscure/) - Obscure password for use in the rclone.conf
|
||||||
* [rclone cryptcheck](/commands/rclone_cryptcheck/) - Check the integrity of a crypted remote.
|
* [rclone cryptcheck](/commands/rclone_cryptcheck/) - Check the integrity of a crypted remote.
|
||||||
|
* [rclone about](/commands/rclone_about/) - Get quota information from the remote.
|
||||||
|
|
||||||
See the [commands index](/commands/) for the full list.
|
See the [commands index](/commands/) for the full list.
|
||||||
|
|
||||||
|
|
|
@ -338,6 +338,14 @@ If you wish to empty your trash you can use the `rclone cleanup remote:`
|
||||||
command which will permanently delete all your trashed files. This command
|
command which will permanently delete all your trashed files. This command
|
||||||
does not take any path arguments.
|
does not take any path arguments.
|
||||||
|
|
||||||
|
### Quota information ###
|
||||||
|
|
||||||
|
To view your current quota you can use the `rclone about remote:`
|
||||||
|
command which will display your usage limit (quota), the usage in Google
|
||||||
|
Drive, the size of all files in the Trash and the space used by other
|
||||||
|
Google services such as Gmail. This command does not take any path
|
||||||
|
arguments.
|
||||||
|
|
||||||
### Specific options ###
|
### Specific options ###
|
||||||
|
|
||||||
Here are the command line options specific to this cloud storage
|
Here are the command line options specific to this cloud storage
|
||||||
|
|
|
@ -119,27 +119,27 @@ All the remotes support a basic set of features, but there are some
|
||||||
optional features supported by some remotes used to make some
|
optional features supported by some remotes used to make some
|
||||||
operations more efficient.
|
operations more efficient.
|
||||||
|
|
||||||
| Name | Purge | Copy | Move | DirMove | CleanUp | ListR | StreamUpload | LinkSharing |
|
| Name | Purge | Copy | Move | DirMove | CleanUp | ListR | StreamUpload | LinkSharing | About |
|
||||||
| ---------------------------- |:-----:|:----:|:----:|:-------:|:-------:|:-----:|:------------:|:------------:|
|
| ---------------------------- |:-----:|:----:|:----:|:-------:|:-------:|:-----:|:------------:|:------------:|:-----:|
|
||||||
| Amazon Drive | Yes | No | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Amazon Drive | Yes | No | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Amazon S3 | No | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Amazon S3 | No | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Backblaze B2 | No | No | No | No | Yes | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Backblaze B2 | No | No | No | No | Yes | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Box | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Box | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Dropbox | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | Yes |
|
| Dropbox | Yes | Yes | Yes | Yes | No [#575](https://github.com/ncw/rclone/issues/575) | No | Yes | Yes | No |
|
||||||
| FTP | No | No | Yes | Yes | No | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| FTP | No | No | Yes | Yes | No | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Google Cloud Storage | Yes | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Google Cloud Storage | Yes | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Google Drive | Yes | Yes | Yes | Yes | Yes | No | Yes | Yes |
|
| Google Drive | Yes | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes |
|
||||||
| HTTP | No | No | No | No | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| HTTP | No | No | No | No | No | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Hubic | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Hubic | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Microsoft Azure Blob Storage | Yes | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Microsoft Azure Blob Storage | Yes | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | 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 | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| 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 | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Openstack Swift | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Openstack Swift | Yes † | Yes | No | No | No | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| pCloud | Yes | Yes | Yes | Yes | Yes | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| pCloud | Yes | Yes | Yes | Yes | Yes | No | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| QingStor | No | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| QingStor | No | Yes | No | No | No | Yes | No | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| SFTP | No | No | Yes | Yes | No | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| SFTP | No | No | Yes | Yes | No | No | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| WebDAV | Yes | Yes | Yes | Yes | No | No | Yes ‡ | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| WebDAV | Yes | Yes | Yes | Yes | No | No | Yes ‡ | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| Yandex Disk | Yes | No | No | No | Yes | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) |
|
| Yandex Disk | Yes | No | No | No | Yes | Yes | Yes | No [#2178](https://github.com/ncw/rclone/issues/2178) | No |
|
||||||
| The local filesystem | Yes | No | Yes | Yes | No | No | Yes | No |
|
| The local filesystem | Yes | No | Yes | Yes | No | No | Yes | No | No |
|
||||||
|
|
||||||
### Purge ###
|
### Purge ###
|
||||||
|
|
||||||
|
@ -202,3 +202,11 @@ file to local disk first, e.g. `rclone rcat`.
|
||||||
Sets the necessary permissions on a file or folder and prints a link
|
Sets the necessary permissions on a file or folder and prints a link
|
||||||
that allows others to access them, even if they don't have an account
|
that allows others to access them, even if they don't have an account
|
||||||
on the particular cloud provider.
|
on the particular cloud provider.
|
||||||
|
|
||||||
|
### About ###
|
||||||
|
|
||||||
|
This is used to fetch quota information from the remote, like bytes
|
||||||
|
used/free/quota and bytes used in the trash.
|
||||||
|
|
||||||
|
If the server can't do `About` then `rclone about` will return an
|
||||||
|
error.
|
||||||
|
|
15
fs/fs.go
15
fs/fs.go
|
@ -377,6 +377,9 @@ type Features struct {
|
||||||
// Don't implement this unless you have a more efficient way
|
// Don't implement this unless you have a more efficient way
|
||||||
// of listing recursively that doing a directory traversal.
|
// of listing recursively that doing a directory traversal.
|
||||||
ListR ListRFn
|
ListR ListRFn
|
||||||
|
|
||||||
|
// Get quota information from the Fs
|
||||||
|
About func() error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable nil's out the named feature. If it isn't found then it
|
// Disable nil's out the named feature. If it isn't found then it
|
||||||
|
@ -466,6 +469,9 @@ func (ft *Features) Fill(f Fs) *Features {
|
||||||
if do, ok := f.(ListRer); ok {
|
if do, ok := f.(ListRer); ok {
|
||||||
ft.ListR = do.ListR
|
ft.ListR = do.ListR
|
||||||
}
|
}
|
||||||
|
if do, ok := f.(Abouter); ok {
|
||||||
|
ft.About = do.About
|
||||||
|
}
|
||||||
return ft.DisableList(Config.DisableFeatures)
|
return ft.DisableList(Config.DisableFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,6 +525,9 @@ func (ft *Features) Mask(f Fs) *Features {
|
||||||
if mask.ListR == nil {
|
if mask.ListR == nil {
|
||||||
ft.ListR = nil
|
ft.ListR = nil
|
||||||
}
|
}
|
||||||
|
if mask.About == nil {
|
||||||
|
ft.About = nil
|
||||||
|
}
|
||||||
return ft.DisableList(Config.DisableFeatures)
|
return ft.DisableList(Config.DisableFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,6 +715,12 @@ type RangeSeeker interface {
|
||||||
RangeSeek(offset int64, whence int, length int64) (int64, error)
|
RangeSeek(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() error
|
||||||
|
}
|
||||||
|
|
||||||
// ObjectsChan is a channel of Objects
|
// ObjectsChan is a channel of Objects
|
||||||
type ObjectsChan chan Object
|
type ObjectsChan chan Object
|
||||||
|
|
||||||
|
|
|
@ -1049,6 +1049,19 @@ func CleanUp(f fs.Fs) error {
|
||||||
return doCleanUp()
|
return doCleanUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// About gets quota information from the remote
|
||||||
|
func About(f fs.Fs) error {
|
||||||
|
doAbout := f.Features().About
|
||||||
|
if doAbout == nil {
|
||||||
|
return errors.Errorf("%v doesn't support about", f)
|
||||||
|
}
|
||||||
|
if fs.Config.DryRun {
|
||||||
|
fs.Logf(f, "Not running about as --dry-run set")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return doAbout()
|
||||||
|
}
|
||||||
|
|
||||||
// wrap a Reader and a Closer together into a ReadCloser
|
// wrap a Reader and a Closer together into a ReadCloser
|
||||||
type readCloser struct {
|
type readCloser struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
|
|
Loading…
Reference in a new issue