blob: 4e71fad6f002d1d6723a108409fc43c3ffa2d91e [file] [log] [blame]
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
type GoModDownloadResult struct {
Dir string
Sum string
Error string
}
func findGoPath() string {
// Locate the go binary. If GOROOT is set, we'll use that one; otherwise,
// we'll use PATH.
goPath := "go"
if runtime.GOOS == "windows" {
goPath += ".exe"
}
if goroot, ok := os.LookupEnv("GOROOT"); ok {
goPath = filepath.Join(goroot, "bin", goPath)
}
return goPath
}
func runGoModDownload(dl *GoModDownloadResult, dest string, importpath string, version string) error {
buf := bytes.NewBuffer(nil)
bufErr := bytes.NewBuffer(nil)
cmd := exec.Command(findGoPath(), "mod", "download", "-json", "-modcacherw")
cmd.Dir = dest
if version != "" && importpath != "" {
cmd.Args = append(cmd.Args, importpath+"@"+version)
}
cmd.Stdout = buf
cmd.Stderr = bufErr
dlErr := cmd.Run()
if dlErr != nil {
if _, ok := dlErr.(*exec.ExitError); !ok {
if bufErr.Len() > 0 {
return fmt.Errorf("go mod download exec error: %s %q: %s, %w", cmd.Path, strings.Join(cmd.Args, " "), bufErr.String(), dlErr)
}
return fmt.Errorf("go mod download exec error: %s %s: %v", cmd.Path, strings.Join(cmd.Args, " "), dlErr)
}
}
// Parse the JSON output.
if err := json.Unmarshal(buf.Bytes(), &dl); err != nil {
if bufErr.Len() > 0 {
return fmt.Errorf("go mod download output format: `%s %s`: parsing JSON: %q stderr: %q error: %w", cmd.Path, strings.Join(cmd.Args, " "), buf.String(), bufErr.String(), err)
}
return fmt.Errorf("go mod download output format: `%s %s`: parsing JSON: %q error: %w", cmd.Path, strings.Join(cmd.Args, " "), buf.String(), err)
}
if dl.Error != "" {
return Join(errors.New(dl.Error), dlErr)
}
if dlErr != nil {
return dlErr
}
return nil
}