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