diff options
| -rw-r--r-- | README.md | 44 | ||||
| -rw-r--r-- | cli/cli.go | 52 | ||||
| -rw-r--r-- | drive.go | 18 | ||||
| -rw-r--r-- | util/generic.go | 33 |
4 files changed, 99 insertions, 48 deletions
@@ -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) @@ -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) } @@ -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] |
