With the release of Go 1.5 comes experimental support for vendor packages. We found this setup to be so useful we pivoted Glide, the Go package manager, to focus on supporting this new vendor setup. In this post I’ll walk through how it works.
Turning On The Vendor Support
The vendor support in Go 1.5 is opt-in. To enable it you need to set the
environment variable GO15VENDOREXPERIMENT to 1. For example,
export GO15VENDOREXPERIMENT=1
Once this is set the go tool will will look for vendor packages in the
vendor directory for a project. The directory structure within the vendor
directory mirrors that of $GOPATH/src and comes first when the go tool
searches for packages.
The structure looks like:
- myProject (Your project)
|
|-- main.go (Your main go code can live here)
|
|-- mySubpackage (You can create your own subpackages, too)
| |
| |-- foo.go
|
|-- vendor
|-- github.com
|
|-- Masterminds
|
|-- ... etc.
Beyond this basic support for a vendor directory the go tool provides little
help. That means it doesn’t provide the tooling to manage packages in this
directory. That’s where Glide comes in.
The Basics of Glide
Once you have the glide tool installed your project needs two things.
glide.yaml
First, there is the glide.yaml file where packages and their versions are
documented. You can either create this by hand or use the glide init function
to create one for you. The format looks like:
package: github.com/Masterminds/glide
import:
- package: github.com/kylelemons/go-gypsy
subpackages:
- yaml
- package: github.com/Masterminds/cookoo
ref: master
repo: git@github.com:Masterminds/cookoo.git
vcs: git
subpackages:
- .
- package: github.com/Masterminds/vcs
- package: github.com/codegangsta/cli
The package top level property is the name of your project. Under import is
a list of the packages to pull into the vendor directory and manage.
If the package name, using the package key, is the only element the latest
commit on the default branch will be be used. This is the same version go get
retrieves if it were to do any management of the vendor directory.
The vcs, repo, and ref keys for an import are where things get interesting.
This allows you to set version control system, repo, and reference. For example,
a package name could be github.com/Masterminds/cookoo. But, the repo could be
git@github.com/mattfarina/cookoo where I keep a fork. The right import path
will be used along with my repo of choice. No import rewriting required.
The ref key allows you to set any reference supported by the underlying VCS.
That includes branches, tags, and individual commit ids.
glide up
Once you have a glide.yaml file defining your packages you can use the glide up
command (aliased to update and install). This will fetch the packages, put
them in the vendor directory, and set the referenced version.
glide up, by default, supports recursively fetching dependencies. So, if one
of your dependencies has a list of dependencies it will fetch those as well.
While we often don’t vendor packages by checking them into our VCS we know
others do. To support those who do vendor packages from vendors, when recursively
installing updates Glide skips packages that have an existing vendor directory.
If the vendor directory exists we assume that package is vendoring packages.
Godep, GPM, and Imports
There are a lot of projects being managed by Godep and GPM and they have done a great job up to this point. With Go 1.5 we wanted the ability import from these systems to the new vendor setup.
If you add the --import flag to glide up or glide get (we’ll talk more
about that in a minute) it will automatically import Godep and GPM dependencies
into each projects vendor directory and create a glide.yaml file for the
project populated with the packages and their versions. This works recursively
with glide up (if you don’t opt out of the recursion).
If you want to convert a project, Glide has the glide import command that can
import from these systems to a glide.yaml file.
Adding Packages with glide get
The go get command is handy to add packages to your GOPATH. But, it doesn’t
support adding packages to a vendor directory. So, we added glide get [package].
Using this command will add the package to your vendor directory and glide.yaml
file.
Scripting with Glide
While the vendor directory is special, once you opt-in, not every tool realizes
this. For example, running go test ./... will test your package and every
package in your vendor directory.
To support scripting we’ve created the glide novendor and glide name. The
glide name command simply returns the name of the package. The more interesting
command is novendor. It will give you all the directories except the vendor
one. So, to test your package and not the packages in vendor you could use
the command:
$ go test $(glide novendor)
Dive In, Find Bugs, and Help Us Improve
This is just the quick rundown of Glide 0.5. We hope you like it and we know it would benefit from continued improvement. Please dive in, take it for a spin, find bugs and file them, and help us improve Glide.