Manul is a vendoring utility for Go programs.
manul can be obtained using go get
:
go get github.com/kovetskiy/manul
Packages are also available for Ubuntu/Debian and Arch Linux.
Because all other vendor utilities suffer from the following:
-
Some wrap the
go
binary and spoof theGOPATH
env variable. You will have a non-go-gettable project which needs additional software in order to compile and run; -
Some copy the source code of dependencies into the vendor directory:
- It will be nearly impossible to find anything using GitHub Search, because you will get many false-positive results;
- Updating dependencies will require manual intervention and committing a lot of modified lines straight into the main repo;
- You will not be able to tell what version of dependency your project is using will by looking at repository; you have to keep versions in the additional ambiguous file with vendors associated with commits.
-
Various architecture problems:
- Impossible to update all or specific vendored dependencies;
- Impossible to rollback vendored dependencies to specific version;
- Impossible to remove unused vendored dependencies;
- Impossible to lock version of vendored dependency.
We all love git, it's a very powerful instrument. Why don't we use its power for vendoring dependencies using an awesome feature, which is called git submodule?
With git submodule you will have a git repository for each dependency.
They can be managed in the same way as main project by git
.
Pros:
-
No need for additional software for building/running your Go project;
-
No need for additional JSON/TOML/YAML file for storing dependencies;
-
Update vendored dependencies directly from remote origins;
-
Rollback changes in dependencies;
-
Go-gettable
git submodule might look like a Silver Bullet, but it's still clumsy to work with manually. We want to have a powerful yet simple interface for vendoring dependencies using this technology.
manul can do it for us.
First of all, we should request dependencies which we have in our project.
To do this, just run manul with -Q
(query) flag. It will output all the
project imports (dependencies), like this:
For example, we have six dependencies, let's lock versions of critical
dependencies by adding submodules: in our case it's zhash
and blackfriday
packages.
For locking versions (installing dependencies) we should use -I
(install)
flag and specify dependencies, which we wish to install:
After installation we can have a look for vendored and non-vendored
dependencies by using flag -Q
. After previous step we should see git commits
along with two already vendored dependencies (zhash
and blackfriday
):
Let's install submodules for remaining dependencies, go the limit! Just run
manul with flag -I
without specifying any dependencies, manul will
install all detected dependencies with skipping already vendored:
Wow, that was crazy! Now, to update some vendored dependencies, for example,
docopt-go
package, manul should be invoked with the flag -U
and import path
(github.com/docopt/docopt-go
):
manul can be used to remove specified submodules of vendored dependencies
by using -R
(remove) flag and specifying dependencies import path:
By the way, manul can detect and remove unused vendored dependencies using -C
(clean) flag:
manul can also get you a specific version of a dependency by using a commit-ish, for example:
manul -I golang.org/x/foo=34a235h1
will installfoo
at the specified commitmanul -U github.com/x/bar=this-tag
will update it tothis-tag
version.
Let's summarize:
-I [<dependency>...]
- install git submodules for specified/all dependencies;-U [<dependency>...]
- update specified/all already vendored dependencies;-R [<dependency>...]
- remove git submodules for specified/all dependencies;-Q [<dependency>...]
- list all used dependencies;-C
- detect and remove all git submodules for unused vendored dependencies.
You can see similar help message by passing -h
or --help
flag.