Skip to content

Commit 2557dd1

Browse files
committed
Use Go cache if modules are in found in the cache
In module mode, when all module dependencies are given with canonical versions and the version is found in the cache, set GOPROXY to file://$(go env GOMODCACHE)/cache/download so that "go get" skips querying the proxy. Related: golang/go#43646 (proposal for GOPROXY=cache)
1 parent eff6aff commit 2557dd1

File tree

1 file changed

+51
-5
lines changed

1 file changed

+51
-5
lines changed

main.go

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ import (
3131
"time"
3232

3333
"golang.org/x/mod/module"
34+
"golang.org/x/mod/semver"
3435
goimp "golang.org/x/tools/imports"
3536
)
3637

3738
type imports struct {
38-
packages map[string]string // alias => import path
39-
modules map[string]string // module path => version
39+
packages map[string]string // alias => import path
40+
modules map[string]string // module path => version
41+
onlySemVer bool
4042
}
4143

4244
func (*imports) String() string {
@@ -71,6 +73,7 @@ func (imp *imports) Set(s string) error {
7173
imp.modules = make(map[string]string)
7274
}
7375
imp.modules[path] = version
76+
imp.onlySemVer = imp.onlySemVer && semver.IsValid(version) && version == semver.Canonical(version)
7477
} else if alias == "" {
7578
alias = " " + path // special alias
7679
}
@@ -104,7 +107,7 @@ func runSilent(cmd *exec.Cmd) error {
104107

105108
func runX(cmd *exec.Cmd) error {
106109
// Inject -x in go commands
107-
if cmd.Args[0] == "go" {
110+
if cmd.Args[0] == "go" && cmd.Args[1] != "env" {
108111
cmd.Args = append([]string{"go", cmd.Args[1], "-x"}, cmd.Args[2:]...)
109112
}
110113
fmt.Printf("%s\n", cmd.Args)
@@ -118,6 +121,25 @@ func runTime(cmd *exec.Cmd) error {
118121
return cmd.Run()
119122
}
120123

124+
var goCmd = "go"
125+
126+
func getGOMODCACHE(env []string) (string, error) {
127+
var out bytes.Buffer
128+
cmd := exec.Command(goCmd, "env", "GOMODCACHE")
129+
cmd.Stderr = os.Stderr
130+
cmd.Stdout = &out
131+
cmd.Env = env
132+
err := run(cmd)
133+
if err != nil {
134+
return "", err
135+
}
136+
b := bytes.TrimRight(out.Bytes(), "\r\n")
137+
if len(b) == 0 {
138+
return "", errors.New("can't retrieve GOMODCACHE")
139+
}
140+
return string(b), nil
141+
}
142+
121143
func main() {
122144
err := _main()
123145
if exit, ok := err.(*exec.ExitError); ok && exit.ExitCode() > 0 {
@@ -129,7 +151,8 @@ func main() {
129151

130152
func _main() error {
131153
imports := imports{
132-
packages: map[string]string{" ": "os"},
154+
packages: map[string]string{" ": "os"},
155+
onlySemVer: true,
133156
}
134157
flag.Var(&imports, "i", "import package: [alias=]import-path")
135158

@@ -193,6 +216,16 @@ func _main() error {
193216
var dir, origDir string
194217

195218
if moduleMode {
219+
// "go get" is not yet as smart as we want, so let's help
220+
// https://go.dev/issue/43646
221+
preferCache := imports.onlySemVer
222+
var gomodcache string
223+
if preferCache {
224+
var err error
225+
gomodcache, err = getGOMODCACHE(env)
226+
preferCache = err == nil
227+
}
228+
196229
var err error
197230
if dir, err = os.MkdirTemp("", "goeval*"); err != nil {
198231
log.Fatal(err)
@@ -216,15 +249,28 @@ func _main() error {
216249
gogetArgs = append(gogetArgs, "get", "--")
217250
for mod, ver := range imports.modules {
218251
gogetArgs = append(gogetArgs, mod+"@"+ver)
252+
if preferCache {
253+
// Keep preferCache as long as we find modules in the cache
254+
_, err := os.Stat(gomodcache + "/cache/download/" + mod + "/@v/" + ver + ".mod")
255+
preferCache = err == nil
256+
}
219257
}
220258
for _, path := range imports.packages {
221259
if _, seen := imports.modules[path]; !seen {
222260
gogetArgs = append(gogetArgs, path)
223261
}
224262
}
225263

264+
// fmt.Println("preferCache", preferCache)
265+
226266
cmd := exec.Command("go", gogetArgs...)
227-
cmd.Env = env
267+
if preferCache {
268+
// As we found all modules in the cache, tell "go get" to not use the proxy.
269+
// See https://go.dev/issue/43646
270+
cmd.Env = append(env, "GOPROXY=file://"+filepath.ToSlash(gomodcache)+"/cache/download")
271+
} else {
272+
cmd.Env = env
273+
}
228274
cmd.Dir = dir
229275
cmd.Stdin = nil
230276
cmd.Stdout = nil

0 commit comments

Comments
 (0)