Gopkg.lock file is generated by
dep ensure and
dep init. It is the output of the solving function: a transitively complete snapshot of a project's dependency graph, expressed as a series of
[[project]] stanzas. That means:
Gopkg.lock also contains some metadata about the algorithm used to arrive at the final graph, under
Gopkg.lock always includes a
revision for all listed dependencies, as the semantics of
revision guarantee them to be immutable. Thus, the
Gopkg.lock acts as a reproducible build list - as long as the upstream remains available, all dependencies can be precisely reproduced.
Gopkg.lock is autogenerated; editing it manually is generally an antipattern. If there is a goal you can only achieve by hand-editing
Gopkg.lock, it is at least a feature request, and likely a bug.
The dependency graph is expressed as a series of
[[projects]] stanzas, each representing a single dependency project. A given project can only appear once in the list, and the version information expressed about them encompasses all contained packages - it is not possible to have multiple packages from a single project at different versions.
These are all the properties that can appear in a
[[projects]] stanza, and whether or not they are guaranteed to be present/must be present for a stanza to be valid.
The project to which the stanza applies, as identified by its project root.
If present, it indicates the upstream source from which the project should be retrieved. It has the same properties as
A complete list of directories from within the source that dep determined to be necessary for the build.
In general, this is the set of packages that were found to be participants in the package import graph, through at least one but as many as all of the following mechanisms:
- Being in the current project's
- Being imported by a package from either the current project or a different dependency
- Being imported by a package from within this project that, directly or transitively, is imported by a package from a different project
In order to provide reproducible builds, it is an absolute requirement that every project stanza contain a
revision, no matter what kinds of constraints were encountered in
Gopkg.toml files. It is further possible that exactly one of either
branch will additionally be present.
When one of the other two are present, the
revision is understood to be the underlying, immutable identifier that corresponded to that
branch at the time when the
Gopkg.lock was written.
Metadata contained in this section tells us about the algorithm that was used to generate the
Gopkg.lock file. These are very coarse indicators, primarily used to trigger a re-evaluation of the lock when it might have become invalid, as well as warn a team when its members are using algorithms with potentially subtly different effects.
More details on "analyzer" and "solver" follow, but the versioning principle is the same: algorithmic changes that result in a decrease to the set of acceptable solutions for at least one input set generally require a version bump, while changes that increase the size of that set do not. However, this is not a formal definition; we leave room for judgment calls on small changes and bug fixes, and we bump at most once per release.
By bumping versions only on solution set contractions, but not expansions, it allows us to avoid having to bump constantly (which could make using dep across teams awkward), while still making it likely that when the solver and version numbers match between
Gopkg.lock and a running version of dep, what's recorded in the file is acceptable by the running version's rules.
The analyzer is an internal dep component responsible for interpreting the contents of
Gopkg.toml files, as well as metadata files from any tools dep knows about:
The analyzer is named because the dep needs to identify itself to its engine, gps (
github.com/golang/dep/gps); gps knows nothing about dep. The analyzer version is bumped when something in the analyzer's logic begins treating data that it already accepted in a significantly different way, or stops accepting a particular class of data. It is not changed when support for entirely new types of data are added.
For example, if dep's analyzer stopped supporting automated conversions from glide, then that would not require bumping the analyzer version, as doing so makes more solutions possible. Adding support for converting from a new tool, or changing the interpretation of
version fields in
Gopkg.toml so that it was only allowed to specify minimum versions, would entail a version bump.
The solver is the algorithm behind the solving function. It selects all the versions that ultimately appear in
Gopkg.lock by finding a combination that satisfies all the rules, including those from
Gopkg.toml (fed to the solver by the analyzer).
The solver is named because, like the analyzer, it is pluggable; an alternative algorithm could be written that applies different rules to achieve the same goal. The one dep uses, "gps-cdcl", is named after the general class of SAT solving algorithm it most resembles, though the algorithm is actually a specialized, domain-specific SMT solver.
The same general principles of version-bumping apply to the solver version: if the solver starts enforcing Go 1.4 import path comments, that entails a bump, because it can only narrow the solution set. If it were to later relax that requirement, it would not require a bump, as that can only expand the solution set.
A SHA256 hash digest of all the inputs to the solving function. Those inputs can be shown directly with the hidden command
dep hash-inputs, allowing this value to be generated directly:
dep hash-inputs | tr -d “\n” | shasum -a256