github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/go/internal/modload/buildlist.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package modload 6 7 import ( 8 "github.com/shogo82148/std/context" 9 "github.com/shogo82148/std/sync" 10 "github.com/shogo82148/std/sync/atomic" 11 12 "github.com/shogo82148/std/cmd/go/internal/mvs" 13 "github.com/shogo82148/std/cmd/go/internal/par" 14 15 "golang.org/x/mod/module" 16 ) 17 18 // A Requirements represents a logically-immutable set of root module requirements. 19 type Requirements struct { 20 // pruning is the pruning at which the requirement graph is computed. 21 // 22 // If unpruned, the graph includes all transitive requirements regardless 23 // of whether the requiring module supports pruning. 24 // 25 // If pruned, the graph includes only the root modules, the explicit 26 // requirements of those root modules, and the transitive requirements of only 27 // the root modules that do not support pruning. 28 // 29 // If workspace, the graph includes only the workspace modules, the explicit 30 // requirements of the workspace modules, and the transitive requirements of 31 // the workspace modules that do not support pruning. 32 pruning modPruning 33 34 // rootModules is the set of root modules of the graph, sorted and capped to 35 // length. It may contain duplicates, and may contain multiple versions for a 36 // given module path. The root modules of the graph are the set of main 37 // modules in workspace mode, and the main module's direct requirements 38 // outside workspace mode. 39 // 40 // The roots are always expected to contain an entry for the "go" module, 41 // indicating the Go language version in use. 42 rootModules []module.Version 43 maxRootVersion map[string]string 44 45 // direct is the set of module paths for which we believe the module provides 46 // a package directly imported by a package or test in the main module. 47 // 48 // The "direct" map controls which modules are annotated with "// indirect" 49 // comments in the go.mod file, and may impact which modules are listed as 50 // explicit roots (vs. indirect-only dependencies). However, it should not 51 // have a semantic effect on the build list overall. 52 // 53 // The initial direct map is populated from the existing "// indirect" 54 // comments (or lack thereof) in the go.mod file. It is updated by the 55 // package loader: dependencies may be promoted to direct if new 56 // direct imports are observed, and may be demoted to indirect during 57 // 'go mod tidy' or 'go mod vendor'. 58 // 59 // The direct map is keyed by module paths, not module versions. When a 60 // module's selected version changes, we assume that it remains direct if the 61 // previous version was a direct dependency. That assumption might not hold in 62 // rare cases (such as if a dependency splits out a nested module, or merges a 63 // nested module back into a parent module). 64 direct map[string]bool 65 66 graphOnce sync.Once 67 graph atomic.Pointer[cachedGraph] 68 } 69 70 // String returns a string describing the Requirements for debugging. 71 func (rs *Requirements) String() string 72 73 // GoVersion returns the Go language version for the Requirements. 74 func (rs *Requirements) GoVersion() string 75 76 // Graph returns the graph of module requirements loaded from the current 77 // root modules (as reported by RootModules). 78 // 79 // Graph always makes a best effort to load the requirement graph despite any 80 // errors, and always returns a non-nil *ModuleGraph. 81 // 82 // If the requirements of any relevant module fail to load, Graph also 83 // returns a non-nil error of type *mvs.BuildListError. 84 func (rs *Requirements) Graph(ctx context.Context) (*ModuleGraph, error) 85 86 // IsDirect returns whether the given module provides a package directly 87 // imported by a package or test in the main module. 88 func (rs *Requirements) IsDirect(path string) bool 89 90 // A ModuleGraph represents the complete graph of module dependencies 91 // of a main module. 92 // 93 // If the main module supports module graph pruning, the graph does not include 94 // transitive dependencies of non-root (implicit) dependencies. 95 type ModuleGraph struct { 96 g *mvs.Graph 97 loadCache par.ErrCache[module.Version, *modFileSummary] 98 99 buildListOnce sync.Once 100 buildList []module.Version 101 } 102 103 // RequiredBy returns the dependencies required by module m in the graph, 104 // or ok=false if module m's dependencies are pruned out. 105 // 106 // The caller must not modify the returned slice, but may safely append to it 107 // and may rely on it not to be modified. 108 func (mg *ModuleGraph) RequiredBy(m module.Version) (reqs []module.Version, ok bool) 109 110 // Selected returns the selected version of the module with the given path. 111 // 112 // If no version is selected, Selected returns version "none". 113 func (mg *ModuleGraph) Selected(path string) (version string) 114 115 // WalkBreadthFirst invokes f once, in breadth-first order, for each module 116 // version other than "none" that appears in the graph, regardless of whether 117 // that version is selected. 118 func (mg *ModuleGraph) WalkBreadthFirst(f func(m module.Version)) 119 120 // BuildList returns the selected versions of all modules present in the graph, 121 // beginning with the main modules. 122 // 123 // The order of the remaining elements in the list is deterministic 124 // but arbitrary. 125 // 126 // The caller must not modify the returned list, but may safely append to it 127 // and may rely on it not to be modified. 128 func (mg *ModuleGraph) BuildList() []module.Version 129 130 // LoadModGraph loads and returns the graph of module dependencies of the main module, 131 // without loading any packages. 132 // 133 // If the goVersion string is non-empty, the returned graph is the graph 134 // as interpreted by the given Go version (instead of the version indicated 135 // in the go.mod file). 136 // 137 // Modules are loaded automatically (and lazily) in LoadPackages: 138 // LoadModGraph need only be called if LoadPackages is not, 139 // typically in commands that care about modules but no particular package. 140 func LoadModGraph(ctx context.Context, goVersion string) (*ModuleGraph, error) 141 142 // EditBuildList edits the global build list by first adding every module in add 143 // to the existing build list, then adjusting versions (and adding or removing 144 // requirements as needed) until every module in mustSelect is selected at the 145 // given version. 146 // 147 // (Note that the newly-added modules might not be selected in the resulting 148 // build list: they could be lower than existing requirements or conflict with 149 // versions in mustSelect.) 150 // 151 // If the versions listed in mustSelect are mutually incompatible (due to one of 152 // the listed modules requiring a higher version of another), EditBuildList 153 // returns a *ConstraintError and leaves the build list in its previous state. 154 // 155 // On success, EditBuildList reports whether the selected version of any module 156 // in the build list may have been changed (possibly to or from "none") as a 157 // result. 158 func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (changed bool, err error) 159 160 // OverrideRoots edits the global requirement roots by replacing the specific module versions. 161 func OverrideRoots(ctx context.Context, replace []module.Version) 162 163 // A ConstraintError describes inconsistent constraints in EditBuildList 164 type ConstraintError struct { 165 // Conflict lists the source of the conflict for each version in mustSelect 166 // that could not be selected due to the requirements of some other version in 167 // mustSelect. 168 Conflicts []Conflict 169 } 170 171 func (e *ConstraintError) Error() string 172 173 // A Conflict is a path of requirements starting at a root or proposed root in 174 // the requirement graph, explaining why that root either causes a module passed 175 // in the mustSelect list to EditBuildList to be unattainable, or introduces an 176 // unresolvable error in loading the requirement graph. 177 type Conflict struct { 178 // Path is a path of requirements starting at some module version passed in 179 // the mustSelect argument and ending at a module whose requirements make that 180 // version unacceptable. (Path always has len ≥ 1.) 181 Path []module.Version 182 183 // If Err is nil, Constraint is a module version passed in the mustSelect 184 // argument that has the same module path as, and a lower version than, 185 // the last element of the Path slice. 186 Constraint module.Version 187 188 // If Constraint is unset, Err is an error encountered when loading the 189 // requirements of the last element in Path. 190 Err error 191 } 192 193 // UnwrapModuleError returns c.Err, but unwraps it if it is a module.ModuleError 194 // with a version and path matching the last entry in the Path slice. 195 func (c Conflict) UnwrapModuleError() error 196 197 // Summary returns a string that describes only the first and last modules in 198 // the conflict path. 199 func (c Conflict) Summary() string 200 201 // String returns a string that describes the full conflict path. 202 func (c Conflict) String() string