Skip to content

Commit 5b18234

Browse files
committed
go/packages: set -mod=readonly when processing overlays in module mode
To prevent us from adding additional module dependencies to modules, especially if the file is in a different module. Sometimes adding additional dependencies would be the right behavior, but sometimes we run go list to determine information about files in other modules, and modifying modules outside the one the user is operating in is bad behavior. Fixes golang/go#32499 Change-Id: I2a12e0a64dc6cd34fa98931cbacc30707e5ba494 Reviewed-on: https://go-review.googlesource.com/c/tools/+/190179 Run-TryBot: Michael Matloob <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Rebecca Stambler <[email protected]>
1 parent 597f577 commit 5b18234

File tree

3 files changed

+54
-23
lines changed

3 files changed

+54
-23
lines changed

go/packages/golist.go

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,28 @@ func (r *responseDeduper) addRoot(id string) {
7272
r.dr.Roots = append(r.dr.Roots, id)
7373
}
7474

75+
// goInfo contains global information from the go tool.
76+
type goInfo struct {
77+
rootDirs map[string]string
78+
env goEnv
79+
}
80+
81+
type goEnv struct {
82+
modulesOn bool
83+
}
84+
85+
func determineEnv(cfg *Config) goEnv {
86+
buf, err := invokeGo(cfg, "env", "GOMOD")
87+
if err != nil {
88+
return goEnv{}
89+
}
90+
gomod := bytes.TrimSpace(buf.Bytes())
91+
92+
env := goEnv{}
93+
env.modulesOn = len(gomod) > 0
94+
return env
95+
}
96+
7597
// goListDriver uses the go list command to interpret the patterns and produce
7698
// the build system package structure.
7799
// See driver for more details.
@@ -88,20 +110,25 @@ func goListDriver(cfg *Config, patterns ...string) (*driverResponse, error) {
88110
}
89111

90112
// start fetching rootDirs
91-
var rootDirs map[string]string
92-
var rootDirsReady = make(chan struct{})
113+
var info goInfo
114+
var rootDirsReady, envReady = make(chan struct{}), make(chan struct{})
93115
go func() {
94-
rootDirs = determineRootDirs(cfg)
116+
info.rootDirs = determineRootDirs(cfg)
95117
close(rootDirsReady)
96118
}()
97-
getRootDirs := func() map[string]string {
119+
go func() {
120+
info.env = determineEnv(cfg)
121+
close(envReady)
122+
}()
123+
getGoInfo := func() *goInfo {
98124
<-rootDirsReady
99-
return rootDirs
125+
<-envReady
126+
return &info
100127
}
101128

102-
// always pass getRootDirs to golistDriver
129+
// always pass getGoInfo to golistDriver
103130
golistDriver := func(cfg *Config, patterns ...string) (*driverResponse, error) {
104-
return golistDriver(cfg, getRootDirs, patterns...)
131+
return golistDriver(cfg, getGoInfo, patterns...)
105132
}
106133

107134
// Determine files requested in contains patterns
@@ -165,7 +192,7 @@ extractQueries:
165192
var containsCandidates []string
166193

167194
if len(containFiles) != 0 {
168-
if err := runContainsQueries(cfg, golistDriver, response, containFiles, getRootDirs); err != nil {
195+
if err := runContainsQueries(cfg, golistDriver, response, containFiles, getGoInfo); err != nil {
169196
return nil, err
170197
}
171198
}
@@ -176,15 +203,15 @@ extractQueries:
176203
}
177204
}
178205

179-
modifiedPkgs, needPkgs, err := processGolistOverlay(cfg, response, getRootDirs)
206+
modifiedPkgs, needPkgs, err := processGolistOverlay(cfg, response, getGoInfo)
180207
if err != nil {
181208
return nil, err
182209
}
183210
if len(containFiles) > 0 {
184211
containsCandidates = append(containsCandidates, modifiedPkgs...)
185212
containsCandidates = append(containsCandidates, needPkgs...)
186213
}
187-
if err := addNeededOverlayPackages(cfg, golistDriver, response, needPkgs, getRootDirs); err != nil {
214+
if err := addNeededOverlayPackages(cfg, golistDriver, response, needPkgs, getGoInfo); err != nil {
188215
return nil, err
189216
}
190217
// Check candidate packages for containFiles.
@@ -216,28 +243,33 @@ extractQueries:
216243
return response.dr, nil
217244
}
218245

