modget

Imports

Imports #

"fmt"
"path/filepath"
"regexp"
"strings"
"sync"
"cmd/go/internal/base"
"cmd/go/internal/gover"
"cmd/go/internal/modload"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/internal/pkgpattern"
"golang.org/x/mod/module"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
"cmd/go/internal/gover"
"cmd/go/internal/imports"
"cmd/go/internal/modfetch"
"cmd/go/internal/modload"
"cmd/go/internal/search"
"cmd/go/internal/toolchain"
"cmd/go/internal/work"
"cmd/internal/par"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"

Constants & Variables

CmdGet var #

var CmdGet = *ast.UnaryExpr

HelpVCS var #

var HelpVCS = *ast.UnaryExpr

errVersionChange var #

errVersionChange is a sentinel error indicating that a module's version needs to be updated before its dependencies can be loaded.

var errVersionChange = *ast.CallExpr

getD var #

var getD dFlag

getF var #

var getF = *ast.CallExpr

getFix var #

var getFix = *ast.CallExpr

getInsecure var #

var getInsecure = *ast.CallExpr

getM var #

var getM = *ast.CallExpr

getT var #

var getT = *ast.CallExpr

getTool var #

var getTool = *ast.CallExpr

getU var #

var getU upgradeFlag

Structs

conflictError struct #

type conflictError struct {
mPath string
proposed versionReason
conflict versionReason
}

dFlag struct #

dFlag is a custom flag.Value for the deprecated -d flag which will be used to provide warnings or errors if -d is provided.

type dFlag struct {
value bool
set bool
}

matchInModuleKey struct #

type matchInModuleKey struct {
pattern string
m module.Version
}

pathSet struct #

A pathSet describes the possible options for resolving a specific path to a package and/or module.

type pathSet struct {
path string
pkgMods []module.Version
mod module.Version
err error
}

query struct #

A query describes a command-line argument and the modules and/or packages to which that argument may resolve..

type query struct {
raw string
rawVersion string
pattern string
patternIsLocal bool
version string
matchWildcard func(path string) bool
canMatchWildcardInModule func(mPath string) bool
conflict *query
candidates []pathSet
candidatesMu sync.Mutex
pathSeen sync.Map
resolved []module.Version
matchesPackages bool
}

resolver struct #

type resolver struct {
localQueries []*query
pathQueries []*query
wildcardQueries []*query
patternAllQueries []*query
toolQueries []*query
nonesByPath map[string]*query
wildcardNones []*query
resolvedVersion map[string]versionReason
buildList []module.Version
buildListVersion map[string]string
initialVersion map[string]string
missing []pathSet
work *par.Queue
matchInModuleCache *ast.IndexListExpr
}

upgradeFlag struct #

upgradeFlag is a custom flag.Value for -u.

type upgradeFlag struct {
rawVersion string
version string
}

versionReason struct #

type versionReason struct {
version string
reason *query
}

Functions

Error method #

func (e *conflictError) Error() string

IsBoolFlag method #

func (*upgradeFlag) IsBoolFlag() bool

IsBoolFlag method #

func (v *dFlag) IsBoolFlag() bool

ResolvedString method #

ResolvedString returns a string describing m as a resolved match for q.

func (q *query) ResolvedString(m module.Version) string

Set method #

func (v *dFlag) Set(s string) error

Set method #

func (v *upgradeFlag) Set(s string) error

String method #

func (b *dFlag) String() string

String method #

String returns the original argument from which q was parsed.

func (q *query) String() string

String method #

func (v *upgradeFlag) String() string

applyUpgrades method #

applyUpgrades disambiguates candidate sets that are needed to upgrade (or provide) transitive dependencies imported by previously-resolved packages. applyUpgrades modifies the build list by adding one module version from each pathSet in upgrades, then downgrading (or further upgrading) those modules as needed to maintain any already-resolved versions of other modules. applyUpgrades does not mark the new versions as resolved, so they can still be further modified by other queries (such as wildcards). If all pathSets are resolved without any changes to the build list, applyUpgrades returns with changed=false.

func (r *resolver) applyUpgrades(ctx context.Context, upgrades []pathSet) (changed bool)

canMatchInModule method #

canMatchInModule reports whether the given module path can potentially contain q.pattern.

func (q *query) canMatchInModule(mPath string) bool

checkAllowedOr method #

checkAllowedOr is like modload.CheckAllowed, but it always allows the requested and current versions (even if they are retracted or otherwise excluded).

func (r *resolver) checkAllowedOr(requested string, selected func(string) string) modload.AllowedFunc

checkPackageProblems method #

checkPackageProblems reloads packages for the given patterns and reports missing and ambiguous package errors. It also reports retractions and deprecations for resolved modules and modules needed to build named packages. It also adds a sum for each updated module in the build list if we had one before and didn't get one while loading packages. We skip missing-package errors earlier in the process, since we want to resolve pathSets ourselves, but at that point, we don't have enough context to log the package-import chains leading to each error.

func (r *resolver) checkPackageProblems(ctx context.Context, pkgPatterns []string)

