Documentation ¶
Index ¶
- func IsAny(c Constraint) bool
- func SortForDowngrade(vl []Version)
- func SortForUpgrade(vl []Version)
- func SortLockedProjects(lps []LockedProject)
- func WriteDepTree(basedir string, l Lock, sm SourceManager, sv bool) error
- type Constraint
- type CouldNotCreateLockError
- type LocalImportsError
- type Lock
- type LockedProject
- type Manifest
- type Package
- type PackageOrErr
- type PackageTree
- type PairedVersion
- type ProjectAnalyzer
- type ProjectConstraint
- type ProjectConstraints
- type ProjectIdentifier
- type ProjectProperties
- type ProjectRoot
- type ReachMap
- type Revision
- type RootManifest
- type SimpleLock
- type SimpleManifest
- type Solution
- type SolveParameters
- type Solver
- type SourceManager
- type SourceMgr
- func (sm *SourceMgr) AnalyzerInfo() (name string, version *semver.Version)
- func (sm *SourceMgr) DeduceProjectRoot(ip string) (ProjectRoot, error)
- func (sm *SourceMgr) ExportProject(id ProjectIdentifier, v Version, to string) error
- func (sm *SourceMgr) GetManifestAndLock(id ProjectIdentifier, v Version) (Manifest, Lock, error)
- func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error)
- func (sm *SourceMgr) ListVersions(id ProjectIdentifier) ([]Version, error)
- func (sm *SourceMgr) Release()
- func (sm *SourceMgr) RevisionPresentIn(id ProjectIdentifier, r Revision) (bool, error)
- func (sm *SourceMgr) SourceExists(id ProjectIdentifier) (bool, error)
- func (sm *SourceMgr) SyncSourceFor(id ProjectIdentifier) error
- type UnpairedVersion
- type Version
- type VersionType
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsAny ¶ added in v0.2.0
func IsAny(c Constraint) bool
IsAny indicates if the provided constraint is the wildcard "Any" constraint.
func SortForDowngrade ¶ added in v0.10.1
func SortForDowngrade(vl []Version)
SortForDowngrade sorts a slice of []Version in roughly ascending order, so that presumably older versions are visited first.
This is *not* the same as reversing SortForUpgrade (or you could simply sort.Reverse()). The type precedence is the same, including the semver vs. semver-with-prerelease relation. Lexicographical comparisons within non-semver tags, branches, and revisions remains the same as well; because we treat these domains as having no ordering relation, there can be no real concept of "upgrade" vs "downgrade", so there is no reason to reverse them.
Thus, the only binary relation that is reversed for downgrade is within-type comparisons for semver.
So, given a slice of the following versions:
- Branch: master devel
- Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1
- Non-semver tags: footag
- Revision: f6e74e8d
Sorting for downgrade will result in the following slice.
[v1.0.0 v1.1.0 v1.1.0-alpha1 footag devel master f6e74e8d]
func SortForUpgrade ¶ added in v0.10.1
func SortForUpgrade(vl []Version)
SortForUpgrade sorts a slice of []Version in roughly descending order, so that presumably newer versions are visited first. The rules are:
- All semver versions come first, and sort mostly according to the semver 2.0 spec (as implemented by github.com/Masterminds/semver lib), with one exception:
- Semver versions with a prerelease are after *all* non-prerelease semver. Within this subset they are sorted first by their numerical component, then lexicographically by their prerelease version.
- The default branch(es) is next; the exact semantics of that are specific to the underlying source.
- All other branches come next, sorted lexicographically.
- All non-semver versions (tags) are next, sorted lexicographically.
- Revisions, if any, are last, sorted lexicographically. Revisions do not typically appear in version lists, so the only invariant we maintain is determinism - deeper semantics, like chronology or topology, do not matter.
So, given a slice of the following versions:
- Branch: master devel
- Semver tags: v1.0.0, v1.1.0, v1.1.0-alpha1
- Non-semver tags: footag
- Revision: f6e74e8d
Sorting for upgrade will result in the following slice.
[v1.1.0 v1.0.0 v1.1.0-alpha1 footag devel master f6e74e8d]
func SortLockedProjects ¶ added in v0.10.1
func SortLockedProjects(lps []LockedProject)
SortLockedProjects sorts a slice of LockedProject in alphabetical order by ProjectRoot.
func WriteDepTree ¶ added in v0.10.0
func WriteDepTree(basedir string, l Lock, sm SourceManager, sv bool) error
WriteDepTree takes a basedir and a Lock, and exports all the projects listed in the lock to the appropriate target location within the basedir.
If the goal is to populate a vendor directory, basedir should be the absolute path to that vendor directory, not its parent (a project root, typically).
It requires a SourceManager to do the work, and takes a flag indicating whether or not to strip vendor directories contained in the exported dependencies.
Types ¶
type Constraint ¶
type Constraint interface { fmt.Stringer // Matches indicates if the provided Version is allowed by the Constraint. Matches(Version) bool // MatchesAny indicates if the intersection of the Constraint with the // provided Constraint would yield a Constraint that could allow *any* // Version. MatchesAny(Constraint) bool // Intersect computes the intersection of the Constraint with the provided // Constraint. Intersect(Constraint) Constraint // contains filtered or unexported methods }
A Constraint provides structured limitations on the versions that are admissible for a given project.
As with Version, it has a private method because the gps's internal implementation of the problem is complete, and the system relies on type magic to operate.
func NewSemverConstraint ¶ added in v0.4.0
func NewSemverConstraint(body string) (Constraint, error)
NewSemverConstraint attempts to construct a semver Constraint object from the input string.
If the input string cannot be made into a valid semver Constraint, an error is returned.
type CouldNotCreateLockError ¶ added in v0.11.0
CouldNotCreateLockError describe failure modes in which creating a SourceMgr did not succeed because there was an error while attempting to create the on-disk lock file.
func (CouldNotCreateLockError) Error ¶ added in v0.11.0
func (e CouldNotCreateLockError) Error() string
type LocalImportsError ¶ added in v0.7.0
LocalImportsError indicates that a package contains at least one relative import that will prevent it from compiling.
TODO(sdboyer) add a Files property once we're doing our own per-file parsing
func (*LocalImportsError) Error ¶ added in v0.7.0
func (e *LocalImportsError) Error() string
type Lock ¶
type Lock interface { // The hash of inputs to gps that resulted in this lock data InputHash() []byte // Projects returns the list of LockedProjects contained in the lock data. Projects() []LockedProject }
Lock represents data from a lock file (or however the implementing tool chooses to store it) at a particular version that is relevant to the satisfiability solving process.
In general, the information produced by gps on finding a successful solution is all that would be necessary to constitute a lock file, though tools can include whatever other information they want in their storage.
type LockedProject ¶ added in v0.2.0
type LockedProject struct {
// contains filtered or unexported fields
}
LockedProject is a single project entry from a lock file. It expresses the project's name, one or both of version and underlying revision, the network URI for accessing it, the path at which it should be placed within a vendor directory, and the packages that are used in it.
func NewLockedProject ¶ added in v0.2.0
func NewLockedProject(id ProjectIdentifier, v Version, pkgs []string) LockedProject
NewLockedProject creates a new LockedProject struct with a given ProjectIdentifier (name and optional upstream source URL), version. and list of packages required from the project.
Note that passing a nil version will cause a panic. This is a correctness measure to ensure that the solver is never exposed to a version-less lock entry. Such a case would be meaningless - the solver would have no choice but to simply dismiss that project. By creating a hard failure case via panic instead, we are trying to avoid inflicting the resulting pain on the user by instead forcing a decision on the Analyzer implementation.
func (LockedProject) Ident ¶ added in v0.2.0
func (lp LockedProject) Ident() ProjectIdentifier
Ident returns the identifier describing the project. This includes both the local name (the root name by which the project is referenced in import paths) and the network name, where the upstream source lives.
func (LockedProject) Packages ¶ added in v0.11.2
func (lp LockedProject) Packages() []string
Packages returns the list of packages from within the LockedProject that are actually used in the import graph. Some caveats:
- The names given are relative to the root import path for the project. If the root package itself is imported, it's represented as ".".
- Just because a package path isn't included in this list doesn't mean it's safe to remove - it could contain C files, or other assets, that can't be safely removed.
- The slice is not a copy. If you need to modify it, copy it first.
func (LockedProject) Version ¶ added in v0.2.0
func (lp LockedProject) Version() Version
Version assembles together whatever version and/or revision data is available into a single Version.
type Manifest ¶ added in v0.1.0
type Manifest interface { // Returns a list of project-level constraints. DependencyConstraints() ProjectConstraints // Returns a list of constraints applicable to test imports. // // These are applied only when tests are incorporated. Typically, that // will only be for root manifests. TestDependencyConstraints() ProjectConstraints }
Manifest represents manifest-type data for a project at a particular version. That means dependency constraints, both for normal dependencies and for tests. The constraints expressed in a manifest determine the set of versions that are acceptable to try for a given project.
Expressing a constraint in a manifest does not guarantee that a particular dependency will be present. It only guarantees that if packages in the project specified by the dependency are discovered through static analysis of the (transitive) import graph, then they will conform to the constraint.
This does entail that manifests can express constraints on projects they do not themselves import. This is by design, but its implications are complex. See the gps docs for more information: https://github.com/sdboyer/gps/wiki
type Package ¶ added in v0.4.0
type Package struct { Name string // Package name, as declared in the package statement ImportPath string // Full import path, including the prefix provided to ListPackages() CommentPath string // Import path given in the comment on the package statement Imports []string // Imports from all go and cgo files TestImports []string // Imports from all go test files (in go/build parlance: both TestImports and XTestImports) }
Package represents a Go package. It contains a subset of the information go/build.Package does.
type PackageOrErr ¶ added in v0.4.0
PackageOrErr stores the results of attempting to parse a single directory for Go source code.
type PackageTree ¶ added in v0.4.0
type PackageTree struct { ImportRoot string Packages map[string]PackageOrErr }
A PackageTree represents the results of recursively parsing a tree of packages, starting at the ImportRoot. The results of parsing the files in the directory identified by each import path - a Package or an error - are stored in the Packages map, keyed by that import path.
func ListPackages ¶ added in v0.11.0
func ListPackages(fileRoot, importRoot string) (PackageTree, error)
ListPackages reports Go package information about all directories in the tree at or below the provided fileRoot.
Directories without any valid Go files are excluded. Directories with multiple packages are excluded.
The importRoot parameter is prepended to the relative path when determining the import path for each package. The obvious case is for something typical, like:
fileRoot = "/home/user/go/src/github.com/foo/bar" importRoot = "github.com/foo/bar"
where the fileRoot and importRoot align. However, if you provide:
fileRoot = "/home/user/workspace/path/to/repo" importRoot = "github.com/foo/bar"
then the root package at path/to/repo will be ascribed import path "github.com/foo/bar", and the package at "/home/user/workspace/path/to/repo/baz" will be "github.com/foo/bar/baz".
A PackageTree is returned, which contains the ImportRoot and map of import path to PackageOrErr - each path under the root that exists will have either a Package, or an error describing why the directory is not a valid package.
func (PackageTree) ExternalReach ¶ added in v0.4.0
func (t PackageTree) ExternalReach(main, tests bool, ignore map[string]bool) ReachMap
ExternalReach looks through a PackageTree and computes the list of external import statements (that is, import statements pointing to packages that are not logical children of PackageTree.ImportRoot) that are transitively imported by the internal packages in the tree.
main indicates whether (true) or not (false) to include main packages in the analysis. When utilized by gps' solver, main packages are generally excluded from analyzing anything other than the root project, as they necessarily can't be imported.
tests indicates whether (true) or not (false) to include imports from test files in packages when computing the reach map.
ignore is a map of import paths that, if encountered, should be excluded from analysis. This exclusion applies to both internal and external packages. If an external import path is ignored, it is simply omitted from the results.
If an internal path is ignored, then not only does it not appear in the final map, but it is also excluded from the transitive calculations of other internal packages. That is, if you ignore A/foo, then the external package list for all internal packages that import A/foo will not include external packages that are only reachable through A/foo.
Visually, this means that, given a PackageTree with root A and packages at A, A/foo, and A/bar, and the following import chain:
A -> A/foo -> A/bar -> B/baz
In this configuration, all of A's packages transitively import B/baz, so the returned map would be:
map[string][]string{ "A": []string{"B/baz"}, "A/foo": []string{"B/baz"} "A/bar": []string{"B/baz"}, }
However, if you ignore A/foo, then A's path to B/baz is broken, and A/foo is omitted entirely. Thus, the returned map would be:
map[string][]string{ "A": []string{}, "A/bar": []string{"B/baz"}, }
If there are no packages to ignore, it is safe to pass a nil map.
type PairedVersion ¶ added in v0.1.0
type PairedVersion interface { Version // Underlying returns the immutable Revision that identifies this Version. Underlying() Revision // Unpair returns the surface-level UnpairedVersion that half of the pair. // // It does NOT modify the original PairedVersion Unpair() UnpairedVersion // contains filtered or unexported methods }
PairedVersion represents a normal Version, but paired with its corresponding, underlying Revision.
type ProjectAnalyzer ¶ added in v0.1.0
type ProjectAnalyzer interface { // Perform analysis of the filesystem tree rooted at path, with the // root import path importRoot, to determine the project's constraints, as // indicated by a Manifest and Lock. DeriveManifestAndLock(path string, importRoot ProjectRoot) (Manifest, Lock, error) // Report the name and version of this ProjectAnalyzer. Info() (name string, version *semver.Version) }
A ProjectAnalyzer is responsible for analyzing a given path for Manifest and Lock information. Tools relying on gps must implement one.
type ProjectConstraint ¶ added in v0.8.0
type ProjectConstraint struct { Ident ProjectIdentifier Constraint Constraint }
A ProjectConstraint combines a ProjectIdentifier with a Constraint. It indicates that, if packages contained in the ProjectIdentifier enter the depgraph, they must do so at a version that is allowed by the Constraint.
type ProjectConstraints ¶ added in v0.9.0
type ProjectConstraints map[ProjectRoot]ProjectProperties
ProjectConstraints is a map of projects, as identified by their import path roots (ProjectRoots) to the corresponding ProjectProperties.
They are the standard form in which Manifests declare their required dependency properties - constraints and network locations - as well as the form in which RootManifests declare their overrides.
type ProjectIdentifier ¶
type ProjectIdentifier struct { ProjectRoot ProjectRoot NetworkName string }
A ProjectIdentifier provides the name and source location of a dependency. It is related to, but differs in two keys ways from, an plain import path.
First, ProjectIdentifiers do not identify a single package. Rather, they encompasses the whole tree of packages, including tree's root - the ProjectRoot. In gps' current design, this ProjectRoot almost always corresponds to the root of a repository.
Second, ProjectIdentifiers can optionally carry a NetworkName, which identifies where the underlying source code can be located on the network. These can be either a full URL, including protocol, or plain import paths. So, these are all valid data for NetworkName:
github.com/sdboyer/gps github.com/fork/gps git@github.com:sdboyer/gps https://github.com/sdboyer/gps
With plain import paths, network addresses are derived purely through an algorithm. By having an explicit network name, it becomes possible to, for example, transparently substitute a fork for the original upstream source repository.
Note that gps makes no guarantees about the actual import paths contained in a repository aligning with ImportRoot. If tools, or their users, specify an alternate NetworkName that contains a repository with incompatible internal import paths, gps' solving operations will error. (gps does no import rewriting.)
Also note that if different projects' manifests report a different NetworkName for a given ImportRoot, it is a solve failure. Everyone has to agree on where a given import path should be sourced from.
If NetworkName is not explicitly set, gps will derive the network address from the ImportRoot using a similar algorithm to that utilized by `go get`.
type ProjectProperties ¶ added in v0.9.0
type ProjectProperties struct { NetworkName string Constraint Constraint }
ProjectProperties comprise the properties that can be attached to a ProjectRoot.
In general, these are declared in the context of a map of ProjectRoot to its ProjectProperties; they make little sense without their corresponding ProjectRoot.
type ProjectRoot ¶ added in v0.8.0
type ProjectRoot string
ProjectRoot is the topmost import path in a tree of other import paths - the root of the tree. In gps' current design, ProjectRoots have to correspond to a repository root (mostly), but their real purpose is to identify the root import path of a "project", logically encompassing all child packages.
Projects are a crucial unit of operation in gps. Constraints are declared by a project's manifest, and apply to all packages in a ProjectRoot's tree. Solving itself mostly proceeds on a project-by-project basis.
Aliasing string types is usually a bit of an anti-pattern. gps does it here as a means of clarifying API intent. This is important because Go's package management domain has lots of different path-ish strings floating around:
actual directories: /home/sdboyer/go/src/github.com/sdboyer/gps/example URLs: https://github.com/sdboyer/gps import paths: github.com/sdboyer/gps/example portions of import paths that refer to a package: example portions that could not possibly refer to anything sane: github.com/sdboyer portions that correspond to a repository root: github.com/sdboyer/gps
While not a panacea, having ProjectRoot allows gps to clearly indicate via the type system when a path-ish string must have particular semantics.
type ReachMap ¶ added in v0.11.0
ReachMap maps a set of import paths (keys) to the set of external packages transitively reachable from the packages at those import paths.
See PackageTree.ExternalReach() for more information.
func (ReachMap) ListExternalImports ¶ added in v0.11.0
ListExternalImports computes a sorted, deduplicated list of all the external packages that are reachable through imports from all valid packages in a ReachMap, as computed by PackageTree.ExternalReach().
main and tests determine whether main packages and test imports should be included in the calculation. "External" is defined as anything not prefixed, after path cleaning, by the PackageTree.ImportRoot. This includes stdlib.
If an internal path is ignored, all of the external packages that it uniquely imports are omitted. Note, however, that no internal transitivity checks are made here - every non-ignored package in the tree is considered independently (with one set of exceptions, noted below). That means, given a PackageTree with root A and packages at A, A/foo, and A/bar, and the following import chain:
A -> A/foo -> A/bar -> B/baz
If you ignore A or A/foo, A/bar will still be visited, and B/baz will be returned, because this method visits ALL packages in the tree, not only those reachable from the root (or any other) packages. If your use case requires interrogating external imports with respect to only specific package entry points, you need ExternalReach() instead.
It is safe to pass a nil map if there are no packages to ignore.
If an internal package has an error (that is, PackageOrErr is Err), it is excluded from consideration. Internal packages that transitively import the error package are also excluded. So, if:
-> B/foo / A \ -> A/bar -> B/baz
And A/bar has some error in it, then both A and A/bar will be eliminated from consideration; neither B/foo nor B/baz will be in the results. If A/bar, with its errors, is ignored, however, then A will remain, and B/foo will be in the results.
Finally, note that if a directory is named "testdata", or has a leading dot or underscore, it will not be directly analyzed as a source. This is in keeping with Go tooling conventions that such directories should be ignored. So, if:
A -> B/foo A/.bar -> B/baz A/_qux -> B/baz A/testdata -> B/baz
Then B/foo will be returned, but B/baz will not, because all three of the packages that import it are in directories with disallowed names.
HOWEVER, in keeping with the Go compiler, if one of those packages in a disallowed directory is imported by a package in an allowed directory, then it *will* be used. That is, while tools like go list will ignore a directory named .foo, you can still import from .foo. Thus, it must be included. So, if:
-> B/foo / A \ -> A/.bar -> B/baz
A is legal, and it imports A/.bar, so the results will include B/baz.
type Revision ¶ added in v0.1.0
type Revision string
A Revision represents an immutable versioning identifier.
func (Revision) Intersect ¶ added in v0.1.0
func (r Revision) Intersect(c Constraint) Constraint
Intersect computes the intersection of the Constraint with the provided Constraint. For Revisions, this can only be another, exactly equal Revision, or a PairedVersion whose underlying Revision is exactly equal.
func (Revision) Matches ¶ added in v0.1.0
Matches is the Revision acting as a constraint; it checks to see if the provided version is the same Revision as itself.
func (Revision) MatchesAny ¶ added in v0.1.0
func (r Revision) MatchesAny(c Constraint) bool
MatchesAny is the Revision acting as a constraint; it checks to see if the provided version is the same Revision as itself.
func (Revision) Type ¶ added in v0.2.0
func (r Revision) Type() VersionType
Type indicates the type of version - for revisions, "revision".
type RootManifest ¶ added in v0.9.0
type RootManifest interface { Manifest // Overrides returns a list of ProjectConstraints that will unconditionally // supercede any ProjectConstraint declarations made in either the root // manifest, or in any dependency's manifest. // // Overrides are a special control afforded only to root manifests. Tool // users should be encouraged to use them only as a last resort; they do not // "play well with others" (that is their express goal), and overreliance on // them can harm the ecosystem as a whole. Overrides() ProjectConstraints // IngoredPackages returns a set of import paths to ignore. These import // paths can be within the root project, or part of other projects. Ignoring // a package means that both it and its (unique) imports will be disregarded // by all relevant solver operations. // // It is an error to include a package in both the ignored and required // sets. IgnoredPackages() map[string]bool // RequiredPackages returns a set of import paths to require. These packages // are required to be present in any solution. The list can include main // packages. // // It is meaningless to specify packages that are within the // PackageTree of the ProjectRoot (though not an error, because the // RootManifest itself does not report a ProjectRoot). // // It is an error to include a package in both the ignored and required // sets. RequiredPackages() map[string]bool }
RootManifest extends Manifest to add special controls over solving that are only afforded to the root project.
type SimpleLock ¶ added in v0.2.0
type SimpleLock []LockedProject
SimpleLock is a helper for tools to easily describe lock data when they know that no hash, or other complex information, is available.
func (SimpleLock) InputHash ¶ added in v0.2.0
func (SimpleLock) InputHash() []byte
InputHash always returns an empty string for SimpleLock. This makes it useless as a stable lock to be written to disk, but still useful for some ephemeral purposes.
func (SimpleLock) Projects ¶ added in v0.2.0
func (l SimpleLock) Projects() []LockedProject
Projects returns the entire contents of the SimpleLock.
type SimpleManifest ¶ added in v0.2.0
type SimpleManifest struct {
Deps, TestDeps ProjectConstraints
}
SimpleManifest is a helper for tools to enumerate manifest data. It's generally intended for ephemeral manifests, such as those Analyzers create on the fly for projects with no manifest metadata, or metadata through a foreign tool's idioms.
func (SimpleManifest) DependencyConstraints ¶ added in v0.6.0
func (m SimpleManifest) DependencyConstraints() ProjectConstraints
DependencyConstraints returns the project's dependencies.
func (SimpleManifest) TestDependencyConstraints ¶ added in v0.6.0
func (m SimpleManifest) TestDependencyConstraints() ProjectConstraints
TestDependencyConstraints returns the project's test dependencies.
type Solution ¶ added in v0.7.0
A Solution is returned by a solver run. It is mostly just a Lock, with some additional methods that report information about the solve run.
type SolveParameters ¶ added in v0.8.0
type SolveParameters struct { // The path to the root of the project on which the solver should operate. // This should point to the directory that should contain the vendor/ // directory. // // In general, it is wise for this to be under an active GOPATH, though it // is not (currently) required. // // A real path to a readable directory is required. RootDir string // The tree of packages that comprise the root project, as well as the // import path that should identify the root of that tree. // // In most situations, tools should simply pass the result of ListPackages() // directly through here. // // The ImportRoot property must be a non-empty string, and at least one // element must be present in the Packages map. RootPackageTree PackageTree // The root manifest. This contains all the dependency constraints // associated with normal Manifests, as well as the particular controls // afforded only to the root project. // // May be nil, but for most cases, that would be unwise. Manifest RootManifest // The root lock. Optional. Generally, this lock is the output of a previous // solve run. // // If provided, the solver will attempt to preserve the versions specified // in the lock, unless ToChange or ChangeAll settings indicate otherwise. Lock Lock // ToChange is a list of project names that should be changed - that is, any // versions specified for those projects in the root lock file should be // ignored. // // Passing ChangeAll has subtly different behavior from enumerating all // projects into ToChange. In general, ToChange should *only* be used if the // user expressly requested an upgrade for a specific project. ToChange []ProjectRoot // ChangeAll indicates that all projects should be changed - that is, any // versions specified in the root lock file should be ignored. ChangeAll bool // Downgrade indicates whether the solver will attempt to upgrade (false) or // downgrade (true) projects that are not locked, or are marked for change. // // Upgrading is, by far, the most typical case. The field is named // 'Downgrade' so that the bool's zero value corresponds to that most // typical case. Downgrade bool // Trace controls whether the solver will generate informative trace output // as it moves through the solving process. Trace bool // TraceLogger is the logger to use for generating trace output. If Trace is // true but no logger is provided, solving will result in an error. TraceLogger *log.Logger }
SolveParameters hold all arguments to a solver run.
Only RootDir and ImportRoot are absolutely required. A nil Manifest is allowed, though it usually makes little sense.
Of these properties, only Manifest and Ignore are (directly) incorporated in memoization hashing.
type Solver ¶
type Solver interface { // HashInputs produces a hash digest representing the unique inputs to this // solver. It is guaranteed that, if the hash digest is equal to the digest // from a previous Solution.InputHash(), that that Solution is valid for // this Solver's inputs. // // In such a case, it may not be necessary to run Solve() at all. HashInputs() []byte // Solve initiates a solving run. It will either complete successfully with // a Solution, or fail with an informative error. Solve() (Solution, error) }
A Solver is the main workhorse of gps: given a set of project inputs, it performs a constraint solving analysis to develop a complete Solution, or else fail with an informative error.
If a Solution is found, an implementing tool may persist it - typically into a "lock file" - and/or use it to write out a directory tree of dependencies, suitable to be a vendor directory, via CreateVendorTree.
func Prepare ¶ added in v0.5.0
func Prepare(params SolveParameters, sm SourceManager) (Solver, error)
Prepare readies a Solver for use.
This function reads and validates the provided SolveParameters. If a problem with the inputs is detected, an error is returned. Otherwise, a Solver is returned, ready to hash and check inputs or perform a solving run.
type SourceManager ¶
type SourceManager interface { // SourceExists checks if a repository exists, either upstream or in the // SourceManager's central repository cache. SourceExists(ProjectIdentifier) (bool, error) // SyncSourceFor will attempt to bring all local information about a source // fully up to date. SyncSourceFor(ProjectIdentifier) error // ListVersions retrieves a list of the available versions for a given // repository name. ListVersions(ProjectIdentifier) ([]Version, error) // RevisionPresentIn indicates whether the provided Version is present in // the given repository. RevisionPresentIn(ProjectIdentifier, Revision) (bool, error) // ListPackages parses the tree of the Go packages at or below root of the // provided ProjectIdentifier, at the provided version. ListPackages(ProjectIdentifier, Version) (PackageTree, error) // GetManifestAndLock returns manifest and lock information for the provided // root import path. // // gps currently requires that projects be rooted at their repository root, // necessitating that the ProjectIdentifier's ProjectRoot must also be a // repository root. GetManifestAndLock(ProjectIdentifier, Version) (Manifest, Lock, error) // ExportProject writes out the tree of the provided import path, at the // provided version, to the provided directory. ExportProject(ProjectIdentifier, Version, string) error // AnalyzerInfo reports the name and version of the logic used to service // GetManifestAndLock(). AnalyzerInfo() (name string, version *semver.Version) // DeduceRootProject takes an import path and deduces the corresponding // project/source root. DeduceProjectRoot(ip string) (ProjectRoot, error) }
A SourceManager is responsible for retrieving, managing, and interrogating source repositories. Its primary purpose is to serve the needs of a Solver, but it is handy for other purposes, as well.
gps's built-in SourceManager, SourceMgr, is intended to be generic and sufficient for any purpose. It provides some additional semantics around the methods defined here.
type SourceMgr ¶ added in v0.8.0
type SourceMgr struct {
// contains filtered or unexported fields
}
SourceMgr is the default SourceManager for gps.
There's no (planned) reason why it would need to be reimplemented by other tools; control via dependency injection is intended to be sufficient.
func NewSourceManager ¶ added in v0.1.0
func NewSourceManager(an ProjectAnalyzer, cachedir string) (*SourceMgr, error)
NewSourceManager produces an instance of gps's built-in SourceManager. It takes a cache directory (where local instances of upstream repositories are stored), and a ProjectAnalyzer that is used to extract manifest and lock information from source trees.
The returned SourceManager aggressively caches information wherever possible. If tools need to do preliminary work involving upstream repository analysis prior to invoking a solve run, it is recommended that they create this SourceManager as early as possible and use it to their ends. That way, the solver can benefit from any caches that may have already been warmed.
gps's SourceManager is intended to be threadsafe (if it's not, please file a bug!). It should be safe to reuse across concurrent solving runs, even on unrelated projects.
func (*SourceMgr) AnalyzerInfo ¶ added in v0.9.0
AnalyzerInfo reports the name and version of the injected ProjectAnalyzer.
func (*SourceMgr) DeduceProjectRoot ¶ added in v0.10.0
func (sm *SourceMgr) DeduceProjectRoot(ip string) (ProjectRoot, error)
DeduceProjectRoot takes an import path and deduces the corresponding project/source root.
Note that some import paths may require network activity to correctly determine the root of the path, such as, but not limited to, vanity import paths. (A special exception is written for gopkg.in to minimize network activity, as its behavior is well-structured)
func (*SourceMgr) ExportProject ¶ added in v0.8.0
func (sm *SourceMgr) ExportProject(id ProjectIdentifier, v Version, to string) error
ExportProject writes out the tree of the provided ProjectIdentifier's ProjectRoot, at the provided version, to the provided directory.
func (*SourceMgr) GetManifestAndLock ¶ added in v0.9.0
GetManifestAndLock returns manifest and lock information for the provided import path. gps currently requires that projects be rooted at their repository root, necessitating that the ProjectIdentifier's ProjectRoot must also be a repository root.
The work of producing the manifest and lock is delegated to the injected ProjectAnalyzer's DeriveManifestAndLock() method.
func (*SourceMgr) ListPackages ¶ added in v0.8.0
func (sm *SourceMgr) ListPackages(id ProjectIdentifier, v Version) (PackageTree, error)
ListPackages parses the tree of the Go packages at and below the ProjectRoot of the given ProjectIdentifier, at the given version.
func (*SourceMgr) ListVersions ¶ added in v0.8.0
func (sm *SourceMgr) ListVersions(id ProjectIdentifier) ([]Version, error)
ListVersions retrieves a list of the available versions for a given repository name.
The list is not sorted; while it may be returned in the order that the underlying VCS reports version information, no guarantee is made. It is expected that the caller either not care about order, or sort the result themselves.
This list is always retrieved from upstream on the first call. Subsequent calls will return a cached version of the first call's results. if upstream is not accessible (network outage, access issues, or the resource actually went away), an error will be returned.
func (*SourceMgr) Release ¶ added in v0.8.0
func (sm *SourceMgr) Release()
Release lets go of any locks held by the SourceManager.
func (*SourceMgr) RevisionPresentIn ¶ added in v0.8.0
func (sm *SourceMgr) RevisionPresentIn(id ProjectIdentifier, r Revision) (bool, error)
RevisionPresentIn indicates whether the provided Revision is present in the given repository.
func (*SourceMgr) SourceExists ¶ added in v0.10.0
func (sm *SourceMgr) SourceExists(id ProjectIdentifier) (bool, error)
SourceExists checks if a repository exists, either upstream or in the cache, for the provided ProjectIdentifier.
func (*SourceMgr) SyncSourceFor ¶ added in v0.10.0
func (sm *SourceMgr) SyncSourceFor(id ProjectIdentifier) error
SyncSourceFor will ensure that all local caches and information about a source are up to date with any network-acccesible information.
The primary use case for this is prefetching.
type UnpairedVersion ¶ added in v0.1.0
type UnpairedVersion interface { Version // Is takes the underlying Revision that this UnpairedVersion corresponds // to and unites them into a PairedVersion. Is(Revision) PairedVersion // contains filtered or unexported methods }
UnpairedVersion represents a normal Version, with a method for creating a VersionPair by indicating the version's corresponding, underlying Revision.
func NewBranch ¶ added in v0.2.0
func NewBranch(body string) UnpairedVersion
NewBranch creates a new Version to represent a floating version (in general, a branch).
func NewVersion ¶ added in v0.1.0
func NewVersion(body string) UnpairedVersion
NewVersion creates a Semver-typed Version if the provided version string is valid semver, and a plain/non-semver version if not.
type Version ¶
type Version interface { Constraint // Indicates the type of version - Revision, Branch, Version, or Semver Type() VersionType }
Version represents one of the different types of versions used by gps.
Version composes Constraint, because all versions can be used as a constraint (where they allow one, and only one, version - themselves), but constraints are not necessarily discrete versions.
Version is an interface, but it contains private methods, which restricts it to gps's own internal implementations. We do this for the confluence of two reasons: the implementation of Versions is complete (there is no case in which we'd need other types), and the implementation relies on type magic under the hood, which would be unsafe to do if other dynamic types could be hiding behind the interface.
type VersionType ¶
type VersionType uint8
VersionType indicates a type for a Version that conveys some additional semantics beyond that which is literally embedded on the Go type.
const ( IsRevision VersionType = iota IsVersion IsSemver IsBranch )
VersionTypes for the four major classes of version we deal with
Source Files ¶
- analysis.go
- bridge.go
- constraints.go
- deduce.go
- discovery.go
- flags.go
- hash.go
- import_mode_go16.go
- lock.go
- manifest.go
- maybe_source.go
- metrics.go
- remove_go17.go
- result.go
- satisfy.go
- selection.go
- solve_failures.go
- solver.go
- source.go
- source_errors.go
- source_manager.go
- trace.go
- typed_radix.go
- types.go
- vcs_source.go
- version.go
- version_queue.go