github.com/hori-ryota/glide@v0.0.0-20160621143827-dc7ca2fac035/glide.go (about)

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