Gopkg.toml是在执行dep init时创建,主要被手动编辑,可以使用以下规则声明方式来改变dep的行为:
-
允许使用
constraints
和overrides
指定可以接受的版本,以及指定获取来源(比如指定依赖的某个第三方库为特定版本号) -
允许使用
required
andignored
来分别增加或排除import路径,进而操纵import graph(允许在go/src之外存放依赖) - 允许使用
metadata
来定义key-value元数据,dep会忽略这些数据,为在dep之上的构建工具链提供支持(CI/自动化编译/自动化部署/自动化测试等流程) -
prune
可以用来定义哪些文件或路径被认为是不必要的,也就是说可以从vendor中移除(也就是说保持vendor精简) -
noverify
用来指定vendor verification需要跳过的一系列的项目路径。
要注意的是,任何required,或者ignored字段,必须出现在所有的[[constraint]]以及[[override]]之前
依赖规则[[constraint]]
and [[override]]
都允许包含如下字段
name
- the import path corresponding to the source root of a dependency (generally: where the VCS root is)
- At most one version rule
- An optional
source
rule -
metadata
that is specific to thename
'd project
A full example (invalid, actually, as it has more than one version rule, for illustrative purposes) of either one of these stanzas looks like this:
[[constraint]]
# Required: the root import path of the project being constrained.
name = "github.com/user/project"
# Recommended: the version constraint to enforce for the project.
# Note that only one of "branch", "version" or "revision" can be specified.
version = "1.0.0"
branch = "master"
revision = "abc123"
# Optional: an alternate location (URL or import path) for the project's source.
source = "https://github.com/myfork/package.git"
# Optional: metadata about the constraint or override that could be used by other independent systems
[metadata]
key1 = "value that convey data to other systems"
system1-data = "value that is used by a system"
system2-data = "value that is used by another system"
[[constraint]]
A [[constraint]]
stanza defines rules for how a direct dependency must be incorporated into the dependency graph. Dep respects these declarations from the current project's Gopkg.toml
, as well as the Gopkg.toml
files found in any dependencies.
Use this for: having a direct dependency use a specific branch, version range, revision, or alternate source (such as a fork).
[[override]]
An [[override]]
stanza differs from a [[constraint]]
in that it applies to all dependencies, direct and transitive, and supersedes all other [[constraint]]
declarations for that project. However, only overrides from the current project's Gopkg.toml
are incorporated.
Use this for: Overrides are primarily intended as a way of eliminating disagreements between multiple irreconcilable [[constraint]]
declarations on a single dependency. However, they will also be your primary recourse if you need to constrain a transitive dependency's version?
Overrides should be used cautiously and temporarily, when possible.
source
A source
rule can specify an alternate location from which the name
'd project should be retrieved. It is primarily useful for temporarily specifying a fork for a repository.
source
rules are generally brittle and should only be used when there is no other recourse. Using them to try to circumvent network reachability issues is typically an antipattern.
版本号规则
[[constraint]]和[[override]]都可以指定版本号规则,可以使用version, branch, revision其中之一来指定(也只能选择一种);
version对应于VCS的tag,或者一个版本号范围(or a semantic version, or a range of semantic version):
version="=1.2.3"用来指定确切的版本号,也就是1.2.3这个版本;
version="!=1.2.3"用来排除某个版本号,也就是说只要不是1.2.3这个版本就行;
version="1.2.3-2.1.2"用来指定版本号范围;
类似还有:
>, >=, <, <=
不过,你可能没想到的还有,
version = "~1.2.3"意思是,只允许最后一段版本号变化;
version = "^1.2.3"意思是,除了非0的最大的一段版本号不允许变化,后面的版本号都可以变化;
^1.2.3 means 1.2.3 <= X < 2.0.0
^0.2.3 means 0.2.3 <= X < 0.3.0
^0.0.3 means 0.0.3 <= X < 0.1.0
另外还允许通配符(肯定脑子进水了,才这样去做事情)。
所以,要想锁定一个版本号,你要这样做:
[[constraint]]
name = "github.com/pkg/errors"
version = "=0.8.0"
有时候,有些仓库不会使用version,而是使用branch。语法是:
branch="feature_support_dynamic_routing"
然而,如果你指定branch="master"不是个好主意。因为master从来不意味着不再改变。
一般情况下,应该优先使用语义上的版本(you should prefer semantic versions to branches, when a project has made them available),而不是branch。
revision是底层的不可变的标识符,就像git commit的sha1. (While it is allowed to constrain to a revision
, doing so is almost always an antipattern)
老夫看的萌萌的,一句话就是尽量别用revision来约束。
The required
and ignored
rules manipulate that graph, in ways that are roughly dual to each other: required
adds import paths to the graph, and ignored
removes them.
required
required
lists a set of packages (not projects) that must be included in Gopkg.lock. This list is merged with the set of packages imported by the current project.
required = ["github.com/user/thing/cmd/thing"]
Use this for: linters, generators, and other development tools that
- Are needed by your project
- Aren't
import
ed by your project, directly or transitively - You don't want to put them in your
GOPATH
, and/or you want to lock the version
Please note that this only pulls in the sources of these dependencies. It does not install or compile them. So, if you need the tool to be installed you should still run the following (manually or from a Makefile
) after each dep ensure
:
cd vendor/pkg/to/install
go install .
This only works reliably if this is the only project to install these executables. This is not enough if you want to be able to run a different version of the same executable depending on the project you're working. In that case you have to use a different GOBIN
for each project, by doing something like this before running the above commands:
export GOBIN=$PWD/bin
export PATH=$GOBIN:$PATH
You might also try virtualgo, which installs dependencies in the required
list automatically in a project specific GOBIN
.
ignored
用来指定dep静态分析代码生成Gopkg.lock时需要忽略的包列表(如果包依赖了其他包X,并且X包只在这里被依赖,那么X也将被忽略),注意这里说的包可以是dependency中的包。ignored = ["github.com/user/project/badpkg"]
你还是可以用通配符的:
ignored = ["github.com/user/project/badpkg*"]
metadata可以在Gopkg.toml中root级别存在,也可以在constraint, override中存在。
dep会假装看不见metadata.
prune
defines the global and per-project prune options for dependencies. The options determine which files are discarded when writing the vendor/
tree.
The following are the current available options:
-
unused-packages
indicates that files from directories that do not appear in the package import graph should be pruned. -
non-go
prunes files that are not used by Go. -
go-tests
prunes Go test files.
Out of an abundance of caution, dep non-optionally preserves files that may have legal significance.
Pruning options are disabled by default. However, generating a Gopkg.toml
via dep init
will add lines to enable go-tests
and unused-packages
prune options at the root level.
[prune]
go-tests = true
unused-packages = true
The same prune options can be defined per-project. An additional name
field is required and, as with [[constraint]]
and [[override]]
, should be a source root, not just any import path.
[prune]
non-go = true
[[prune.project]]
name = "github.com/project/name"
go-tests = true
non-go = false
Almost all projects will be fine without setting any project-specific rules, and enabling the following pruning rules globally:
[prune]
unused-packages = true
go-tests = true
It is usually safe to set non-go = true
, as well. However, as dep only has a clear model for the role played by Go files, and non-Go files necessarily fall outside that model, there can be no comparable general definition of safety.
noverify
The noverify
field is a list of paths, typically project roots, to exclude from vendor verification.
Dep uses per-project hash digests, computed after pruning and recorded in Gopkg.lock, to determine if the contents of vendor/
are as expected. If the recorded digest and the hash of the corresponding tree in vendor/
differ, that project is considered to be out of sync:
-
dep ensure
will regenerate it -
dep check
will complain of a hash mismatch and exit 1
It is strongly recommended that you leave vendor/
unmodified, in whatever state dep puts it in. However, this isn't always feasible. If you have no choice but to modify vendor/
for a particular project, then add the project root for that project to noverify
. This will have the following effects:
-
dep ensure
will ignore hash mismatches for the project, and only regenerate it invendor/
if absolutely necessary (prune options change, package list changes, version changes) -
dep check
will continue to report hash mismatches (albeit with an annotation aboutnoverify
) for the project, but will no longer exit 1.
noverify
can also be used to preserve certain excess paths that would otherwise be removed; for example, adding WORKSPACE
to the noverify
list would allow you to preserve vendor/WORKSPACE
, which can help with some Bazel-based workflows.
Scope
dep
evaluates
[[override]]
required
ignored
only in the root project, i.e. the project where dep
runs. For example, if you have a project: github.com/urname/goproject
, and github.com/foo/bar
is a dependency for your project, then dep will evaluate the Gopkg.toml
files of these projects as follows:
github.com/urname/goproject | github.com/foo/bar |
---|---|
[[constraint]] ✔ | [[constraint]] ✔ |
[[override]] ✔ | [[override]] ✖ |
required ✔ | required ✖ |
ignored ✔ | ignored ✖ |
✔ : Evaluated ✖ : Not evaluated
Example
Here's a sample Gopkg.toml
with most elements present.
required = ["github.com/user/thing/cmd/thing"]
ignored = [
"github.com/user/project/pkgX",
"bitbucket.org/user/project/pkgA/pkgY"
]
noverify = ["github.com/something/odd"]
[metadata]
codename = "foo"
[prune]
non-go = true
[[prune.project]]
name = "github.com/project/name"
go-tests = true
non-go = false
[[constraint]]
name = "github.com/user/project"
version = "1.0.0"
[constraint.metadata]
property1 = "value1"
property2 = 10
[[constraint]]
name = "github.com/user/project2"
branch = "dev"
source = "github.com/myfork/project2"
[[override]]
name = "github.com/x/y"
version = "2.4.0"
[override.metadata]
propertyX = "valueX"