1
0
mirror of https://github.com/golang/go synced 2024-11-23 07:20:06 -07:00

cmd/go: enter vendor mode depending on new modules.txt workspace line

modules.txt gets a new ## workspace line at the start of the file if
it's generated in workspace mode. Then, when deciding whether the go
command runs in mod=vendor, we only do so if we're in the same mode
(workspace or not) as the modules.txt specifies.

For #60056

Change-Id: If478a9891a7135614326fcb80c4c33a431e4e531
Reviewed-on: https://go-review.googlesource.com/c/go/+/513756
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
This commit is contained in:
Michael Matloob 2023-07-26 14:09:06 -04:00
parent 5abf00e4f0
commit 33cdafed52
6 changed files with 128 additions and 10 deletions

View File

@ -155,6 +155,10 @@ func RunVendor(ctx context.Context, vendorE bool, vendorO string, args []string)
w = io.MultiWriter(&buf, os.Stderr)
}
if modload.MainModules.WorkFile() != nil {
fmt.Fprintf(w, "## workspace\n")
}
replacementWritten := make(map[module.Version]bool)
for _, m := range vendorMods {
replacement := modload.Replacement(m)

View File

@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"internal/lazyregexp"
"io"
"os"
"path"
"path/filepath"
@ -1408,26 +1409,69 @@ func setDefaultBuildMod() {
if fi, err := fsys.Stat(vendorDir); err == nil && fi.IsDir() {
modGo := "unspecified"
if goVersion != "" {
if gover.Compare(goVersion, "1.14") >= 0 {
// The Go version is at least 1.14, and a vendor directory exists.
// Set -mod=vendor by default.
cfg.BuildMod = "vendor"
cfg.BuildModReason = "Go version in " + versionSource + " is at least 1.14 and vendor directory exists."
return
if gover.Compare(goVersion, "1.14") < 0 {
// The go version is less than 1.14. Don't set -mod=vendor by default.
// Since a vendor directory exists, we should record why we didn't use it.
// This message won't normally be shown, but it may appear with import errors.
cfg.BuildModReason = fmt.Sprintf("Go version in "+versionSource+" is %s, so vendor directory was not used.", modGo)
} else {
modGo = goVersion
vendoredWorkspace, err := modulesTextIsForWorkspace(vendorDir)
if err != nil {
base.Fatalf("go: reading modules.txt for vendor directory: %v", err)
}
if vendoredWorkspace != (versionSource == "go.work") {
if vendoredWorkspace {
cfg.BuildModReason = "Outside workspace mode, but vendor directory is for a workspace."
} else {
cfg.BuildModReason = "In workspace mode, but vendor directory is not for a workspace"
}
} else {
// The Go version is at least 1.14, a vendor directory exists, and
// the modules.txt was generated in the same mode the command is running in.
// Set -mod=vendor by default.
cfg.BuildMod = "vendor"
cfg.BuildModReason = "Go version in " + versionSource + " is at least 1.14 and vendor directory exists."
return
}
}
modGo = goVersion
}
// Since a vendor directory exists, we should record why we didn't use it.
// This message won't normally be shown, but it may appear with import errors.
cfg.BuildModReason = fmt.Sprintf("Go version in "+versionSource+" is %s, so vendor directory was not used.", modGo)
}
}
cfg.BuildMod = "readonly"
}
func modulesTextIsForWorkspace(vendorDir string) (bool, error) {
f, err := fsys.Open(filepath.Join(vendorDir, "modules.txt"))
if errors.Is(err, os.ErrNotExist) {
// Some vendor directories exist that don't contain modules.txt.
// This mostly happens when converting to modules.
// We want to preserve the behavior that mod=vendor is set (even though
// readVendorList does nothing in that case).
return false, nil
}
if err != nil {
return false, err
}
var buf [512]byte
n, err := f.Read(buf[:])
if err != nil && err != io.EOF {
return false, err
}
line, _, _ := strings.Cut(string(buf[:n]), "\n")
if annotations, ok := strings.CutPrefix(line, "## "); ok {
for _, entry := range strings.Split(annotations, ";") {
entry = strings.TrimSpace(entry)
if entry == "workspace" {
return true, nil
}
}
}
return false, nil
}
func mustHaveCompleteRequirements() bool {
return cfg.BuildMod != "mod" && !inWorkspaceMode()
}

View File

@ -0,0 +1,62 @@
# This test checks to see if we only start in workspace vendor
# mode if the modules.txt specifies ## workspace (and only in
# standard vendor if it doesn't).
# vendor directory produced for workspace, workspace mode
# runs in mod=vendor
go work vendor
cmp vendor/modules.txt want_workspace_modules_txt
go list -f {{.Dir}} example.com/b
stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
# vendor directory produced for workspace, module mode
# runs in mod=readonly
env GOWORK=off
go list -f {{.Dir}} example.com/b
stdout $GOPATH[\\/]src[\\/]b
# vendor directory produced for module, module mode
# runs in mod=vendor
go mod vendor
cmp vendor/modules.txt want_module_modules_txt
go list -f {{.Dir}} example.com/b
stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]b
# vendor directory produced for module, workspace mode
# runs in mod=readonly
env GOWORK=
go list -f {{.Dir}} example.com/b
stdout $GOPATH[\\/]src[\\/]b
-- want_workspace_modules_txt --
## workspace
# example.com/b v0.0.0 => ./b
## explicit; go 1.21
example.com/b
# example.com/b => ./b
-- want_module_modules_txt --
# example.com/b v0.0.0 => ./b
## explicit; go 1.21
example.com/b
# example.com/b => ./b
-- go.work --
go 1.21
use .
-- go.mod --
module example.com/a
go 1.21
require example.com/b v0.0.0
replace example.com/b => ./b
-- a.go --
package a
import _ "example.com/b"
-- b/go.mod --
module example.com/b
go 1.21
-- b/b.go --
package b

