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