type Requirements … type cachedGraph … var requirements … func mustHaveGoRoot(roots []module.Version) { … } // newRequirements returns a new requirement set with the given root modules. // The dependencies of the roots will be loaded lazily at the first call to the // Graph method. // // The rootModules slice must be sorted according to gover.ModSort. // The caller must not modify the rootModules slice or direct map after passing // them to newRequirements. // // If vendoring is in effect, the caller must invoke initVendor on the returned // *Requirements before any other method. func newRequirements(pruning modPruning, rootModules []module.Version, direct map[string]bool) *Requirements { … } // String returns a string describing the Requirements for debugging. func (rs *Requirements) String() string { … } // initVendor initializes rs.graph from the given list of vendored module // dependencies, overriding the graph that would normally be loaded from module // requirements. func (rs *Requirements) initVendor(vendorList []module.Version) { … } // GoVersion returns the Go language version for the Requirements. func (rs *Requirements) GoVersion() string { … } // rootSelected returns the version of the root dependency with the given module // path, or the zero module.Version and ok=false if the module is not a root // dependency. func (rs *Requirements) rootSelected(path string) (version string, ok bool) { … } // hasRedundantRoot returns true if the root list contains multiple requirements // of the same module or a requirement on any version of the main module. // Redundant requirements should be pruned, but they may influence version // selection. func (rs *Requirements) hasRedundantRoot() bool { … } // Graph returns the graph of module requirements loaded from the current // root modules (as reported by RootModules). // // Graph always makes a best effort to load the requirement graph despite any // errors, and always returns a non-nil *ModuleGraph. // // If the requirements of any relevant module fail to load, Graph also // returns a non-nil error of type *mvs.BuildListError. func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) { … } // IsDirect returns whether the given module provides a package directly // imported by a package or test in the main module. func (rs *Requirements) IsDirect(path string) bool { … } type ModuleGraph … var readModGraphDebugOnce … // readModGraph reads and returns the module dependency graph starting at the // given roots. // // The requirements of the module versions found in the unprune map are included // in the graph even if they would normally be pruned out. // // Unlike LoadModGraph, readModGraph does not attempt to diagnose or update // inconsistent roots. func readModGraph(ctx context.Context, pruning modPruning, roots []module.Version, unprune map[module.Version]bool) (*ModuleGraph, error) { … } // RequiredBy returns the dependencies required by module m in the graph, // or ok=false if module m's dependencies are pruned out. // // The caller must not modify the returned slice, but may safely append to it // and may rely on it not to be modified. func (mg *ModuleGraph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) { … } // Selected returns the selected version of the module with the given path. // // If no version is selected, Selected returns version "none". func (mg *ModuleGraph) Selected(path string) (version string) { … } // WalkBreadthFirst invokes f once, in breadth-first order, for each module // version other than "none" that appears in the graph, regardless of whether // that version is selected. func (mg *ModuleGraph) WalkBreadthFirst(f func(m module.Version)) { … } // BuildList returns the selected versions of all modules present in the graph, // beginning with the main modules. // // The order of the remaining elements in the list is deterministic // but arbitrary. // // The caller must not modify the returned list, but may safely append to it // and may rely on it not to be modified. func (mg *ModuleGraph) BuildList() []module.Version { … } func (mg *ModuleGraph) findError() error { … } func (mg *ModuleGraph) allRootsSelected() bool { … } // LoadModGraph loads and returns the graph of module dependencies of the main module, // without loading any packages. // // If the goVersion string is non-empty, the returned graph is the graph // as interpreted by the given Go version (instead of the version indicated // in the go.mod file). // // Modules are loaded automatically (and lazily) in LoadPackages: // LoadModGraph need only be called if LoadPackages is not, // typically in commands that care about modules but no particular package. func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) { … } // expandGraph loads the complete module graph from rs. // // If the complete graph reveals that some root of rs is not actually the // selected version of its path, expandGraph computes a new set of roots that // are consistent. (With a pruned module graph, this may result in upgrades to // other modules due to requirements that were previously pruned out.) // // expandGraph returns the updated roots, along with the module graph loaded // from those roots and any error encountered while loading that graph. // expandGraph returns non-nil requirements and a non-nil graph regardless of // errors. On error, the roots might not be updated to be consistent. func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleGraph, error) { … } // EditBuildList edits the global build list by first adding every module in add // to the existing build list, then adjusting versions (and adding or removing // requirements as needed) until every module in mustSelect is selected at the // given version. // // (Note that the newly-added modules might not be selected in the resulting // build list: they could be lower than existing requirements or conflict with // versions in mustSelect.) // // If the versions listed in mustSelect are mutually incompatible (due to one of // the listed modules requiring a higher version of another), EditBuildList // returns a *ConstraintError and leaves the build list in its previous state. // // On success, EditBuildList reports whether the selected version of any module // in the build list may have been changed (possibly to or from "none") as a // result. func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) { … } // OverrideRoots edits the global requirement roots by replacing the specific module versions. func OverrideRoots(ctx context.Context, replace []module.Version) { … } func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Version) *Requirements { … } type ConstraintError … func (e *ConstraintError) Error() string { … } type Conflict … // UnwrapModuleError returns c.Err, but unwraps it if it is a module.ModuleError // with a version and path matching the last entry in the Path slice. func (c Conflict) UnwrapModuleError() error { … } // Summary returns a string that describes only the first and last modules in // the conflict path. func (c Conflict) Summary() string { … } // String returns a string that describes the full conflict path. func (c Conflict) String() string { … } // tidyRoots trims the root dependencies to the minimal requirements needed to // both retain the same versions of all packages in pkgs and satisfy the // graph-pruning invariants (if applicable). func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Requirements, error) { … } func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { … } func updateWorkspaceRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { … } // tidyPrunedRoots returns a minimal set of root requirements that maintains the // invariants of the go.mod file needed to support graph pruning for the given // packages: // // 1. For each package marked with pkgInAll, the module path that provided that // package is included as a root. // 2. For all packages, the module that provided that package either remains // selected at the same version or is upgraded by the dependencies of a // root. // // If any module that provided a package has been upgraded above its previous // version, the caller may need to reload and recompute the package graph. // // To ensure that the loading process eventually converges, the caller should // add any needed roots from the tidy root set (without removing existing untidy // roots) until the set of roots has converged. func tidyPrunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { … } // updatePrunedRoots returns a set of root requirements that maintains the // invariants of the go.mod file needed to support graph pruning: // // 1. The selected version of the module providing each package marked with // either pkgInAll or pkgIsRoot is included as a root. // Note that certain root patterns (such as '...') may explode the root set // to contain every module that provides any package imported (or merely // required) by any other module. // 2. Each root appears only once, at the selected version of its path // (if rs.graph is non-nil) or at the highest version otherwise present as a // root (otherwise). // 3. Every module path that appears as a root in rs remains a root. // 4. Every version in add is selected at its given version unless upgraded by // (the dependencies of) an existing root or another module in add. // // The packages in pkgs are assumed to have been loaded from either the roots of // rs or the modules selected in the graph of rs. // // The above invariants together imply the graph-pruning invariants for the // go.mod file: // // 1. (The import invariant.) Every module that provides a package transitively // imported by any package or test in the main module is included as a root. // This follows by induction from (1) and (3) above. Transitively-imported // packages loaded during this invocation are marked with pkgInAll (1), // and by hypothesis any transitively-imported packages loaded in previous // invocations were already roots in rs (3). // // 2. (The argument invariant.) Every module that provides a package matching // an explicit package pattern is included as a root. This follows directly // from (1): packages matching explicit package patterns are marked with // pkgIsRoot. // // 3. (The completeness invariant.) Every module that contributed any package // to the build is required by either the main module or one of the modules // it requires explicitly. This invariant is left up to the caller, who must // not load packages from outside the module graph but may add roots to the // graph, but is facilitated by (3). If the caller adds roots to the graph in // order to resolve missing packages, then updatePrunedRoots will retain them, // the selected versions of those roots cannot regress, and they will // eventually be written back to the main module's go.mod file. // // (See https://golang.org/design/36460-lazy-module-loading#invariants for more // detail.) func updatePrunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) { … } // spotCheckRoots reports whether the versions of the roots in rs satisfy the // explicit requirements of the modules in mods. func spotCheckRoots(ctx context.Context, rs *Requirements, mods map[module.Version]bool) bool { … } // tidyUnprunedRoots returns a minimal set of root requirements that maintains // the selected version of every module that provided or lexically could have // provided a package in pkgs, and includes the selected version of every such // module in direct as a root. func tidyUnprunedRoots(ctx context.Context, mainModule module.Version, old *Requirements, pkgs []*loadPkg) (*Requirements, error) { … } // updateUnprunedRoots returns a set of root requirements that includes the selected // version of every module path in direct as a root, and maintains the selected // version of every module selected in the graph of rs. // // The roots are updated such that: // // 1. The selected version of every module path in direct is included as a root // (if it is not "none"). // 2. Each root is the selected version of its path. (We say that such a root // set is “consistent”.) // 3. Every version selected in the graph of rs remains selected unless upgraded // by a dependency in add. // 4. Every version in add is selected at its given version unless upgraded by // (the dependencies of) an existing root or another module in add. func updateUnprunedRoots(ctx context.Context, direct map[string]bool, rs *Requirements, add []module.Version) (*Requirements, error) { … } // convertPruning returns a version of rs with the given pruning behavior. // If rs already has the given pruning, convertPruning returns rs unmodified. func convertPruning(ctx context.Context, rs *Requirements, pruning modPruning) (*Requirements, error) { … }