View File

@ -28,11 +28,13 @@ cp modules.txt.extra_replacement vendor/modules.txt
cmpenv stderr extra_replacement_error.txt
-- modules.txt.want --
## workspace
# example.com/p v1.0.0 => ./p
## explicit; go 1.21
# example.com/q v1.0.0 => ./q
## explicit; go 1.21
-- modules.txt.required_but_not_explicit --
## workspace
# example.com/p v1.0.0 => ./p
## go 1.21
# example.com/q v1.0.0 => ./q
@ -45,6 +47,7 @@ go: inconsistent vendoring in $GOPATH${/}src:
To sync the vendor directory, run:
go work vendor
-- modules.txt.missing_replacement --
## workspace
# example.com/p v1.0.0
## explicit; go 1.21
# example.com/q v1.0.0 => ./q
@ -57,6 +60,7 @@ go: inconsistent vendoring in $GOPATH${/}src:
To sync the vendor directory, run:
go work vendor
-- modules.txt.different_replacement --
## workspace
# example.com/p v1.0.0 => ./r
## explicit; go 1.21
# example.com/q v1.0.0 => ./q
@ -69,6 +73,7 @@ go: inconsistent vendoring in $GOPATH${/}src:
To sync the vendor directory, run:
go work vendor
-- modules.txt.extra_explicit --
## workspace
# example.com/p v1.0.0 => ./p
## explicit; go 1.21
# example.com/q v1.0.0 => ./q
@ -84,6 +89,7 @@ go: inconsistent vendoring in $GOPATH${/}src:
To sync the vendor directory, run:
go work vendor
-- modules.txt.extra_replacement --
## workspace
# example.com/p v1.0.0 => ./p
## explicit; go 1.21
# example.com/q v1.0.0 => ./q

View File

@ -22,6 +22,7 @@ go run example.com/p
stdout 'version 1.1.0'
-- modules.txt.want --
## workspace
# example.com/b v1.0.0 => ./b
## explicit; go 1.18
example.com/b

View File

@ -18,6 +18,7 @@ stdout $GOPATH[\\/]src[\\/]vendor[\\/]example.com[\\/]z
cmp $GOPATH/src/vendor/example.com/q/q.go q1_1_0/q.go
-- modules.txt.want --
## workspace
# example.com/b v1.0.0 => ./b
## explicit; go 1.18
example.com/b