/
help.go
485 lines (452 loc) · 18 KB
/
help.go
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package drive
import (
"fmt"
"io"
"os"
"sort"
"strings"
prettywords "github.com/odeke-em/pretty-words"
)
const (
AboutKey = "about"
AllKey = "all"
CopyKey = "copy"
DeleteKey = "delete"
DeInitKey = "deinit"
EditDescriptionKey = "edit-description"
EditDescriptionShortKey = "edit-desc"
DiffKey = "diff"
AddressKey = "address"
EmptyTrashKey = "emptytrash"
FeaturesKey = "features"
HelpKey = "help"
InitKey = "init"
LinkKey = "Link"
ListKey = "list"
DuKey = "du"
Md5sumKey = "md5sum"
MoveKey = "move"
OcrKey = "ocr"
ConvertKey = "convert"
OSLinuxKey = "linux"
PullKey = "pull"
PipedKey = "piped"
PushKey = "push"
PubKey = "pub"
QRLinkKey = "qr"
RenameKey = "rename"
QuotaKey = "quota"
ShareKey = "share"
StatKey = "stat"
TouchKey = "touch"
TrashKey = "trash"
UnshareKey = "unshare"
UntrashKey = "untrash"
UnpubKey = "unpub"
VersionKey = "version"
NewKey = "new"
IndexKey = "index"
PruneKey = "prune"
StarKey = "star"
UnStarKey = "unstar"
CoercedMimeKeyKey = "coerced-mime"
ExportsKey = "export"
ExportsDirKey = "exports-dir"
NoClobberKey = "no-clobber"
RecursiveKey = "recursive"
IgnoreChecksumKey = "ignore-checksum"
ExcludeOpsKey = "exclude-ops"
IgnoreConflictKey = "ignore-conflict"
IgnoreNameClashesKey = "ignore-name-clashes"
ClashesKey = "clashes"
CommentStr = "#"
DepthKey = "depth"
EmailsKey = "emails"
EmailMessageKey = "emailMessage"
ForceKey = "force"
QuietKey = "quiet"
IdKey = "id"
QuitShortKey = "q"
YesShortKey = "Y"
QuitLongKey = "quit"
MatchesKey = "matches"
HiddenKey = "hidden"
Md5Key = "md5"
NoPromptKey = "no-prompt"
SizeKey = "size"
NameKey = "name"
OpenKey = "open"
OriginalNameKey = "oname"
ModTimeKey = "modt"
LastViewedByMeTimeKey = "lvt"
AccountTypeKey = "account-type"
RoleKey = "role"
TypeKey = "type"
TrashedKey = "trashed"
SkipMimeKeyKey = "skip-mime"
MatchMimeKeyKey = "exact-mime"
ExactTitleKey = "exact-title"
MatchOwnerKey = "match-owner"
ExactOwnerKey = "exact-owner"
NotOwnerKey = "skip-owner"
SortKey = "sort"
FolderKey = "folder"
MimeKey = "mime-key"
PageSizeKey = "pagesize"
DriveRepoRelPath = "github.com/odeke-em/drive"
UrlKey = "url"
ReportIssueKey = "report-issue"
IssueTitleKey = "title"
IssueBodyKey = "body"
SkipContentCheckKey = "skip-content-check"
TouchModTimeKey = "time"
TouchTimeFmtSpecifierKey = "format"
TouchOffsetDurationKey = "duration"
)
const (
DescAbout = "print out information about your Google drive"
DescAll = "print out the entire help section"
DescAllStarred = "all the starred files"
DescCopy = "copy remote paths to a destination"
DescDelete = "deletes the items permanently. This operation is irreversible"
DescDiff = "compares local files with their remote equivalent"
DescEdit = "edit the attributes of a file"
DescEmptyTrash = "permanently cleans out your trash"
DescExcludeOps = "exclude operations"
DescFeatures = "returns information about the features of your drive"
DescIndex = "fetch indices from remote"
DescHelp = "Get help for a topic"
DescInit = "initializes a directory and authenticates user"
DescDeInit = "removes the user's credentials and initialized files"
DescList = "lists the contents of remote path"
DescMove = "move files/folders"
DescPiped = "get content in from standard input (stdin)"
DescQuota = "prints out information related to your quota space"
DescPublish = "publishes a file and prints its publicly available url"
DescRename = "renames a file/folder"
DescPull = "pulls remote changes from Google Drive"
DescPruneIndices = "remove stale indices"
DescPush = "push local changes to Google Drive"
DescShare = "share files with specific emails giving the specified users specifies roles and permissions"
DescStar = "star files"
DescUnStar = "unstar files"
DescStat = "display information about a file"
DescTouch = "updates a remote file's modification time to that currently on the server"
DescTrash = "moves files to trash"
DescUnshare = "revoke a user's access to a file"
DescUntrash = "restores files from trash to their original locations"
DescUnpublish = "revokes public access to a file"
DescVersion = "prints the version"
DescMd5sum = "prints a list compatible with md5sum(1)"
DescDu = "similar to util `du` gives you disk usage"
DescAccountTypes = "\n\t* anyone.\n\t* user.\n\t* domain.\n\t* group"
DescRoles = "\n\t* owner.\n\t* reader.\n\t* writer.\n\t* commenter."
DescExplicitylPullExports = "explicitly pull exports"
DescIgnoreChecksum = "avoids computation of checksums as a final check." +
"\nUse cases may include:\n\t* when you are low on bandwidth e.g SSHFS." +
"\n\t* Are on a low power device"
DescIgnoreConflict = "turns off the conflict resolution safety"
DescIgnoreNameClashes = "ignore name clashes"
DescSort = "sort items by a combination of attributes\n\t* modtime.\n\t* md5.\n\t* name.\n\t* size.\n\t* type.\n\t* version\ncomma separated e.g modtime,md5_r,name"
DescSkipMime = "skip elements with mimeTypes derived from these extensions"
DescMatchMime = "get elements with the exact mimeTypes derived from extensions"
DescMatchTitle = "elements with matching titles"
DescExactTitle = "get elements with the exact titles"
DescMatchOwner = "elements with matching owners"
DescExactOwner = "elements with the exact owner"
DescNotOwner = "ignore elements owned by these users"
DescNew = "create a new file/folder"
DescAllIndexOperations = "perform all the index related operations"
DescOpen = "open a file in the appropriate filemanager or default browser"
DescUrl = "returns the remote URL of each file"
DescVerbose = "show step by step information verbosely"
DescFixClashes = "fix clashes by renaming or trashing files"
DescFixClashesMode = "set fix policy to rename or trash"
DescListClashes = "list clashes"
DescDescription = "set the description"
DescQR = "open up the QR code for specified files"
DescStarred = "operate only on starred files"
DescUnifiedDiff = "unified diff"
DescDiffBaseLocal = "when set uses local as the base other remote will be used as the base"
DescClashesOpById = "operate on clashes by id instead of by path"
DescIssueBody = "the detailed description of the issue being filed"
DescIssueTitle = "the title of the issue being filed"
DescReportIssue = "report an issue to the project's issue tracker"
DescId = "retrieve the fileId for the specified paths"
DescSkipContentCheck = "skip diffing actual body content, show only name, time, type changes"
DescPushDestination = "specify the final destination of the contents of an operation"
DescExponentialBackoffRetryCount = "max number of retries for exponential backoff"
DescEncryptionPassword = "encryption password"
DescDecryptionPassword = "decryption password"
DescWithLink = "turn off file indexing so that only those with the link can view it"
DescAllowDesktopLinks = "allows docs + sheets to be pulled as .desktop files or URL linked files"
DescKeepParent = "ensures that when moving a file into a destination, that we also retain its original parent so that it will exist in more than one folder"
DescTouchTimeStr = "the time each file's modification time should be set to"
DescTouchOffsetDuration = "the duration offset from now that each file's modification time should be set to e.g -32h\nSee https://golang.org/pkg/time/#ParseDuration"
DescTouchTimeFmtSpecifier = "the custom layout that you'd like your time to be set in, representative of the way 'Mon Jan 2 15:04:05 -0700 MST 2006' should be represented\nSee https://golang.org/pkg/time/#Parse"
)
const (
CLIOptionDescription = "description"
CLIOptionExplicitlyExport = "explicitly-export"
CLIOptionIgnoreChecksum = "ignore-checksum"
CLIOptionIgnoreConflict = "ignore-conflict"
CLIOptionIgnoreNameClashes = "ignore-name-clashes"
CLIOptionExcludeOperations = "exclude-ops"
CLIOptionId = "id"
CLIOptionNoClobber = "no-clobber"
CLIOptionNotify = "notify"
CLIOptionSkipMime = "skip-mime"
CLIOptionExactMime = "exact-mime"
CLIOptionMatchMime = "match-mime"
CLIOptionExactTitle = "exact-title"
CLIOptionMatchTitle = "match-title"
CLIOptionExactOwner = "exact-owner"
CLIOptionMatchOwner = "match-owner"
CLIOptionNotOwner = "skip-owner"
CLIOptionPruneIndices = "prune"
CLIOptionAllIndexOperations = "all-ops"
CLIOptionVerboseKey = "verbose"
CLIOptionVerboseShortKey = "v"
CLIOptionOpen = "open"
CLIOptionWebBrowser = "web-browser"
CLIOptionFileBrowser = "file-browser"
CLIOptionDirectories = "directories"
CLIOptionFiles = "files"
CLIOptionLongFmt = "long"
CLIOptionFixClashesKey = "fix-clashes"
CLIOptionPiped = "piped"
CLIOptionStarred = "starred"
CLIOptionAllStarred = "all"
CLIOptionUnified = "unified"
CLIOptionUnifiedShortKey = "u"
CLIOptionDiffBaseLocal = "base-local"
CLIOptionFixClashes = "fix"
CLIOptionFixClashesMode = "fix-mode"
CLIOptionListClashes = "list"
CLIOptionPushDestination = "destination"
CLIOptionRenameLocal = "local"
CLIOptionRenameRemote = "remote"
CLIOptionRetryCount = "retry-count"
CLIEncryptionPassword = "encryption-password"
CLIDecryptionPassword = "decryption-password"
CLIOptionWithLink = "with-link"
CLIOptionDesktopLinks = "desktop-links"
CLIOptionKeepParent = "keep-parent"
CLIOptionExportsDumpToSameDirectory = "same-exports-dir"
)
const (
DefaultMaxTraversalDepth = -1
)
const (
GoogleApiClientIdEnvKey = "GOOGLE_API_CLIENT_ID"
GoogleApiClientSecretEnvKey = "GOOGLE_API_CLIENT_SECRET"
DriveGoMaxProcsKey = "DRIVE_GOMAXPROCS"
GoMaxProcsKey = "GOMAXPROCS"
)
const (
DesktopExtension = "desktop"
)
const (
InfiniteDepth = -1
)
var (
skipChecksumNote = fmt.Sprintf(
"\nNote: You can skip checksum verification by passing in flag `-%s`", CLIOptionIgnoreChecksum)
PermanentDeletionNoPromptError = fmt.Errorf("%q is set yet performing a permanent deletion. Please see issue https://github.com/odeke-em/drive/issues/448", NoPromptKey)
)
var docMap = map[string][]string{
AboutKey: []string{
DescAbout,
},
CopyKey: []string{
DescCopy,
},
DeleteKey: []string{
DescDelete,
},
DiffKey: []string{
DescDiff, "Accepts multiple remote paths for line by line comparison",
skipChecksumNote,
},
EditDescriptionShortKey: []string{
DescEdit, "Accepts multiple remote paths as well as ids",
},
EmptyTrashKey: []string{
DescEmptyTrash,
},
FeaturesKey: []string{
DescFeatures,
},
InitKey: []string{
DescInit, "Requests for access to your Google Drive",
"Creating a folder that contains your credentials",
"Note: `init` in an already initialized drive will erase the old credentials",
},
PullKey: []string{
DescPull, "Downloads content from the remote drive or modifies",
" local content to match that on your Google Drive",
skipChecksumNote,
},
PushKey: []string{
DescPush, "Uploads content to your Google Drive from your local path",
"Push comes in a couple of flavors",
"\t* Ordinary push: `drive push path1 path2 path3`",
"\t* Mounted push: `drive push -m path1 [path2 path3] drive_context_path`",
skipChecksumNote,
},
ListKey: []string{
DescList,
"List the information of a remote path not necessarily present locally",
"Allows printing of long options and by default does minimal printing",
},
MoveKey: []string{
DescMove,
"Moves files/folders between folders",
},
OpenKey: []string{
DescOpen, fmt.Sprintf("toggle between %q=bool and %q=bool",
CLIOptionWebBrowser, CLIOptionFileBrowser),
},
PubKey: []string{
DescPublish, "Accepts multiple paths",
},
RenameKey: []string{
DescRename, "Accepts <src> <newName>",
},
QuotaKey: []string{DescQuota},
ShareKey: []string{
DescShare, "Accepts multiple paths",
"Specify the emails to share with as well as the message to send them on notification",
"Accepted values for:\n+ accountType: ",
DescAccountTypes, "\n+ roles:", DescRoles,
},
StatKey: []string{
DescStat, "provides detailed information about a remote file",
"Accepts multiple paths",
},
TouchKey: []string{
DescTouch, "Given a list of remote files `touch` updates their",
"last edit times to that currently on the server",
},
TrashKey: []string{
DescTrash, "Sends a list of remote files to trash",
},
UnshareKey: []string{
DescUnshare, "Accepts multiple paths",
"Accepted values for accountTypes::", DescAccountTypes,
},
UntrashKey: []string{
DescUntrash, "takes remote files out of the trash",
"Note: untrash is a relative path command so any resolutions are made",
"relative to the current working directory i.e",
"\n\t$ drive trash mnt/logos",
},
UnpubKey: []string{
DescUnpublish, "revokes public access to a list of remote files",
},
UrlKey: []string{
DescUrl, "takes multiple paths or ids",
},
VersionKey: []string{
DescVersion, fmt.Sprintf("current version is: %s", Version),
},
}
func createAndRegisterAliases() map[string][]string {
aliases := map[string][]string{
CopyKey: []string{"cp"},
ListKey: []string{"ls"},
MoveKey: []string{"mv"},
DeleteKey: []string{"del"},
EditDescriptionKey: []string{EditDescriptionShortKey},
IdKey: []string{"file-id"},
ReportIssueKey: []string{"issue", "report"},
}
for originalKey, aliasList := range aliases {
docDetails, ok := docMap[originalKey]
if !ok {
continue
}
for _, alias := range aliasList {
docMap[alias] = docDetails
}
}
return aliases
}
var Aliases = createAndRegisterAliases()
func ShowAllDescriptions() {
keys := []string{}
for key, _ := range docMap {
keys = append(keys, key)
}
sort.Strings(keys)
for _, key := range keys {
ShowDescription(key)
}
}
func ShowDescriptions(topics ...string) {
if len(topics) < 1 {
topics = append(topics, AllKey)
}
for _, topic := range topics {
ShowDescription(topic)
}
}
func ShowDescription(topic string) {
if topic == AllKey {
ShowAllDescriptions()
return
}
help, ok := docMap[topic]
if !ok {
PrintfShadow("Unknown command '%s' type `drive help all` for entire usage documentation", topic)
ShowAllDescriptions()
} else {
description, documentation := help[0], help[1:]
PrintfShadow("Name\n\t%s - %s\n", topic, description)
if len(documentation) >= 1 {
PrintfShadow("Description\n")
for _, line := range documentation {
segments := formatText(line)
for _, segment := range segments {
PrintfShadow("\t%s", segment)
}
}
PrintfShadow("\n* For usage flags: \033[32m`drive %s -h`\033[00m\n\n", topic)
}
fmt.Fprintf(os.Stdout, "\n")
}
}
func formatText(text string) []string {
splits := strings.Split(text, "\n")
pr := prettywords.PrettyRubric{
Limit: 80,
Body: splits,
}
return pr.Format()
}
func PrintfShadow(fmt_ string, args ...interface{}) {
FprintfShadow(os.Stdout, fmt_, args...)
}
func StdoutPrintf(fmt_ string, args ...interface{}) {
fmt.Fprintf(os.Stdout, fmt_, args...)
}
func FprintfShadow(f io.Writer, fmt_ string, args ...interface{}) {
sprinted := fmt.Sprintf(fmt_, args...)
splits := formatText(sprinted)
for _, split := range splits {
fmt.Fprintf(f, "%s\n", split)
}
}