1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:58:00 -07:00

cmd/go: in 'go get', promote named implicit dependencies to explicit

'go get pkg@vers' will now add an explicit requirement for the module
providing pkg if that version was already indirectly required.

'go get mod@vers' will do the same if mod is a module path but not a
package.

Requirements promoted this way will be marked "// indirect" because
'go get' doesn't know whether they're needed to build packages in the
main module. So users should prefer to run 'go get ./pkg' (where ./pkg
is a package in the main module) to promote requirements.

Fixes #43131

Change-Id: Ifbb65b71274b3cc752a7a593d6ddd875f7de23b8
Reviewed-on: https://go-review.googlesource.com/c/go/+/278812
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Jay Conrod <jayconrod@google.com>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jay Conrod 2020-12-16 16:37:56 -05:00
parent fd6ba1c8a2
commit 98a73030b0
5 changed files with 39 additions and 8 deletions

View File

@ -28,6 +28,11 @@ import (
// //
var buildList []module.Version var buildList []module.Version
// additionalExplicitRequirements is a list of modules paths for which
// WriteGoMod should record explicit requirements, even if they would be
// selected without those requirements. Each path must also appear in buildList.
var additionalExplicitRequirements []string
// capVersionSlice returns s with its cap reduced to its length. // capVersionSlice returns s with its cap reduced to its length.
func capVersionSlice(s []module.Version) []module.Version { func capVersionSlice(s []module.Version) []module.Version {
return s[:len(s):len(s)] return s[:len(s):len(s)]
@ -121,6 +126,12 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) error
if !inconsistent { if !inconsistent {
buildList = final buildList = final
additionalExplicitRequirements = make([]string, 0, len(mustSelect))
for _, m := range mustSelect {
if m.Version != "none" {
additionalExplicitRequirements = append(additionalExplicitRequirements, m.Path)
}
}
return nil return nil
} }

View File

@ -15,6 +15,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -27,6 +28,7 @@ import (
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/mvs" "cmd/go/internal/mvs"
"cmd/go/internal/search" "cmd/go/internal/search"
"cmd/go/internal/str"
"golang.org/x/mod/modfile" "golang.org/x/mod/modfile"
"golang.org/x/mod/module" "golang.org/x/mod/module"
@ -845,13 +847,15 @@ func AllowWriteGoMod() {
// MinReqs returns a Reqs with minimal additional dependencies of Target, // MinReqs returns a Reqs with minimal additional dependencies of Target,
// as will be written to go.mod. // as will be written to go.mod.
func MinReqs() mvs.Reqs { func MinReqs() mvs.Reqs {
var retain []string retain := append([]string{}, additionalExplicitRequirements...)
for _, m := range buildList[1:] { for _, m := range buildList[1:] {
_, explicit := index.require[m] _, explicit := index.require[m]
if explicit || loaded.direct[m.Path] { if explicit || loaded.direct[m.Path] {
retain = append(retain, m.Path) retain = append(retain, m.Path)
} }
} }
sort.Strings(retain)
str.Uniq(&retain)
min, err := mvs.Req(Target, retain, &mvsReqs{buildList: buildList}) min, err := mvs.Req(Target, retain, &mvsReqs{buildList: buildList})
if err != nil { if err != nil {
base.Fatalf("go: %v", err) base.Fatalf("go: %v", err)

View File

@ -21,6 +21,7 @@ import (
"cmd/go/internal/imports" "cmd/go/internal/imports"
"cmd/go/internal/modfetch" "cmd/go/internal/modfetch"
"cmd/go/internal/search" "cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/trace" "cmd/go/internal/trace"
"golang.org/x/mod/module" "golang.org/x/mod/module"
@ -1005,13 +1006,8 @@ func (rr *replacementRepo) Versions(prefix string) ([]string, error) {
sort.Slice(versions, func(i, j int) bool { sort.Slice(versions, func(i, j int) bool {
return semver.Compare(versions[i], versions[j]) < 0 return semver.Compare(versions[i], versions[j]) < 0
}) })
uniq := versions[:1] str.Uniq(&versions)
for _, v := range versions { return versions, nil
if v != uniq[len(uniq)-1] {
uniq = append(uniq, v)
}
}
return uniq, nil
} }
func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) { func (rr *replacementRepo) Stat(rev string) (*modfetch.RevInfo, error) {

View File

@ -96,6 +96,20 @@ func Contains(x []string, s string) bool {
return false return false
} }
// Uniq removes consecutive duplicate strings from ss.
func Uniq(ss *[]string) {
if len(*ss) <= 1 {
return
}
uniq := (*ss)[:1]
for _, s := range *ss {
if s != uniq[len(uniq)-1] {
uniq = append(uniq, s)
}
}
*ss = uniq
}
func isSpaceByte(c byte) bool { func isSpaceByte(c byte) bool {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' return c == ' ' || c == '\t' || c == '\n' || c == '\r'
} }

View File

@ -14,6 +14,12 @@ go get -d m/use-indirect
cmp go.mod go.mod.use cmp go.mod go.mod.use
cp go.mod.orig go.mod cp go.mod.orig go.mod
# We can also promote implicit requirements using 'go get' on them, or their
# packages. This gives us "// indirect" requirements, since 'go get' doesn't
# know they're needed by the main module. See #43131 for the rationale.
go get -d indirect-with-pkg indirect-without-pkg
cmp go.mod go.mod.indirect
-- go.mod.orig -- -- go.mod.orig --
module m module m