installGoPackage installs a Go package using "go install".
(ctx context.Context, pkg *Package, version string)
| 29 | |
| 30 | // installGoPackage installs a Go package using "go install". |
| 31 | func installGoPackage(ctx context.Context, pkg *Package, version string) (string, error) { |
| 32 | binaryName := pkg.BinaryName() |
| 33 | if binaryName == "" { |
| 34 | return "", fmt.Errorf("cannot determine binary name for %s/%s", pkg.RepoOwner, pkg.RepoName) |
| 35 | } |
| 36 | |
| 37 | binDir := BinDir() |
| 38 | binaryPath := filepath.Join(binDir, binaryName) |
| 39 | |
| 40 | // Already installed? |
| 41 | if _, err := os.Stat(binaryPath); err == nil { |
| 42 | return binaryPath, nil |
| 43 | } |
| 44 | |
| 45 | // Determine the Go module path. |
| 46 | goPath := pkg.GoInstallPath |
| 47 | if goPath == "" { |
| 48 | if pkg.RepoOwner == "golang" { |
| 49 | goPath = fmt.Sprintf("golang.org/x/%s/%s", pkg.RepoName, binaryName) |
| 50 | } else { |
| 51 | goPath = fmt.Sprintf("github.com/%s/%s", pkg.RepoOwner, pkg.RepoName) |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | // Strip multi-module tag prefix: "gopls/v0.21.1" → "v0.21.1". |
| 56 | installVersion := version |
| 57 | if idx := strings.LastIndex(version, "/"); idx >= 0 { |
| 58 | installVersion = version[idx+1:] |
| 59 | } |
| 60 | if !strings.HasPrefix(installVersion, "v") && installVersion != "latest" { |
| 61 | installVersion = "v" + installVersion |
| 62 | } |
| 63 | |
| 64 | if err := os.MkdirAll(binDir, 0o755); err != nil { //nolint:gosec // bin dir holds installed tool binaries; needs traversal/exec |
| 65 | return "", fmt.Errorf("creating bin directory: %w", err) |
| 66 | } |
| 67 | |
| 68 | installArg := goPath + "@" + installVersion |
| 69 | cmd := exec.CommandContext(ctx, "go", "install", installArg) |
| 70 | cmd.Env = append(os.Environ(), "GOBIN="+binDir) |
| 71 | cmd.Stdout = os.Stderr |
| 72 | cmd.Stderr = os.Stderr |
| 73 | |
| 74 | if err := cmd.Run(); err != nil { |
| 75 | return "", fmt.Errorf("go install %s: %w", installArg, err) |
| 76 | } |
| 77 | |
| 78 | if _, err := os.Stat(binaryPath); err != nil { |
| 79 | return "", fmt.Errorf("binary %q not found after go install %s", binaryName, installArg) |
| 80 | } |
| 81 | |
| 82 | return binaryPath, nil |
| 83 | } |
| 84 | |
| 85 | // installGitHubRelease downloads and installs a package from GitHub releases. |
| 86 | func (r *Registry) installGitHubRelease(ctx context.Context, pkg *Package, version string) (string, error) { |
no test coverage detected