Skip to content

Commit 14e2060

Browse files
committed
estimate: Use the default GOPATH to cache downloads
This avoids re-downloading the same modules (potentially hundreds of megabytes for moderately sized binaries) over and over. The downside is wasted disk space that the user must manually clear (`go clean -modcache`). Why keeping the downloaded modules is believed to be more useful than automatically deleting them: * It makes offline use possible. * Packaging a complex module with lots of unpackaged dependencies means a long slow process of chipping away at the dependencies. It would be nice to be able to re-run `dh-make-golang estimate` several times to track progress and plan next steps without incurring a huge download cost. * Developing `dh-make-golang estimate` itself involves re-running it over and over to test changes. The interesting modules to test are the complex ones, and those take a while to download. * I believe that `golang-*-dev` package maintainers are already accustomed to running `go clean -modcache`, an occasional necessity with serious Go development. * The modules don't actually need to be fully downloaded and unpacked; only their `go.mod` files are necessary to construct a dependency graph. Changing `dh-make-golang estimate` in a future commit to only download just `go.mod` would address disk usage concerns. It would also mean that re-downloading over and over would be less of a problem, but keeping the `go.mod` files avoids abusing proxy.golang.org and sum.golang.org. This change makes `progressSize` not useful, so `go get`'s stdout and stderr are passed through, and `-x` is passed to `go get` to get some progress indication.
1 parent 7e0ed09 commit 14e2060

File tree

1 file changed

+16
-41
lines changed

1 file changed

+16
-41
lines changed

estimate.go

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ func getSourcesInNew() (map[string]string, error) {
5555
return sourcesInNew, nil
5656
}
5757

58-
func get(gopath, repodir, repo, rev string) error {
58+
func get(repodir, repo, rev string) error {
5959
done := make(chan struct{})
6060
defer close(done)
61-
go progressSize("go get", gopath, done)
6261

6362
// As per https://groups.google.com/forum/#!topic/golang-nuts/N5apfenE4m4,
6463
// the arguments to “go get” are packages, not repositories. Hence, we
@@ -71,43 +70,31 @@ func get(gopath, repodir, repo, rev string) error {
7170
if rev != "" {
7271
packages += "@" + rev
7372
}
74-
cmd := exec.Command("go", "get", "-t", packages)
73+
cmd := exec.Command("go", "get", "-x", "-t", packages)
7574

76-
out := bytes.Buffer{}
7775
cmd.Dir = repodir
78-
cmd.Stderr = &out
79-
cmd.Env = append([]string{
80-
"GOPATH=" + gopath,
81-
}, passthroughEnv()...)
82-
err := cmd.Run()
83-
if err != nil {
84-
fmt.Fprint(os.Stderr, "\n", out.String())
85-
}
86-
return err
76+
cmd.Stderr = os.Stderr
77+
cmd.Stdout = os.Stdout
78+
return cmd.Run()
8779
}
8880

89-
// getModuleDir returns the path of the directory containing a module for the
90-
// given GOPATH and repository dir values.
91-
func getModuleDir(gopath, repodir, module string) (string, error) {
81+
// getModuleDir returns the path of the directory containing a module for the given repository dir.
82+
func getModuleDir(repodir, module string) (string, error) {
9283
cmd := exec.Command("go", "list", "-m", "-f", "{{.Dir}}", module)
9384
cmd.Dir = repodir
9485
cmd.Stderr = os.Stderr
95-
cmd.Env = append([]string{
96-
"GOPATH=" + gopath,
97-
}, passthroughEnv()...)
9886
out, err := cmd.Output()
9987
if err != nil {
10088
return "", fmt.Errorf("go list: args: %v; error: %w", cmd.Args, err)
10189
}
10290
return string(bytes.TrimSpace(out)), nil
10391
}
10492

105-
// getDirectDependencies returns a set of all the direct dependencies of a
106-
// module for the given GOPATH and repository dir values. It first finds the
107-
// directory that contains this module, then uses go list in this directory
108-
// to get its direct dependencies.
109-
func getDirectDependencies(gopath, repodir, module string) (map[string]bool, error) {
110-
dir, err := getModuleDir(gopath, repodir, module)
93+
// getDirectDependencies returns a set of all the direct dependencies of a module for the given
94+
// repository dir. It first finds the directory that contains this module, then uses go list in this
95+
// directory to get its direct dependencies.
96+
func getDirectDependencies(repodir, module string) (map[string]bool, error) {
97+
dir, err := getModuleDir(repodir, module)
11198
if err != nil {
11299
return nil, fmt.Errorf("get module dir: %w", err)
113100
}
@@ -120,9 +107,6 @@ func getDirectDependencies(gopath, repodir, module string) (map[string]bool, err
120107
cmd := exec.Command("go", "list", "-m", "-f", "{{if not .Indirect}}{{.Path}}{{end}}", "all")
121108
cmd.Dir = dir
122109
cmd.Stderr = os.Stderr
123-
cmd.Env = append([]string{
124-
"GOPATH=" + gopath,
125-
}, passthroughEnv()...)
126110
out, err := cmd.Output()
127111
if err != nil {
128112
return nil, fmt.Errorf("go list: args: %v; error: %w", cmd.Args, err)
@@ -207,13 +191,7 @@ func estimate(importpath, revision string) error {
207191
}
208192
}
209193

210-
// construct a separate GOPATH in a temporary directory
211-
gopath, err := os.MkdirTemp("", "dh-make-golang")
212-
if err != nil {
213-
return fmt.Errorf("create temp dir: %w", err)
214-
}
215-
defer removeTemp(gopath)
216-
// second temporary directosy for the repo sources
194+
// temporary directory for the repo sources
217195
repodir, err := os.MkdirTemp("", "dh-make-golang")
218196
if err != nil {
219197
return fmt.Errorf("create temp dir: %w", err)
@@ -226,7 +204,7 @@ func estimate(importpath, revision string) error {
226204
return fmt.Errorf("create dummymod: %w", err)
227205
}
228206

229-
if err := get(gopath, repodir, importpath, revision); err != nil {
207+
if err := get(repodir, importpath, revision); err != nil {
230208
return fmt.Errorf("go get: %w", err)
231209
}
232210

@@ -237,7 +215,7 @@ func estimate(importpath, revision string) error {
237215

238216
if found {
239217
// Fetch un-vendored dependencies
240-
if err := get(gopath, repodir, importpath, revision); err != nil {
218+
if err := get(repodir, importpath, revision); err != nil {
241219
return fmt.Errorf("fetch un-vendored: go get: %w", err)
242220
}
243221
}
@@ -246,16 +224,13 @@ func estimate(importpath, revision string) error {
246224
cmd := exec.Command("go", "mod", "graph")
247225
cmd.Dir = repodir
248226
cmd.Stderr = os.Stderr
249-
cmd.Env = append([]string{
250-
"GOPATH=" + gopath,
251-
}, passthroughEnv()...)
252227
out, err := cmd.Output()
253228
if err != nil {
254229
return fmt.Errorf("go mod graph: args: %v; error: %w", cmd.Args, err)
255230
}
256231

257232
// Get direct dependencies, to filter out indirect ones from go mod graph output
258-
directDeps, err := getDirectDependencies(gopath, repodir, importpath)
233+
directDeps, err := getDirectDependencies(repodir, importpath)
259234
if err != nil {
260235
return fmt.Errorf("get direct dependencies: %w", err)
261236
}

0 commit comments

Comments
 (0)