Skip to content

Commit

Permalink
Folder support added
Browse files Browse the repository at this point in the history
  • Loading branch information
erich-roncarolo committed Feb 15, 2014
1 parent d1e0a57 commit 10cfc69
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 48 deletions.
44 changes: 25 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
52 changes: 41 additions & 11 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}

Expand Down
18 changes: 15 additions & 3 deletions drive.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`

Expand Down Expand Up @@ -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":
Expand Down
33 changes: 18 additions & 15 deletions util/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand Down

0 comments on commit 10cfc69

Please sign in to comment.