219-
func addNeededOverlayPackages(cfg *Config, driver driver, response *responseDeduper, pkgs []string, getRootDirs func() map[string]string) error {
246+
func addNeededOverlayPackages(cfg *Config, driver driver, response *responseDeduper, pkgs []string, getGoInfo func() *goInfo) error {
220247
if len(pkgs) == 0 {
221248
return nil
222249
}
223-
dr, err := driver(cfg, pkgs...)
250+
drivercfg := *cfg
251+
if getGoInfo().env.modulesOn {
252+
drivercfg.BuildFlags = append(drivercfg.BuildFlags, "-mod=readonly")
253+
}
254+
dr, err := driver(&drivercfg, pkgs...)
255+
224256
if err != nil {
225257
return err
226258
}
227259
for _, pkg := range dr.Packages {
228260
response.addPackage(pkg)
229261
}
230-
_, needPkgs, err := processGolistOverlay(cfg, response, getRootDirs)
262+
_, needPkgs, err := processGolistOverlay(cfg, response, getGoInfo)
231263
if err != nil {
232264
return err
233265
}
234-
if err := addNeededOverlayPackages(cfg, driver, response, needPkgs, getRootDirs); err != nil {
266+
if err := addNeededOverlayPackages(cfg, driver, response, needPkgs, getGoInfo); err != nil {
235267
return err
236268
}
237269
return nil
238270
}
239271

240-
func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, queries []string, rootDirs func() map[string]string) error {
272+
func runContainsQueries(cfg *Config, driver driver, response *responseDeduper, queries []string, goInfo func() *goInfo) error {
241273
for _, query := range queries {
242274
// TODO(matloob): Do only one query per directory.
243275
fdir := filepath.Dir(query)
@@ -600,7 +632,7 @@ func otherFiles(p *jsonPackage) [][]string {
600632
// golistDriver uses the "go list" command to expand the pattern
601633
// words and return metadata for the specified packages. dir may be
602634
// "" and env may be nil, as per os/exec.Command.
603-
func golistDriver(cfg *Config, rootsDirs func() map[string]string, words ...string) (*driverResponse, error) {
635+
func golistDriver(cfg *Config, rootsDirs func() *goInfo, words ...string) (*driverResponse, error) {
604636
// go list uses the following identifiers in ImportPath and Imports:
605637
//
606638
// "p" -- importable package or main (command)
@@ -759,8 +791,8 @@ func golistDriver(cfg *Config, rootsDirs func() map[string]string, words ...stri
759791
}
760792

761793
// getPkgPath finds the package path of a directory if it's relative to a root directory.
762-
func getPkgPath(dir string, rootDirs func() map[string]string) (string, bool) {
763-
for rdir, rpath := range rootDirs() {
794+
func getPkgPath(dir string, goInfo func() *goInfo) (string, bool) {
795+
for rdir, rpath := range goInfo().rootDirs {
764796
// TODO(matloob): This doesn't properly handle symlinks.
765797
r, err := filepath.Rel(rdir, dir)
766798
if err != nil {

go/packages/golist_overlay.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
// sometimes incorrect.
1818
// TODO(matloob): Handle unsupported cases, including the following:
1919
// - determining the correct package to add given a new import path
20-
func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func() map[string]string) (modifiedPkgs, needPkgs []string, err error) {
20+
func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func() *goInfo) (modifiedPkgs, needPkgs []string, err error) {
2121
havePkgs := make(map[string]string) // importPath -> non-test package ID
2222
needPkgsSet := make(map[string]bool)
2323
modifiedPkgsSet := make(map[string]bool)
@@ -75,7 +75,7 @@ func processGolistOverlay(cfg *Config, response *responseDeduper, rootDirs func(
7575
// Try to find the module or gopath dir the file is contained in.
7676
// Then for modules, add the module opath to the beginning.
7777
var pkgPath string
78-
for rdir, rpath := range rootDirs() {
78+
for rdir, rpath := range rootDirs().rootDirs {
7979
// TODO(matloob): This doesn't properly handle symlinks.
8080
r, err := filepath.Rel(rdir, dir)
8181
if err != nil {

go/packages/packages_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,9 +1053,6 @@ const A = 1
10531053
// TestOverlayModFileChanges tests the behavior resulting from having files from
10541054
// multiple modules in overlays.
10551055
func TestOverlayModFileChanges(t *testing.T) {
1056-
// TODO: Enable this test when golang/go#32499 is resolved.
1057-
t.Skip()
1058-
10591056
// Create two unrelated modules in a temporary directory.
10601057
tmp, err := ioutil.TempDir("", "tmp")
10611058
if err != nil {
@@ -1086,6 +1083,8 @@ func TestOverlayModFileChanges(t *testing.T) {
10861083
defer os.Remove(mod2)
10871084

10881085
want := `module mod2
1086+
1087+
go 1.11
10891088
`
10901089
if err := ioutil.WriteFile(filepath.Join(mod2, "go.mod"), []byte(want), 0775); err != nil {
10911090
t.Fatal(err)

0 commit comments

Comments
 (0)