checkWildcardVersions method #

checkWildcardVersions reports an error if any module in the build list has a path (or contains a package) matching a query with a wildcard pattern, but has a selected version that does *not* match the query.

func (r *resolver) checkWildcardVersions(ctx context.Context)

chooseArbitrarily method #

chooseArbitrarily returns an arbitrary (but deterministic) module version from among those in the given set. chooseArbitrarily prefers module paths that were already in the build list at the start of 'go get', prefers modules that provide packages over those that do not, and chooses the first module meeting those criteria (so biases toward longer paths).

func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Version)

disambiguate method #

disambiguate eliminates candidates from cs that conflict with other module versions that have already been resolved. If there is only one (unique) remaining candidate, disambiguate returns that candidate, along with an indication of whether that result interprets cs.path as a package Note: we're only doing very simple disambiguation here. The goal is to reproduce the user's intent, not to find a solution that a human couldn't. In the vast majority of cases, we expect only one module per pathSet, but we want to give some minimal additional tools so that users can add an extra argument or two on the command line to resolve simple ambiguities.

func (r *resolver) disambiguate(cs pathSet) (filtered pathSet, isPackage bool, m module.Version, unique bool)

errSet function #

errSet returns a pathSet containing the given error.

func errSet(err error) pathSet

findAndUpgradeImports method #

findAndUpgradeImports returns a pathSet for each package that is not yet in the build list but is transitively imported by the packages matching the given queries (which must already have been resolved). If the getU flag ("-u") is set, findAndUpgradeImports also returns a pathSet for each module that is not constrained by any other command-line argument and has an available matching upgrade.

func (r *resolver) findAndUpgradeImports(ctx context.Context, queries []*query) (upgrades []pathSet)

findMissingWildcards method #

findMissingWildcards adds a candidate set for each query in r.wildcardQueries that has not yet resolved to any version containing packages.

func (r *resolver) findMissingWildcards(ctx context.Context)

init function #

func init()

initialSelected method #

initialSelected returns the version of the module with the given path that was selected at the start of this 'go get' invocation.

func (r *resolver) initialSelected(mPath string) (version string)

isNoSuchModuleVersion function #

isNoSuchModuleVersion reports whether err indicates that the requested module does not exist at the requested version, either because the module does not exist at all or because it does not include that specific version.

func isNoSuchModuleVersion(err error) bool

isNoSuchPackageVersion function #

isNoSuchPackageVersion reports whether err indicates that the requested package does not exist at the requested version, either because no module that could contain it exists at that version, or because every such module that does exist does not actually contain the package.

func isNoSuchPackageVersion(err error) bool

isWildcard method #

isWildcard reports whether q is a pattern that can match multiple paths.

func (q *query) isWildcard() bool

loadPackages method #

loadPackages loads the packages matching the given patterns, invoking the findPackage function for each package that may require a change to the build list. loadPackages invokes the findPackage function for each package loaded from a module outside the main module. If the module or version that supplies that package needs to be changed due to a query, findPackage may return false and the imports of that package will not be loaded. loadPackages also invokes the findPackage function for each imported package that is neither present in the standard library nor in any module in the build list.

func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) versionOk bool)

matchInModule method #

matchInModule is a caching wrapper around modload.MatchInModule.

func (r *resolver) matchInModule(ctx context.Context, pattern string, m module.Version) (packages []string, err error)

matchesPath method #

matchesPath reports whether the given path matches q.pattern.

func (q *query) matchesPath(path string) bool

newQuery function #

newQuery returns a new query parsed from the raw argument, which must be either path or path@version.

func newQuery(raw string) (*query, error)

newResolver function #

func newResolver(ctx context.Context, queries []*query) *resolver

noneForPath method #

noneForPath returns a "none" query matching the given module path, or found == false if no such query exists.

func (r *resolver) noneForPath(mPath string) (nq *query, found bool)

parseArgs function #

parseArgs parses command-line arguments and reports errors. The command-line arguments are of the form path@version or simply path, with implicit @upgrade. path@none is "downgrade away".

func parseArgs(ctx context.Context, rawArgs []string) (dropToolchain bool, queries []*query)

pathOnce method #

pathOnce invokes f to generate the pathSet for the given path, if one is still needed. Note that, unlike sync.Once, pathOnce does not guarantee that a concurrent call to f for the given path has completed on return. pathOnce is safe for concurrent use by multiple goroutines, but note that multiple concurrent calls will result in the sets being added in nondeterministic order.

func (q *query) pathOnce(path string, f func() pathSet)

performLocalQueries method #

func (r *resolver) performLocalQueries(ctx context.Context)

performPathQueries method #

performPathQueries populates the candidates for each query whose pattern is a path literal. The candidate packages and modules for path literals depend only on the initial build list, not the current build list, so we only need to query path literals once.

func (r *resolver) performPathQueries(ctx context.Context)

performPatternAllQueries method #

