github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/cmd/fetch_repo/go_mod_download.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "runtime" 12 "strings" 13 ) 14 15 type GoModDownloadResult struct { 16 Dir string 17 Sum string 18 Error string 19 } 20 21 func findGoPath() string { 22 // Locate the go binary. If GOROOT is set, we'll use that one; otherwise, 23 // we'll use PATH. 24 goPath := "go" 25 if runtime.GOOS == "windows" { 26 goPath += ".exe" 27 } 28 if goroot, ok := os.LookupEnv("GOROOT"); ok { 29 goPath = filepath.Join(goroot, "bin", goPath) 30 } 31 return goPath 32 } 33 34 func runGoModDownload(dl *GoModDownloadResult, dest string, importpath string, version string) error { 35 buf := bytes.NewBuffer(nil) 36 bufErr := bytes.NewBuffer(nil) 37 cmd := exec.Command(findGoPath(), "mod", "download", "-json", "-modcacherw") 38 cmd.Dir = dest 39 40 if version != "" && importpath != "" { 41 cmd.Args = append(cmd.Args, importpath+"@"+version) 42 } 43 44 cmd.Stdout = buf 45 cmd.Stderr = bufErr 46 dlErr := cmd.Run() 47 if dlErr != nil { 48 if _, ok := dlErr.(*exec.ExitError); !ok { 49 if bufErr.Len() > 0 { 50 return fmt.Errorf("go mod download exec error: %s %q: %s, %w", cmd.Path, strings.Join(cmd.Args, " "), bufErr.String(), dlErr) 51 } 52 return fmt.Errorf("go mod download exec error: %s %s: %v", cmd.Path, strings.Join(cmd.Args, " "), dlErr) 53 } 54 } 55 56 // Parse the JSON output. 57 if err := json.Unmarshal(buf.Bytes(), &dl); err != nil { 58 if bufErr.Len() > 0 { 59 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) 60 } 61 return fmt.Errorf("go mod download output format: `%s %s`: parsing JSON: %q error: %w", cmd.Path, strings.Join(cmd.Args, " "), buf.String(), err) 62 } 63 if dl.Error != "" { 64 return errors.Join(errors.New(dl.Error), dlErr) 65 } 66 if dlErr != nil { 67 return dlErr 68 } 69 return nil 70 }