github.com/danusarf/glide@v0.13.4-0.20210514084836-b5dc6967662e/glide.go (about)

     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/danusarf/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/danusarf/glide/action"
    25  	"github.com/danusarf/glide/cache"
    26  	"github.com/danusarf/glide/msg"
    27  	gpath "github.com/danusarf/glide/path"
    28  	"github.com/danusarf/glide/repo"
    29  	"github.com/danusarf/glide/util"
    30  
    31  	"github.com/urfave/cli"
    32  
    33  	"fmt"
    34  	"os"
    35  )
    36  
    37  var version = "0.13.4-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/danusarf/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  }