github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/go/internal/modload/init.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/errors" 10 "github.com/shogo82148/std/sync" 11 12 "golang.org/x/mod/modfile" 13 "golang.org/x/mod/module" 14 ) 15 16 // Variables set by other packages. 17 // 18 // TODO(#40775): See if these can be plumbed as explicit parameters. 19 var ( 20 // RootMode determines whether a module root is needed. 21 RootMode Root 22 23 // ForceUseModules may be set to force modules to be enabled when 24 // GO111MODULE=auto or to report an error when GO111MODULE=off. 25 ForceUseModules bool 26 27 // ExplicitWriteGoMod prevents LoadPackages, ListModules, and other functions 28 // from updating go.mod and go.sum or reporting errors when updates are 29 // needed. A package should set this if it would cause go.mod to be written 30 // multiple times (for example, 'go get' calls LoadPackages multiple times) or 31 // if it needs some other operation to be successful before go.mod and go.sum 32 // can be written (for example, 'go mod download' must download modules before 33 // adding sums to go.sum). Packages that set this are responsible for calling 34 // WriteGoMod explicitly. 35 ExplicitWriteGoMod bool 36 ) 37 38 // EnterModule resets MainModules and requirements to refer to just this one module. 39 func EnterModule(ctx context.Context, enterModroot string) 40 41 type MainModuleSet struct { 42 // versions are the module.Version values of each of the main modules. 43 // For each of them, the Path fields are ordinary module paths and the Version 44 // fields are empty strings. 45 // versions is clipped (len=cap). 46 versions []module.Version 47 48 // modRoot maps each module in versions to its absolute filesystem path. 49 modRoot map[module.Version]string 50 51 // pathPrefix is the path prefix for packages in the module, without a trailing 52 // slash. For most modules, pathPrefix is just version.Path, but the 53 // standard-library module "std" has an empty prefix. 54 pathPrefix map[module.Version]string 55 56 // inGorootSrc caches whether modRoot is within GOROOT/src. 57 // The "std" module is special within GOROOT/src, but not otherwise. 58 inGorootSrc map[module.Version]bool 59 60 modFiles map[module.Version]*modfile.File 61 62 modContainingCWD module.Version 63 64 workFile *modfile.WorkFile 65 66 workFileReplaceMap map[module.Version]module.Version 67 // highest replaced version of each module path; empty string for wildcard-only replacements 68 highestReplaced map[string]string 69 70 indexMu sync.Mutex 71 indices map[module.Version]*modFileIndex 72 } 73 74 func (mms *MainModuleSet) PathPrefix(m module.Version) string 75 76 // Versions returns the module.Version values of each of the main modules. 77 // For each of them, the Path fields are ordinary module paths and the Version 78 // fields are empty strings. 79 // Callers should not modify the returned slice. 80 func (mms *MainModuleSet) Versions() []module.Version 81 82 func (mms *MainModuleSet) Contains(path string) bool 83 84 func (mms *MainModuleSet) ModRoot(m module.Version) string 85 86 func (mms *MainModuleSet) InGorootSrc(m module.Version) bool 87 88 func (mms *MainModuleSet) GetSingleIndexOrNil() *modFileIndex 89 90 func (mms *MainModuleSet) Index(m module.Version) *modFileIndex 91 92 func (mms *MainModuleSet) SetIndex(m module.Version, index *modFileIndex) 93 94 func (mms *MainModuleSet) ModFile(m module.Version) *modfile.File 95 96 func (mms *MainModuleSet) WorkFile() *modfile.WorkFile 97 98 func (mms *MainModuleSet) Len() int 99 100 // ModContainingCWD returns the main module containing the working directory, 101 // or module.Version{} if none of the main modules contain the working 102 // directory. 103 func (mms *MainModuleSet) ModContainingCWD() module.Version 104 105 func (mms *MainModuleSet) HighestReplaced() map[string]string 106 107 // GoVersion returns the go version set on the single module, in module mode, 108 // or the go.work file in workspace mode. 109 func (mms *MainModuleSet) GoVersion() string 110 111 // Toolchain returns the toolchain set on the single module, in module mode, 112 // or the go.work file in workspace mode. 113 func (mms *MainModuleSet) Toolchain() string 114 115 func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version 116 117 var MainModules *MainModuleSet 118 119 type Root int 120 121 const ( 122 // AutoRoot is the default for most commands. modload.Init will look for 123 // a go.mod file in the current directory or any parent. If none is found, 124 // modules may be disabled (GO111MODULE=auto) or commands may run in a 125 // limited module mode. 126 AutoRoot Root = iota 127 128 // NoRoot is used for commands that run in module mode and ignore any go.mod 129 // file the current directory or in parent directories. 130 NoRoot 131 132 // NeedRoot is used for commands that must run in module mode and don't 133 // make sense without a main module. 134 NeedRoot 135 ) 136 137 // ModFile returns the parsed go.mod file. 138 // 139 // Note that after calling LoadPackages or LoadModGraph, 140 // the require statements in the modfile.File are no longer 141 // the source of truth and will be ignored: edits made directly 142 // will be lost at the next call to WriteGoMod. 143 // To make permanent changes to the require statements 144 // in go.mod, edit it before loading. 145 func ModFile() *modfile.File 146 147 func BinDir() string 148 149 // InitWorkfile initializes the workFilePath variable for commands that 150 // operate in workspace mode. It should not be called by other commands, 151 // for example 'go mod tidy', that don't operate in workspace mode. 152 func InitWorkfile() 153 154 // FindGoWork returns the name of the go.work file for this command, 155 // or the empty string if there isn't one. 156 // Most code should use Init and Enabled rather than use this directly. 157 // It is exported mainly for Go toolchain switching, which must process 158 // the go.work very early at startup. 159 func FindGoWork(wd string) string 160 161 // WorkFilePath returns the absolute path of the go.work file, or "" if not in 162 // workspace mode. WorkFilePath must be called after InitWorkfile. 163 func WorkFilePath() string 164 165 // Reset clears all the initialized, cached state about the use of modules, 166 // so that we can start over. 167 func Reset() 168 169 // Init determines whether module mode is enabled, locates the root of the 170 // current module (if any), sets environment variables for Git subprocesses, and 171 // configures the cfg, codehost, load, modfetch, and search packages for use 172 // with modules. 173 func Init() 174 175 // WillBeEnabled checks whether modules should be enabled but does not 176 // initialize modules by installing hooks. If Init has already been called, 177 // WillBeEnabled returns the same result as Enabled. 178 // 179 // This function is needed to break a cycle. The main package needs to know 180 // whether modules are enabled in order to install the module or GOPATH version 181 // of 'go get', but Init reads the -modfile flag in 'go get', so it shouldn't 182 // be called until the command is installed and flags are parsed. Instead of 183 // calling Init and Enabled, the main package can call this function. 184 func WillBeEnabled() bool 185 186 // FindGoMod returns the name of the go.mod file for this command, 187 // or the empty string if there isn't one. 188 // Most code should use Init and Enabled rather than use this directly. 189 // It is exported mainly for Go toolchain switching, which must process 190 // the go.mod very early at startup. 191 func FindGoMod(wd string) string 192 193 // Enabled reports whether modules are (or must be) enabled. 194 // If modules are enabled but there is no main module, Enabled returns true 195 // and then the first use of module information will call die 196 // (usually through MustModRoot). 197 func Enabled() bool 198 199 func VendorDir() string 200 201 // HasModRoot reports whether a main module is present. 202 // HasModRoot may return false even if Enabled returns true: for example, 'get' 203 // does not require a main module. 204 func HasModRoot() bool 205 206 // MustHaveModRoot checks that a main module or main modules are present, 207 // and calls base.Fatalf if there are no main modules. 208 func MustHaveModRoot() 209 210 // ModFilePath returns the path that would be used for the go.mod 211 // file, if in module mode. ModFilePath calls base.Fatalf if there is no main 212 // module, even if -modfile is set. 213 func ModFilePath() string 214 215 var ErrNoModRoot = errors.New("go.mod file not found in current directory or any parent directory; see 'go help modules'") 216 217 // ReadWorkFile reads and parses the go.work file at the given path. 218 func ReadWorkFile(path string) (*modfile.WorkFile, error) 219 220 // WriteWorkFile cleans and writes out the go.work file to the given path. 221 func WriteWorkFile(path string, wf *modfile.WorkFile) error 222 223 // UpdateWorkGoVersion updates the go line in wf to be at least goVers, 224 // reporting whether it changed the file. 225 func UpdateWorkGoVersion(wf *modfile.WorkFile, goVers string) (changed bool) 226 227 // UpdateWorkFile updates comments on directory directives in the go.work 228 // file to include the associated module path. 229 func UpdateWorkFile(wf *modfile.WorkFile) 230 231 // LoadModFile sets Target and, if there is a main module, parses the initial 232 // build list from its go.mod file. 233 // 234 // LoadModFile may make changes in memory, like adding a go directive and 235 // ensuring requirements are consistent. The caller is responsible for ensuring 236 // those changes are written to disk by calling LoadPackages or ListModules 237 // (unless ExplicitWriteGoMod is set) or by calling WriteGoMod directly. 238 // 239 // As a side-effect, LoadModFile may change cfg.BuildMod to "vendor" if 240 // -mod wasn't set explicitly and automatic vendoring should be enabled. 241 // 242 // If LoadModFile or CreateModFile has already been called, LoadModFile returns 243 // the existing in-memory requirements (rather than re-reading them from disk). 244 // 245 // LoadModFile checks the roots of the module graph for consistency with each 246 // other, but unlike LoadModGraph does not load the full module graph or check 247 // it for global consistency. Most callers outside of the modload package should 248 // use LoadModGraph instead. 249 func LoadModFile(ctx context.Context) *Requirements 250 251 // CreateModFile initializes a new module by creating a go.mod file. 252 // 253 // If modPath is empty, CreateModFile will attempt to infer the path from the 254 // directory location within GOPATH. 255 // 256 // If a vendoring configuration file is present, CreateModFile will attempt to 257 // translate it to go.mod directives. The resulting build list may not be 258 // exactly the same as in the legacy configuration (for example, we can't get 259 // packages at multiple versions from the same module). 260 func CreateModFile(ctx context.Context, modPath string) 261 262 // AllowMissingModuleImports allows import paths to be resolved to modules 263 // when there is no module root. Normally, this is forbidden because it's slow 264 // and there's no way to make the result reproducible, but some commands 265 // like 'go get' are expected to do this. 266 // 267 // This function affects the default cfg.BuildMod when outside of a module, 268 // so it can only be called prior to Init. 269 func AllowMissingModuleImports() 270 271 // WriteOpts control the behavior of WriteGoMod. 272 type WriteOpts struct { 273 DropToolchain bool 274 ExplicitToolchain bool 275 276 // TODO(bcmills): Make 'go mod tidy' update the go version in the Requirements 277 // instead of writing directly to the modfile.File 278 TidyWroteGo bool 279 } 280 281 // WriteGoMod writes the current build list back to go.mod. 282 func WriteGoMod(ctx context.Context, opts WriteOpts) error