main.commands   F
last analyzed

Complexity

Conditions 49

Size

Total Lines 701
Code Lines 394

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 49
eloc 394
nop 0
dl 0
loc 701
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like main.commands often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
// Glide is a command line utility that manages Go project dependencies.
2
//
3
// Configuration of where to start is managed via a glide.yaml in the root of a
4
// project. The yaml
5
//
6
// A glide.yaml file looks like:
7
//
8
//		package: github.com/Masterminds/glide
9
//		imports:
10
//		- package: github.com/Masterminds/cookoo
11
//		- package: github.com/kylelemons/go-gypsy
12
//		  subpackages:
13
//		  - yaml
14
//
15
// Glide puts dependencies in a vendor directory. Go utilities require this to
16
// be in your GOPATH. Glide makes this easy.
17
//
18
// For more information use the `glide help` command or see https://glide.sh
19
package main
20
21
import (
22
	"path/filepath"
23
24
	"github.com/Masterminds/glide/action"
25
	"github.com/Masterminds/glide/cache"
26
	"github.com/Masterminds/glide/msg"
27
	gpath "github.com/Masterminds/glide/path"
28
	"github.com/Masterminds/glide/repo"
29
	"github.com/Masterminds/glide/util"
30
31
	"github.com/codegangsta/cli"
32
33
	"fmt"
34
	"os"
35
)
36
37
var version = "0.13.2-dev"
38
39
const usage = `Vendor Package Management for your Go projects.
40
41
   Each project should have a 'glide.yaml' file in the project directory. Files
42
   look something like this:
43
44
       package: github.com/Masterminds/glide
45
       imports:
46
       - package: github.com/Masterminds/cookoo
47
         version: 1.1.0
48
       - package: github.com/kylelemons/go-gypsy
49
         subpackages:
50
         - yaml
51
52
   For more details on the 'glide.yaml' files see the documentation at
53
   https://glide.sh/docs/glide.yaml
54
`
55
56
// VendorDir default vendor directory name
57
var VendorDir = "vendor"
58
59
func main() {
60
	app := cli.NewApp()
61
	app.Name = "glide"
62
	app.Usage = usage
63
	app.Version = version
64
	app.Flags = []cli.Flag{
65
		cli.StringFlag{
66
			Name:  "yaml, y",
67
			Value: "glide.yaml",
68
			Usage: "Set a YAML configuration file.",
69
		},
70
		cli.BoolFlag{
71
			Name:  "quiet, q",
72
			Usage: "Quiet (no info or debug messages)",
73
		},
74
		cli.BoolFlag{
75
			Name:  "debug",
76
			Usage: "Print debug verbose informational messages",
77
		},
78
		cli.StringFlag{
79
			Name:   "home",
80
			Value:  gpath.Home(),
81
			Usage:  "The location of Glide files",
82
			EnvVar: "GLIDE_HOME",
83
		},
84
		cli.StringFlag{
85
			Name:   "tmp",
86
			Value:  "",
87
			Usage:  "The temp directory to use. Defaults to systems temp",
88
			EnvVar: "GLIDE_TMP",
89
		},
90
		cli.BoolFlag{
91
			Name:  "no-color",
92
			Usage: "Turn off colored output for log messages",
93
		},
94
	}
95
	app.CommandNotFound = func(c *cli.Context, command string) {
96
		// TODO: Set some useful env vars.
97
		action.Plugin(command, os.Args)
98
	}
99
	app.Before = startup
100
	app.After = shutdown
101
	app.Commands = commands()
102
103
	// Detect errors from the Before and After calls and exit on them.
104
	if err := app.Run(os.Args); err != nil {
105
		msg.Err(err.Error())
106
		os.Exit(1)
107
	}
108
109
	// If there was an Error message exit non-zero.
110
	if msg.HasErrored() {
111
		m := msg.Color(msg.Red, "An Error has occurred")
112
		msg.Msg(m)
113
		os.Exit(2)
114
	}
115
}
116
117
func commands() []cli.Command {
118
	return []cli.Command{
119
		{
120
			Name:      "create",
121
			ShortName: "init",
122
			Usage:     "Initialize a new project, creating a glide.yaml file",
123
			Description: `This command starts from a project without Glide and
124
   sets it up. It generates a glide.yaml file, parsing your codebase to guess
125
   the dependencies to include. Once this step is done you may edit the
126
   glide.yaml file to update imported dependency properties such as the version
127
   or version range to include.
128
129
   To fetch the dependencies you may run 'glide install'.`,
130
			Flags: []cli.Flag{
131
				cli.BoolFlag{
132
					Name:  "skip-import",
133
					Usage: "When initializing skip importing from other package managers.",
134
				},
135
				cli.BoolFlag{
136
					Name:  "non-interactive",
137
					Usage: "Disable interactive prompts.",
138
				},
139
			},
140
			Action: func(c *cli.Context) error {
141
				action.Create(".", c.Bool("skip-import"), c.Bool("non-interactive"))
142
				return nil
143
			},
144
		},
145
		{
146
			Name:      "config-wizard",
147
			ShortName: "cw",
148
			Usage:     "Wizard that makes optional suggestions to improve config in a glide.yaml file.",
149
			Description: `Glide will analyze a projects glide.yaml file and the imported
150
		projects to find ways the glide.yaml file can potentially be improved. It
151
		will then interactively make suggestions that you can skip or accept.`,
152
			Action: func(c *cli.Context) error {
153
				action.ConfigWizard(".")
154
				return nil
155
			},
156
		},
157
		{
158
			Name:  "get",
159
			Usage: "Install one or more packages into `vendor/` and add dependency to glide.yaml.",
160
			Description: `Gets one or more package (like 'go get') and then adds that file
161
   to the glide.yaml file. Multiple package names can be specified on one line.
162
163
       $ glide get github.com/Masterminds/cookoo/web
164
165
   The above will install the project github.com/Masterminds/cookoo and add
166
   the subpackage 'web'.
167
168
   If a fetched dependency has a glide.yaml file, configuration from Godep,
169
   GPM, GOM, or GB Glide that configuration will be used to find the dependencies
170
   and versions to fetch. If those are not available the dependent packages will
171
   be fetched as either a version specified elsewhere or the latest version.
172
173
   When adding a new dependency Glide will perform an update to work out
174
   the versions for the dependencies of this dependency (transitive ones). This
175
   will generate an updated glide.lock file with specific locked versions to use.
176
177
   The '--strip-vendor' flag will remove any nested 'vendor' folders and
178
   'Godeps/_workspace' folders after an update (along with undoing any Godep
179
   import rewriting). Note, The Godeps specific functionality is deprecated and
180
   will be removed when most Godeps users have migrated to using the vendor
181
   folder.`,
182
			Flags: []cli.Flag{
183
				cli.BoolFlag{
184
					Name:  "test",
185
					Usage: "Add test dependencies.",
186
				},
187
				cli.BoolFlag{
188
					Name:  "insecure",
189
					Usage: "Use http:// rather than https:// to retrieve packages.",
190
				},
191
				cli.BoolFlag{
192
					Name:  "no-recursive, quick",
193
					Usage: "Disable updating dependencies' dependencies.",
194
				},
195
				cli.BoolFlag{
196
					Name:  "force",
197
					Usage: "If there was a change in the repo or VCS switch to new one. Warning, changes will be lost.",
198
				},
199
				cli.BoolFlag{
200
					Name:  "all-dependencies",
201
					Usage: "This will resolve all dependencies for all packages, not just those directly used.",
202
				},
203
				cli.BoolFlag{
204
					Name:   "update-vendored, u",
205
					Usage:  "Update vendored packages (without local VCS repo). Warning, changes will be lost.",
206
					Hidden: true,
207
				},
208
				cli.BoolFlag{
209
					Name:   "cache",
210
					Usage:  "When downloading dependencies attempt to cache them.",
211
					Hidden: true,
212
				},
213
				cli.BoolFlag{
214
					Name:   "cache-gopath",
215
					Usage:  "When downloading dependencies attempt to put them in the GOPATH, too.",
216
					Hidden: true,
217
				},
218
				cli.BoolFlag{
219
					Name:   "use-gopath",
220
					Usage:  "Copy dependencies from the GOPATH if they exist there.",
221
					Hidden: true,
222
				},
223
				cli.BoolFlag{
224
					Name:  "resolve-current",
225
					Usage: "Resolve dependencies for only the current system rather than all build modes.",
226
				},
227
				cli.BoolFlag{
228
					Name:   "strip-vcs, s",
229
					Usage:  "Removes version control metadata (e.g, .git directory) from the vendor folder.",
230
					Hidden: true,
231
				},
232
				cli.BoolFlag{
233
					Name:  "strip-vendor, v",
234
					Usage: "Removes nested vendor and Godeps/_workspace directories.",
235
				},
236
				cli.BoolFlag{
237
					Name:  "non-interactive",
238
					Usage: "Disable interactive prompts.",
239
				},
240
				cli.BoolFlag{
241
					Name:  "skip-test",
242
					Usage: "Resolve dependencies in test files.",
243
				},
244
			},
245
			Action: func(c *cli.Context) error {
246
				if c.Bool("delete") {
247
					msg.Warn("The --delete flag is deprecated. This now works by default.")
248
				}
249
				if c.Bool("update-vendored") {
250
					msg.Warn("The --update-vendored flag is deprecated. This now works by default.")
251
				}
252
				if c.String("file") != "" {
253
					msg.Warn("The --file flag is deprecated.")
254
				}
255
				if c.Bool("cache") {
256
					msg.Warn("The --cache flag is deprecated. This now works by default.")
257
				}
258
				if c.Bool("cache-gopath") {
259
					msg.Warn("The --cache-gopath flag is deprecated.")
260
				}
261
				if c.Bool("use-gopath") {
262
					msg.Warn("The --use-gopath flag is deprecated. Please see overrides.")
263
				}
264
				if c.Bool("strip-vcs") {
265
					msg.Warn("The --strip-vcs flag is deprecated. This now works by default.")
266
				}
267
268
				if len(c.Args()) < 1 {
269
					fmt.Println("Oops! Package name is required.")
270
					os.Exit(1)
271
				}
272
273
				if c.Bool("resolve-current") {
274
					util.ResolveCurrent = true
275
					msg.Warn("Only resolving dependencies for the current OS/Arch.")
276
				}
277
278
				inst := repo.NewInstaller()
279
				inst.Force = c.Bool("force")
280
				inst.ResolveAllFiles = c.Bool("all-dependencies")
281
				inst.ResolveTest = !c.Bool("skip-test")
282
				packages := []string(c.Args())
283
				insecure := c.Bool("insecure")
284
				action.Get(packages, inst, insecure, c.Bool("no-recursive"), c.Bool("strip-vendor"), c.Bool("non-interactive"), c.Bool("test"))
285
				return nil
286
			},
287
		},
288
		{
289
			Name:      "remove",
290
			ShortName: "rm",
291
			Usage:     "Remove a package from the glide.yaml file, and regenerate the lock file.",
292
			Description: `This takes one or more package names, and removes references from the glide.yaml file.
293
   This will rebuild the glide lock file re-resolving the depencies.`,
294
			Flags: []cli.Flag{
295
				cli.BoolFlag{
296
					Name:  "delete,d",
297
					Usage: "Also delete from vendor/ any packages that are no longer used.",
298
				},
299
			},
300
			Action: func(c *cli.Context) error {
301
				if len(c.Args()) < 1 {
302
					fmt.Println("Oops! At least one package name is required.")
303
					os.Exit(1)
304
				}
305
306
				if c.Bool("delete") {
307
					// FIXME: Implement this in the installer.
308
					fmt.Println("Delete is not currently implemented.")
309
				}
310
				inst := repo.NewInstaller()
311
				inst.Force = c.Bool("force")
312
				packages := []string(c.Args())
313
				action.Remove(packages, inst)
314
				return nil
315
			},
316
		},
317
		{
318
			Name:  "import",
319
			Usage: "Import files from other dependency management systems.",
320
			Subcommands: []cli.Command{
321
				{
322
					Name:  "godep",
323
					Usage: "Import Godep's Godeps.json files and display the would-be yaml file",
324
					Flags: []cli.Flag{
325
						cli.StringFlag{
326
							Name:  "file, f",
327
							Usage: "Save all of the discovered dependencies to a Glide YAML file.",
328
						},
329
					},
330
					Action: func(c *cli.Context) error {
331
						action.ImportGodep(c.String("file"))
332
						return nil
333
					},
334
				},
335
				{
336
					Name:  "gpm",
337
					Usage: "Import GPM's Godeps and Godeps-Git files and display the would-be yaml file",
338
					Flags: []cli.Flag{
339
						cli.StringFlag{
340
							Name:  "file, f",
341
							Usage: "Save all of the discovered dependencies to a Glide YAML file.",
342
						},
343
					},
344
					Action: func(c *cli.Context) error {
345
						action.ImportGPM(c.String("file"))
346
						return nil
347
					},
348
				},
349
				{
350
					Name:  "gb",
351
					Usage: "Import gb's manifest file and display the would-be yaml file",
352
					Flags: []cli.Flag{
353
						cli.StringFlag{
354
							Name:  "file, f",
355
							Usage: "Save all of the discovered dependencies to a Glide YAML file.",
356
						},
357
					},
358
					Action: func(c *cli.Context) error {
359
						action.ImportGB(c.String("file"))
360
						return nil
361
					},
362
				},
363
				{
364
					Name:  "gom",
365
					Usage: "Import Gomfile and display the would-be yaml file",
366
					Flags: []cli.Flag{
367
						cli.StringFlag{
368
							Name:  "file, f",
369
							Usage: "Save all of the discovered dependencies to a Glide YAML file.",
370
						},
371
					},
372
					Action: func(c *cli.Context) error {
373
						action.ImportGom(c.String("file"))
374
						return nil
375
					},
376
				},
377
			},
378
		},
379
		{
380
			Name:        "name",
381
			Usage:       "Print the name of this project.",
382
			Description: `Read the glide.yaml file and print the name given on the 'package' line.`,
383
			Action: func(c *cli.Context) error {
384
				action.Name()
385
				return nil
386
			},
387
		},
388
		{
389
			Name:      "novendor",
390
			ShortName: "nv",
391
			Usage:     "List all non-vendor paths in a directory.",
392
			Description: `Given a directory, list all the relevant Go paths that are not vendored.
393
394
Example:
395
   $ go test $(glide novendor)`,
396
			Flags: []cli.Flag{
397
				cli.StringFlag{
398
					Name:  "dir,d",
399
					Usage: "Specify a directory to run novendor against.",
400
					Value: ".",
401
				},
402
				cli.BoolFlag{
403
					Name:  "no-subdir,x",
404
					Usage: "Specify this to prevent nv from append '/...' to all directories.",
405
				},
406
			},
407
			Action: func(c *cli.Context) error {
408
				action.NoVendor(c.String("dir"), true, !c.Bool("no-subdir"))
409
				return nil
410
			},
411
		},
412
		{
413
			Name:  "rebuild",
414
			Usage: "Rebuild ('go build') the dependencies",
415
			Description: `(Deprecated) This rebuilds the packages' '.a' files. On some systems
416
	this can improve performance on subsequent 'go run' and 'go build' calls.`,
417
			Action: func(c *cli.Context) error {
418
				action.Rebuild()
419
				return nil
420
			},
421
		},
422
		{
423
			Name:      "install",
424
			ShortName: "i",
425
			Usage:     "Install a project's dependencies",
426
			Description: `This uses the native VCS of each package to install
427
   the appropriate version. There are two ways a project's dependencies can
428
   be installed. When there is a glide.yaml file defining the dependencies but
429
   no lock file (glide.lock) the dependencies are installed using the "update"
430
   command and a glide.lock file is generated pinning all dependencies. If a
431
   glide.lock file is already present the dependencies are installed or updated
432
   from the lock file.`,
433
			Flags: []cli.Flag{
434
				cli.BoolFlag{
435
					Name:   "delete",
436
					Usage:  "Delete vendor packages not specified in config.",
437
					Hidden: true,
438
				},
439
				cli.BoolFlag{
440
					Name:  "force",
441
					Usage: "If there was a change in the repo or VCS switch to new one. Warning: changes will be lost.",
442
				},
443
				cli.BoolFlag{
444
					Name:   "update-vendored, u",
445
					Usage:  "Update vendored packages (without local VCS repo). Warning: this may destroy local modifications to vendor/.",
446
					Hidden: true,
447
				},
448
				cli.StringFlag{
449
					Name:   "file, f",
450
					Usage:  "Save all of the discovered dependencies to a Glide YAML file. (DEPRECATED: This has no impact.)",
451
					Hidden: true,
452
				},
453
				cli.BoolFlag{
454
					Name:   "cache",
455
					Usage:  "When downloading dependencies attempt to cache them.",
456
					Hidden: true,
457
				},
458
				cli.BoolFlag{
459
					Name:   "cache-gopath",
460
					Usage:  "When downloading dependencies attempt to put them in the GOPATH, too.",
461
					Hidden: true,
462
				},
463
				cli.BoolFlag{
464
					Name:   "use-gopath",
465
					Usage:  "Copy dependencies from the GOPATH if they exist there.",
466
					Hidden: true,
467
				},
468
				cli.BoolFlag{
469
					Name:   "strip-vcs, s",
470
					Usage:  "Removes version control metadata (e.g, .git directory) from the vendor folder.",
471
					Hidden: true,
472
				},
473
				cli.BoolFlag{
474
					Name:  "strip-vendor, v",
475
					Usage: "Removes nested vendor and Godeps/_workspace directories.",
476
				},
477
				cli.BoolFlag{
478
					Name:  "skip-test",
479
					Usage: "Resolve dependencies in test files.",
480
				},
481
			},
482
			Action: func(c *cli.Context) error {
483
				if c.Bool("delete") {
484
					msg.Warn("The --delete flag is deprecated. This now works by default.")
485
				}
486
				if c.Bool("update-vendored") {
487
					msg.Warn("The --update-vendored flag is deprecated. This now works by default.")
488
				}
489
				if c.String("file") != "" {
490
					msg.Warn("The --flag flag is deprecated.")
491
				}
492
				if c.Bool("cache") {
493
					msg.Warn("The --cache flag is deprecated. This now works by default.")
494
				}
495
				if c.Bool("cache-gopath") {
496
					msg.Warn("The --cache-gopath flag is deprecated.")
497
				}
498
				if c.Bool("use-gopath") {
499
					msg.Warn("The --use-gopath flag is deprecated. Please see overrides.")
500
				}
501
				if c.Bool("strip-vcs") {
502
					msg.Warn("The --strip-vcs flag is deprecated. This now works by default.")
503
				}
504
505
				installer := repo.NewInstaller()
506
				installer.Force = c.Bool("force")
507
				installer.Home = c.GlobalString("home")
508
				installer.ResolveTest = !c.Bool("skip-test")
509
510
				action.Install(installer, c.Bool("strip-vendor"))
511
				return nil
512
			},
513
		},
514
		{
515
			Name:      "update",
516
			ShortName: "up",
517
			Usage:     "Update a project's dependencies",
518
			Description: `This updates the dependencies by scanning the codebase
519
   to determine the needed dependencies and fetching them following the rules
520
   in the glide.yaml file. When no rules exist the tip of the default branch
521
   is used. For more details see https://glide.sh/docs/glide.yaml
522
523
   If a dependency has a glide.yaml file, update will read that file and
524
   use the information contained there. Those dependencies are maintained in
525
   the top level 'vendor/' directory. 'vendor/foo/bar' will have its
526
   dependencies stored in 'vendor/'. This behavior can be disabled with
527
   '--no-recursive'. When this behavior is skipped a glide.lock file is not
528
   generated because the full dependency tree cannot be known.
529
530
   Glide will also import Godep, GB, GOM, and GPM files as it finds them in dependencies.
531
   It will create a glide.yaml file from the Godeps data, and then update. This
532
   has no effect if '--no-recursive' is set.
533
534
   The '--strip-vendor' flag will remove any nested 'vendor' folders and
535
   'Godeps/_workspace' folders after an update (along with undoing any Godep
536
   import rewriting). Note, the Godeps specific functionality is deprecated and
537
   will be removed when most Godeps users have migrated to using the vendor
538
   folder.`,
539
			Flags: []cli.Flag{
540
				cli.BoolFlag{
541
					Name:   "delete",
542
					Usage:  "Delete vendor packages not specified in config.",
543
					Hidden: true,
544
				},
545
				cli.BoolFlag{
546
					Name:  "no-recursive, quick",
547
					Usage: "Disable updating dependencies' dependencies. Only update things in glide.yaml.",
548
				},
549
				cli.BoolFlag{
550
					Name:  "force",
551
					Usage: "If there was a change in the repo or VCS switch to new one. Warning, changes will be lost.",
552
				},
553
				cli.BoolFlag{
554
					Name:  "all-dependencies",
555
					Usage: "This will resolve all dependencies for all packages, not just those directly used.",
556
				},
557
				cli.BoolFlag{
558
					Name:   "update-vendored, u",
559
					Usage:  "Update vendored packages (without local VCS repo). Warning, changes will be lost.",
560
					Hidden: true,
561
				},
562
				cli.StringFlag{
563
					Name:   "file, f",
564
					Usage:  "Save all of the discovered dependencies to a Glide YAML file.",
565
					Hidden: true,
566
				},
567
				cli.BoolFlag{
568
					Name:   "cache",
569
					Usage:  "When downloading dependencies attempt to cache them.",
570
					Hidden: true,
571
				},
572
				cli.BoolFlag{
573
					Name:   "cache-gopath",
574
					Usage:  "When downloading dependencies attempt to put them in the GOPATH, too.",
575
					Hidden: true,
576
				},
577
				cli.BoolFlag{
578
					Name:   "use-gopath",
579
					Usage:  "Copy dependencies from the GOPATH if they exist there.",
580
					Hidden: true,
581
				},
582
				cli.BoolFlag{
583
					Name:  "resolve-current",
584
					Usage: "Resolve dependencies for only the current system rather than all build modes.",
585
				},
586
				cli.BoolFlag{
587
					Name:   "strip-vcs, s",
588
					Usage:  "Removes version control metadata (e.g, .git directory) from the vendor folder.",
589
					Hidden: true,
590
				},
591
				cli.BoolFlag{
592
					Name:  "strip-vendor, v",
593
					Usage: "Removes nested vendor and Godeps/_workspace directories.",
594
				},
595
				cli.BoolFlag{
596
					Name:  "skip-test",
597
					Usage: "Resolve dependencies in test files.",
598
				},
599
			},
600
			Action: func(c *cli.Context) error {
601
				if c.Bool("delete") {
602
					msg.Warn("The --delete flag is deprecated. This now works by default.")
603
				}
604
				if c.Bool("update-vendored") {
605
					msg.Warn("The --update-vendored flag is deprecated. This now works by default.")
606
				}
607
				if c.String("file") != "" {
608
					msg.Warn("The --flag flag is deprecated.")
609
				}
610
				if c.Bool("cache") {
611
					msg.Warn("The --cache flag is deprecated. This now works by default.")
612
				}
613
				if c.Bool("cache-gopath") {
614
					msg.Warn("The --cache-gopath flag is deprecated.")
615
				}
616
				if c.Bool("use-gopath") {
617
					msg.Warn("The --use-gopath flag is deprecated. Please see overrides.")
618
				}
619
				if c.Bool("strip-vcs") {
620
					msg.Warn("The --strip-vcs flag is deprecated. This now works by default.")
621
				}
622
623
				if c.Bool("resolve-current") {
624
					util.ResolveCurrent = true
625
					msg.Warn("Only resolving dependencies for the current OS/Arch")
626
				}
627
628
				installer := repo.NewInstaller()
629
				installer.Force = c.Bool("force")
630
				installer.ResolveAllFiles = c.Bool("all-dependencies")
631
				installer.Home = c.GlobalString("home")
632
				installer.ResolveTest = !c.Bool("skip-test")
633
634
				action.Update(installer, c.Bool("no-recursive"), c.Bool("strip-vendor"))
635
636
				return nil
637
			},
638
		},
639
		{
640
			Name:  "tree",
641
			Usage: "(Deprecated) Tree prints the dependencies of this project as a tree.",
642
			Description: `This scans a project's source files and builds a tree
643
   representation of the import graph.
644
645
   It ignores testdata/ and directories that begin with . or _. Packages in
646
   vendor/ are only included if they are referenced by the main project or
647
   one of its dependencies.
648
649
   Note, for large projects this can display a large list tens of thousands of
650
   lines long.`,
651
			Action: func(c *cli.Context) error {
652
				action.Tree(".", false)
653
				return nil
654
			},
655
		},
656
		{
657
			Name:  "list",
658
			Usage: "List prints all dependencies that the present code references.",
659
			Description: `List scans your code and lists all of the packages that are used.
660
661
   It does not use the glide.yaml. Instead, it inspects the code to determine what packages are
662
   imported.
663
664
   Directories that begin with . or _ are ignored, as are testdata directories. Packages in
665
   vendor are only included if they are used by the project.`,
666
			Action: func(c *cli.Context) error {
667
				action.List(".", true, c.String("output"))
668
				return nil
669
			},
670
			Flags: []cli.Flag{
671
				cli.StringFlag{
672
					Name:  "output, o",
673
					Usage: "Output format. One of: json|json-pretty|text",
674
					Value: "text",
675
				},
676
			},
677
		},
678
		{
679
			Name:  "info",
680
			Usage: "Info prints information about this project",
681
			Flags: []cli.Flag{
682
				cli.StringFlag{
683
					Name:  "format, f",
684
					Usage: `Format of the information wanted (required).`,
685
				},
686
			},
687
			Description: `A format containing the text with replacement variables
688
   has to be passed in. Those variables are:
689
690
       %n - name
691
       %d - description
692
       %h - homepage
693
       %l - license
694
695
   For example, given a project with the following glide.yaml:
696
697
       package: foo
698
       homepage: https://example.com
699
       license: MIT
700
       description: Some example description
701
702
   Then running the following commands:
703
704
       glide info -f %n
705
          prints 'foo'
706
707
       glide info -f "License: %l"
708
          prints 'License: MIT'
709
710
       glide info -f "%n - %d - %h - %l"
711
          prints 'foo - Some example description - https://example.com - MIT'`,
712
			Action: func(c *cli.Context) error {
713
				if c.IsSet("format") {
714
					action.Info(c.String("format"))
715
				} else {
716
					cli.ShowCommandHelp(c, c.Command.Name)
717
				}
718
				return nil
719
			},
720
		},
721
		{
722
			Name:      "cache-clear",
723
			ShortName: "cc",
724
			Usage:     "Clears the Glide cache.",
725
			Action: func(c *cli.Context) error {
726
				action.CacheClear()
727
				return nil
728
			},
729
		},
730
		{
731
			Name:  "about",
732
			Usage: "Learn about Glide",
733
			Action: func(c *cli.Context) error {
734
				action.About()
735
				return nil
736
			},
737
		},
738
		{
739
			Name:  "mirror",
740
			Usage: "Manage mirrors",
741
			Description: `Mirrors provide the ability to replace a repo location with
742
   another location that's a mirror of the original. This is useful when you want
743
   to have a cache for your continuous integration (CI) system or if you want to
744
   work on a dependency in a local location.
745
746
   The mirrors are stored in a mirrors.yaml file in your GLIDE_HOME.
747
748
   The three commands to manage mirrors are 'list', 'set', and 'remove'.
749
750
   Use 'set' in the form:
751
752
       glide mirror set [original] [replacement]
753
754
   or
755
756
       glide mirror set [original] [replacement] --vcs [type]
757
758
   for example,
759
760
       glide mirror set https://github.com/example/foo https://git.example.com/example/foo.git
761
762
       glide mirror set https://github.com/example/foo file:///path/to/local/repo --vcs git
763
764
   Use 'remove' in the form:
765
766
       glide mirror remove [original]
767
768
   for example,
769
770
       glide mirror remove https://github.com/example/foo`,
771
			Subcommands: []cli.Command{
772
				{
773
					Name:  "list",
774
					Usage: "List the current mirrors",
775
					Action: func(c *cli.Context) error {
776
						return action.MirrorsList()
777
					},
778
				},
779
				{
780
					Name:  "set",
781
					Usage: "Set a mirror. This overwrites an existing entry if one exists",
782
					Description: `Use 'set' in the form:
783
784
       glide mirror set [original] [replacement]
785
786
   or
787
788
       glide mirror set [original] [replacement] --vcs [type]
789
790
   for example,
791
792
       glide mirror set https://github.com/example/foo https://git.example.com/example/foo.git
793
794
       glide mirror set https://github.com/example/foo file:///path/to/local/repo --vcs git`,
795
					Flags: []cli.Flag{
796
						cli.StringFlag{
797
							Name:  "vcs",
798
							Usage: "The VCS type to use. Autodiscovery is attempted when not supplied. Can be one of git, svn, bzr, or hg",
799
						},
800
					},
801
					Action: func(c *cli.Context) error {
802
						return action.MirrorsSet(c.Args().Get(0), c.Args().Get(1), c.String("vcs"))
803
					},
804
				},
805
				{
806
					Name:      "remove",
807
					ShortName: "rm",
808
					Usage:     "Remove a mirror",
809
					Description: `Use 'remove' in the form:
810
811
       glide mirror remove [original]
812
813
   for example,
814
815
       glide mirror remove https://github.com/example/foo`,
816
					Action: func(c *cli.Context) error {
817
						return action.MirrorsRemove(c.Args().Get(0))
818
					},
819
				},
820
			},
821
		},
822
	}
823
}
824
825
// startup sets up the base environment.
826
//
827
// It does not assume the presence of a Glide.yaml file or vendor/ directory,
828
// so it can be used by any Glide command.
829
func startup(c *cli.Context) error {
830
	action.Debug(c.Bool("debug"))
831
	action.NoColor(c.Bool("no-color"))
832
	action.Quiet(c.Bool("quiet"))
833
	action.Init(c.String("yaml"), c.String("home"))
834
	action.EnsureGoVendor()
835
	gpath.Tmp = c.String("tmp")
836
	return nil
837
}
838
839
func shutdown(c *cli.Context) error {
840
	cache.SystemUnlock()
841
	return nil
842
}
843
844
// Get the path to the glide.yaml file.
845
//
846
// This returns the name of the path, even if the file does not exist. The value
847
// may be set by the user, or it may be the default.
848
func glidefile(c *cli.Context) string {
849
	path := c.String("file")
850
	if path == "" {
851
		// For now, we construct a basic assumption. In the future, we could
852
		// traverse backward to see if a glide.yaml exists in a parent.
853
		path = "./glide.yaml"
854
	}
855
	a, err := filepath.Abs(path)
856
	if err != nil {
857
		// Underlying fs didn't provide working dir.
858
		return path
859
	}
860
	return a
861
}
862