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  }