aboutsummaryrefslogtreecommitdiffstats
path: root/drive/list.go
blob: e63658523207ae14f808d0f5e840cf4ded732efb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package drive

import (
    "fmt"
    "io"
    "text/tabwriter"
    "golang.org/x/net/context"
    "google.golang.org/api/drive/v3"
    "google.golang.org/api/googleapi"
)

type ListFilesArgs struct {
    Out io.Writer
    MaxFiles int64
    NameWidth int64
    Query string
    SortOrder string
    SkipHeader bool
    SizeInBytes bool
}

func (self *Drive) List(args ListFilesArgs) (err error) {
    listArgs := listAllFilesArgs{
        query: args.Query,
        fields: []googleapi.Field{"nextPageToken", "files(id,name,md5Checksum,mimeType,size,createdTime)"},
        sortOrder: args.SortOrder,
        maxFiles: args.MaxFiles,
    }
    files, err := self.listAllFiles(listArgs)
    if err != nil {
        return fmt.Errorf("Failed to list files: %s", err)
    }

    PrintFileList(PrintFileListArgs{
        Out: args.Out,
        Files: files,
        NameWidth: int(args.NameWidth),
        SkipHeader: args.SkipHeader,
        SizeInBytes: args.SizeInBytes,
    })

    return
}

type listAllFilesArgs struct {
    query string
    fields []googleapi.Field
    sortOrder string
    maxFiles int64
}

func (self *Drive) listAllFiles(args listAllFilesArgs) ([]*drive.File, error) {
    var files []*drive.File

    var pageSize int64
    if args.maxFiles > 0 && args.maxFiles < 1000 {
        pageSize = args.maxFiles
    } else {
        pageSize = 1000
    }

    controlledStop := fmt.Errorf("Controlled stop")

    err := self.service.Files.List().Q(args.query).Fields(args.fields...).OrderBy(args.sortOrder).PageSize(pageSize).Pages(context.TODO(), func(fl *drive.FileList) error {
        files = append(files, fl.Files...)

        // Stop when we have all the files we need
        if args.maxFiles > 0 && len(files) >= int(args.maxFiles) {
            return controlledStop
        }

        return nil
    })

    if err != nil && err != controlledStop {
        return nil, err
    }

    if args.maxFiles > 0 {
        n := min(len(files), int(args.maxFiles))
        return files[:n], nil
    }

    return files, nil
}

type PrintFileListArgs struct {
    Out io.Writer
    Files []*drive.File
    NameWidth int
    SkipHeader bool
    SizeInBytes bool
}

func PrintFileList(args PrintFileListArgs) {
    w := new(tabwriter.Writer)
    w.Init(args.Out, 0, 0, 3, ' ', 0)

    if !args.SkipHeader {
        fmt.Fprintln(w, "Id\tName\tType\tSize\tCreated")
    }

    for _, f := range args.Files {
        fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
            f.Id,
            truncateString(f.Name, args.NameWidth),
            filetype(f),
            formatSize(f.Size, args.SizeInBytes),
            formatDatetime(f.CreatedTime),
        )
    }

    w.Flush()
}

func filetype(f *drive.File) string {
    if isDir(f) {
        return "dir"
    } else if isBinary(f) {
        return "bin"
    }
    return "doc"
}