performPatternAllQueries populates the candidates for each query whose pattern is "all". The candidate modules for a given package in "all" depend only on the initial build list, but we cannot follow the dependencies of a given package until we know which candidate is selected — and that selection may depend on the results of other queries. We need to re-evaluate the "all" queries whenever the module for one or more packages in "all" are resolved.

func (r *resolver) performPatternAllQueries(ctx context.Context)

performToolQueries method #

performToolQueries populates the candidates for each query whose pattern is "tool".

func (r *resolver) performToolQueries(ctx context.Context)

performWildcardQueries method #

performWildcardQueries populates the candidates for each query whose pattern is a wildcard. The candidates for a given module path matching (or containing a package matching) a wildcard query depend only on the initial build list, but the set of modules may be expanded by other queries, so wildcard queries need to be re-evaluated whenever a potentially-matching module path is added to the build list.

func (r *resolver) performWildcardQueries(ctx context.Context)

queryModule method #

queryModule wraps modload.Query, substituting r.checkAllowedOr to decide allowed versions.

func (r *resolver) queryModule(ctx context.Context, mPath string, query string, selected func(string) string) (module.Version, error)

queryNone method #

queryNone adds a candidate set to q for each module matching q.pattern. Each candidate set has only one possible module version: the matched module at version "none". We interpret arguments to 'go get' as packages first, and fall back to modules second. However, no module exists at version "none", and therefore no package exists at that version either: we know that the argument cannot match any packages, and thus it must match modules instead.

func (r *resolver) queryNone(ctx context.Context, q *query)

queryPackages method #

queryPackages wraps modload.QueryPackage, substituting r.checkAllowedOr to decide allowed versions.

func (r *resolver) queryPackages(ctx context.Context, pattern string, query string, selected func(string) string) (pkgMods []module.Version, err error)

queryPath method #

queryPath adds a candidate set to q for the package with path q.pattern. The candidate set consists of all modules that could provide q.pattern and have a version matching q, plus (if it exists) the module whose path is itself q.pattern (at a matching version).

func (r *resolver) queryPath(ctx context.Context, q *query)

queryPattern method #

queryPattern wraps modload.QueryPattern, substituting r.checkAllowedOr to decide allowed versions.

func (r *resolver) queryPattern(ctx context.Context, pattern string, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error)

queryWildcard method #

queryWildcard adds a candidate set to q for each module for which: - some version of the module is already in the build list, and - that module exists at some version matching q.version, and - either the module path itself matches q.pattern, or some package within the module at q.version matches q.pattern.

func (r *resolver) queryWildcard(ctx context.Context, q *query)

reportChanges method #

reportChanges logs version changes to os.Stderr. reportChanges only logs changes to modules named on the command line and to explicitly required modules in go.mod. Most changes to indirect requirements are not relevant to the user and are not logged. reportChanges should be called after WriteGoMod.

func (r *resolver) reportChanges(oldReqs []module.Version, newReqs []module.Version)

reportConflict function #

func reportConflict(pq *query, m module.Version, conflict versionReason)

reportError function #

reportError logs err concisely using base.Errorf.

func reportError(q *query, err error)

reqsFromGoMod function #

func reqsFromGoMod(f *modfile.File) []module.Version

resolve method #

resolve records that module m must be at its indicated version (which may be "none") due to query q. If some other query forces module m to be at a different version, resolve reports a conflict error.

func (r *resolver) resolve(q *query, m module.Version)

resolveQueries method #

resolveQueries resolves candidate sets that are attached to the given queries and/or needed to provide the given missing-package dependencies. resolveQueries starts by resolving one module version from each unambiguous pathSet attached to the given queries. If no unambiguous query results in a change to the build list, resolveQueries revisits the ambiguous query candidates and resolves them arbitrarily in order to guarantee forward progress. If all pathSets are resolved without any changes to the build list, resolveQueries returns with changed=false.

func (r *resolver) resolveQueries(ctx context.Context, queries []*query) (changed bool)

runGet function #

func runGet(ctx context.Context, cmd *base.Command, args []string)

selected method #

selected returns the version of the module with the given path that is selected in the resolver's current build list.

func (r *resolver) selected(mPath string) (version string)

tryWildcard method #

tryWildcard returns a pathSet for module m matching query q. If m does not actually match q, tryWildcard returns an empty pathSet.

func (r *resolver) tryWildcard(ctx context.Context, q *query, m module.Version) pathSet

updateBuildList method #

updateBuildList updates the module loader's global build list to be consistent with r.resolvedVersion, and to include additional modules provided that they do not conflict with the resolved versions. If the additional modules conflict with the resolved versions, they will be downgraded to a non-conflicting version (possibly "none"). If the resulting build list is the same as the one resulting from the last call to updateBuildList, updateBuildList returns with changed=false.

func (r *resolver) updateBuildList(ctx context.Context, additions []module.Version) (changed bool)

updateTools function #

func updateTools(ctx context.Context, queries []*query, opts *modload.WriteOpts)

validate method #

validate reports a non-nil error if q is not sensible and well-formed.

func (q *query) validate() error

versionOkForMainModule function #

func versionOkForMainModule(version string) bool

Generated with Arrow