// editRequirements returns an edited version of rs such that: // // 1. Each module version in mustSelect is selected. // // 2. Each module version in tryUpgrade is upgraded toward the indicated // version as far as can be done without violating (1). // (Other upgrades are also allowed if they are caused by // transitive requirements of versions in mustSelect or // tryUpgrade.) // // 3. Each module version in rs.rootModules (or rs.graph, if rs is unpruned) // is downgraded or upgraded from its original version only to the extent // needed to satisfy (1) and (2). // // Generally, the module versions in mustSelect are due to the module or a // package within the module matching an explicit command line argument to 'go // get', and the versions in tryUpgrade are transitive dependencies that are // either being upgraded by 'go get -u' or being added to satisfy some // otherwise-missing package import. // // If pruning is enabled, the roots of the edited requirements include an // explicit entry for each module path in tryUpgrade, mustSelect, and the roots // of rs, unless the selected version for the module path is "none". func editRequirements(ctx context.Context, rs *Requirements, tryUpgrade, mustSelect []module.Version) (edited *Requirements, changed bool, err error) { … } // extendGraph loads the module graph from roots, and iteratively extends it by // unpruning the selected version of each module path that is a root in rs or in // the roots slice until the graph reaches a fixed point. // // The graph is guaranteed to converge to a fixed point because unpruning a // module version can only increase (never decrease) the selected versions, // and the set of versions for each module is finite. // // The extended graph is useful for diagnosing version conflicts: for each // selected module version, it can provide a complete path of requirements from // some root to that version. func extendGraph(ctx context.Context, rootPruning modPruning, roots []module.Version, selectedRoot map[string]string) (mg *ModuleGraph, upgradedRoot map[module.Version]bool, err error) { … } type perPruning … func (pp perPruning[T]) from(p modPruning) T { … } type dqTracker … type dqState … func (dq dqState) isDisqualified() bool { … } func (dq dqState) String() string { … } // require records that m directly requires r, in case r becomes disqualified. // (These edges are in the opposite direction from the edges in an mvs.Graph.) // // If r is already disqualified, require propagates the disqualification to m // and returns the reason for the disqualification. func (t *dqTracker) require(m, r module.Version) (ok bool) { … } // disqualify records why the dependencies of m cannot be included in the module // graph if reached from a part of the graph with the given pruning. // // Since the pruned graph is a subgraph of the unpruned graph, disqualifying a // module from a pruned part of the graph also disqualifies it in the unpruned // parts. func (t *dqTracker) disqualify(m module.Version, fromPruning modPruning, reason dqState) { … } // check reports whether m is disqualified in the given pruning context. func (t *dqTracker) check(m module.Version, pruning modPruning) dqState { … } // path returns the path from m to the reason it is disqualified, which may be // either a module that violates constraints or an error in loading // requirements. // // If m is not disqualified, path returns (nil, nil). func (t *dqTracker) path(m module.Version, pruning modPruning) (path []module.Version, err error) { … }