aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md44
-rw-r--r--cli/cli.go52
-rw-r--r--drive.go18
-rw-r--r--util/generic.go33
4 files changed, 99 insertions, 48 deletions
diff --git a/README.md b/README.md
index 1fcb7d8..b67eadc 100644
--- a/README.md
+++ b/README.md
@@ -33,34 +33,40 @@ If you want to compile from source you need the go toolchain: http://golang.org/
#### Options
Global options:
- -a, --advanced Advanced Mode -- lets you specify your own oauth client id and secret on setup
- -c, --config Set application path where config and token is stored. Defaults to ~/.gdrive
- -v, --version Print version
- -h, --help Show this help
+ -a, --advanced Advanced Mode -- lets you specify your own oauth client id and secret on setup
+ -c, --config Set application path where config and token is stored. Defaults to ~/.gdrive
+ -v, --version Print version
+ -h, --help Show this help
Verbs:
delete:
- -i, --id File Id (*)
+ -i, --id File Id (*)
download:
- -i, --id File Id (*)
- -s, --stdout Write file content to stdout
- --pop Download latest file, and remove it from google drive
+ -i, --id File Id (*)
+ -s, --stdout Write file content to stdout
+ --pop Download latest file, and remove it from google drive
+ folder:
+ -t, --title Folder to create (*)
+ -p, --parent Parent Id of the folder
+ --share Share created folder
info:
- -i, --id File Id (*)
+ -i, --id File Id (*)
list:
- -m, --max Max results
- -t, --title Title filter
- -q, --query Query (see https://developers.google.com/drive/search-parameters)
- -s, --shared Show shared status (Note: this will generate 1 http req per file)
+ -m, --max Max results
+ -t, --title Title filter
+ -q, --query Query (see https://developers.google.com/drive/search-parameters)
+ -s, --shared Show shared status (Note: this will generate 1 http req per file)
+ -n, --noheader Do not show the header
share:
- -i, --id File Id (*)
+ -i, --id File Id (*)
unshare:
- -i, --id File Id (*)
+ -i, --id File Id (*)
upload:
- -f, --file File to upload (*)
- -s, --stdin Use stdin as file content (*)
- -t, --title Title to give uploaded file. Defaults to filename
- --share Share uploaded file
+ -f, --file File to upload (*)
+ -s, --stdin Use stdin as file content (*)
+ -t, --title Title to give uploaded file. Defaults to filename
+ -p, --parent Parent Id of the file
+ --share Share uploaded file
url:
-i, --id File Id (*)
-p, --preview Generate preview url (default)
diff --git a/cli/cli.go b/cli/cli.go
index c27dc8e..a886a64 100644
--- a/cli/cli.go
+++ b/cli/cli.go
@@ -12,7 +12,7 @@ import (
"../gdrive"
)
-func List(d *gdrive.Drive, query, titleFilter string, maxResults int, sharedStatus bool) {
+func List(d *gdrive.Drive, query, titleFilter string, maxResults int, sharedStatus bool, noHeader bool) {
caller := d.Files.List()
if maxResults > 0 {
@@ -39,8 +39,13 @@ func List(d *gdrive.Drive, query, titleFilter string, maxResults int, sharedStat
for _, f := range list.Items {
// Skip files that dont have a download url (they are not stored on google drive)
if f.DownloadUrl == "" {
- continue
+ if f.MimeType != "application/vnd.google-apps.folder" {
+ continue
+ }
}
+ if f.Labels.Trashed {
+ continue
+ }
items = append(items, map[string]string{
"Id": f.Id,
@@ -57,7 +62,7 @@ func List(d *gdrive.Drive, query, titleFilter string, maxResults int, sharedStat
columnOrder = append(columnOrder, "Shared")
}
- util.PrintColumns(items, columnOrder, 3)
+ util.PrintColumns(items, columnOrder, 3, noHeader)
}
// Adds the key-value-pair 'Shared: True/False' to the map
@@ -117,8 +122,30 @@ func printInfo(d *gdrive.Drive, f *drive.File) {
util.Print(fields, order)
}
+// Create folder in drive
+func Folder(d *gdrive.Drive, title string, parentId string, share bool) {
+ // File instance
+ f := &drive.File{Title: title, MimeType: "application/vnd.google-apps.folder"}
+ // Set parent (if provided)
+ if parentId != "" {
+ p := &drive.ParentReference{Id: parentId}
+ f.Parents = []*drive.ParentReference{p}
+ }
+ // Create folder
+ info, err := d.Files.Insert(f).Do()
+ if err != nil {
+ fmt.Printf("An error occurred creating the folder: %v\n", err)
+ os.Exit(1)
+ }
+ // Share folder if the share flag was provided
+ if share {
+ Share(d, info.Id)
+ }
+ fmt.Printf("Folder created in %s\n", parentId)
+}
+
// Upload file to drive
-func Upload(d *gdrive.Drive, input io.ReadCloser, title string, share bool) {
+func Upload(d *gdrive.Drive, input io.ReadCloser, title string, parentId string, share bool) {
// Use filename or 'untitled' as title if no title is specified
if title == "" {
if f, ok := input.(*os.File); ok && input != os.Stdin {
@@ -129,13 +156,16 @@ func Upload(d *gdrive.Drive, input io.ReadCloser, title string, share bool) {
}
var mimeType = mime.TypeByExtension(filepath.Ext(title))
- metadata := &drive.File{
- Title: title,
- MimeType: mimeType,
- }
+ // File instance
+ f := &drive.File{Title: title, MimeType: mimeType}
+ // Set parent (if provided)
+ if parentId != "" {
+ p := &drive.ParentReference{Id: parentId}
+ f.Parents = []*drive.ParentReference{p}
+ }
getRate := util.MeasureTransferRate()
- info, err := d.Files.Insert(metadata).Media(input).Do()
+ info, err := d.Files.Insert(f).Media(input).Do()
if err != nil {
fmt.Printf("An error occurred uploading the document: %v\n", err)
os.Exit(1)
@@ -218,7 +248,7 @@ func Download(d *gdrive.Drive, fileId string, stdout, deleteAfterDownload bool)
}
// Create a new file
- outFile, err := os.Create(info.Title)
+ outFile, err := os.Create(info.Title)
if err != nil {
fmt.Printf("An error occurred: %v\n", err)
os.Exit(1)
@@ -253,7 +283,7 @@ func Delete(d *gdrive.Drive, fileId string) {
fmt.Printf("An error occurred: %v\n", err)
os.Exit(1)
}
-
+
fmt.Printf("Removed file '%s'\n", info.Title)
}
diff --git a/drive.go b/drive.go
index 4f2fb33..a26ecaa 100644
--- a/drive.go
+++ b/drive.go
@@ -26,16 +26,24 @@ type Options struct {
TitleFilter string `goptions:"-t, --title, mutexgroup='query', description='Title filter'"`
Query string `goptions:"-q, --query, mutexgroup='query', description='Query (see https://developers.google.com/drive/search-parameters)'"`
SharedStatus bool `goptions:"-s, --shared, description='Show shared status (Note: this will generate 1 http req per file)'"`
+ NoHeader bool `goptions:"-n, --noheader, description='Do not show the header'"`
} `goptions:"list"`
Info struct {
FileId string `goptions:"-i, --id, obligatory, description='File Id'"`
} `goptions:"info"`
+ Folder struct {
+ Title string `goptions:"-t, --title, obligatory, description='Folder to create'"`
+ ParentId string `goptions:"-p, --parent, description='Parent Id of the folder'"`
+ Share bool `goptions:"--share, description='Share created folder'"`
+ } `goptions:"folder"`
+
Upload struct {
File *os.File `goptions:"-f, --file, mutexgroup='input', obligatory, rdonly, description='File to upload'"`
Stdin bool `goptions:"-s, --stdin, mutexgroup='input', obligatory, description='Use stdin as file content'"`
Title string `goptions:"-t, --title, description='Title to give uploaded file. Defaults to filename'"`
+ ParentId string `goptions:"-p, --parent, description='Parent Id of the file'"`
Share bool `goptions:"--share, description='Share uploaded file'"`
} `goptions:"upload"`
@@ -84,17 +92,21 @@ func main() {
switch opts.Verbs {
case "list":
args := opts.List
- cli.List(drive, args.Query, args.TitleFilter, args.MaxResults, args.SharedStatus)
+ cli.List(drive, args.Query, args.TitleFilter, args.MaxResults, args.SharedStatus, args.NoHeader)
case "info":
cli.Info(drive, opts.Info.FileId)
+ case "folder":
+ args := opts.Folder
+ cli.Folder(drive, args.Title, args.ParentId, args.Share)
+
case "upload":
args := opts.Upload
if args.Stdin {
- cli.Upload(drive, os.Stdin, args.Title, args.Share)
+ cli.Upload(drive, os.Stdin, args.Title, args.ParentId, args.Share)
} else {
- cli.Upload(drive, args.File, args.Title, args.Share)
+ cli.Upload(drive, args.File, args.Title, args.ParentId, args.Share)
}
case "download":
diff --git a/util/generic.go b/util/generic.go
index fec2c31..972aabf 100644
--- a/util/generic.go
+++ b/util/generic.go
@@ -74,13 +74,13 @@ func TruncateString(str string, maxRunes int) string {
if runeCount <= maxRunes || maxRunes < 9 {
return str
}
-
+
// Number of remaining runes to be removed
remaining := (runeCount - maxRunes) + utf8.RuneCountInString(indicator)
-
+
var truncated string
var skip bool
-
+
for leftOffset, char := range str {
rightOffset := runeCount - (leftOffset + remaining)
@@ -96,11 +96,11 @@ func TruncateString(str string, maxRunes int) string {
remaining--
continue
}
-
+
// Add char to result string
truncated += string(char)
}
-
+
// Return truncated string
return truncated
}
@@ -140,22 +140,25 @@ func Print(m map[string]string, keyOrder []string) {
}
// Prints items in columns with header and correct padding
-func PrintColumns(items []map[string]string, keyOrder []string, columnSpacing int) {
- // Create header
- header := make(map[string]string)
- for _, key := range keyOrder {
- header[key] = key
- }
+func PrintColumns(items []map[string]string, keyOrder []string, columnSpacing int, noHeader bool) {
+
+ if !noHeader {
+ // Create header
+ header := make(map[string]string)
+ for _, key := range keyOrder {
+ header[key] = key
+ }
- // Add header as the first element of items
- items = append([]map[string]string{header}, items...)
+ // Add header as the first element of items
+ items = append([]map[string]string{header}, items...)
+ }
// Get a padding function for each column
padFns := make(map[string]func(string)string)
for _, key := range keyOrder {
padFns[key] = columnPadder(items, key, columnSpacing)
}
-
+
// Loop, pad and print items
for _, item := range items {
var line string
@@ -175,7 +178,7 @@ func PrintColumns(items []map[string]string, keyOrder []string, columnSpacing in
func columnPadder(items []map[string]string, key string, spacing int) func(string)string {
// Holds length of longest string
var max int
-
+
// Find the longest string of type key in the array
for _, item := range items {
str := item[key]