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