terraform-provider-gitea/vendor/github.com/hashicorp/hc-install/internal/build/go_build.go
Malar Invention 00ebcd295e add vendor
2022-04-03 09:37:16 +05:30

124 lines
3.0 KiB
Go

package build
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"github.com/hashicorp/go-version"
)
var discardLogger = log.New(ioutil.Discard, "", 0)
// GoBuild represents a Go builder (to run "go build")
type GoBuild struct {
Version *version.Version
DetectVendoring bool
pathToRemove string
logger *log.Logger
}
func (gb *GoBuild) SetLogger(logger *log.Logger) {
gb.logger = logger
}
func (gb *GoBuild) log() *log.Logger {
if gb.logger == nil {
return discardLogger
}
return gb.logger
}
// Build runs "go build" within a given repo to produce binaryName in targetDir
func (gb *GoBuild) Build(ctx context.Context, repoDir, targetDir, binaryName string) (string, error) {
goCmd, cleanupFunc, err := gb.ensureRequiredGoVersion(ctx, repoDir)
if err != nil {
return "", err
}
defer cleanupFunc(ctx)
goArgs := []string{"build", "-o", filepath.Join(targetDir, binaryName)}
if gb.DetectVendoring {
vendorDir := filepath.Join(repoDir, "vendor")
if fi, err := os.Stat(vendorDir); err == nil && fi.IsDir() {
goArgs = append(goArgs, "-mod", "vendor")
}
}
gb.log().Printf("executing %s %q in %q", goCmd, goArgs, repoDir)
cmd := exec.CommandContext(ctx, goCmd, goArgs...)
cmd.Dir = repoDir
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("unable to build: %w\n%s", err, out)
}
binPath := filepath.Join(targetDir, binaryName)
gb.pathToRemove = binPath
return binPath, nil
}
func (gb *GoBuild) Remove(ctx context.Context) error {
return os.RemoveAll(gb.pathToRemove)
}
func (gb *GoBuild) ensureRequiredGoVersion(ctx context.Context, repoDir string) (string, CleanupFunc, error) {
cmdName := "go"
noopCleanupFunc := func(context.Context) {}
if gb.Version != nil {
goVersion, err := GetGoVersion(ctx)
if err != nil {
return cmdName, noopCleanupFunc, err
}
if !goVersion.GreaterThanOrEqual(gb.Version) {
// found incompatible version, try downloading the desired one
return gb.installGoVersion(ctx, gb.Version)
}
}
if requiredVersion, ok := guessRequiredGoVersion(repoDir); ok {
goVersion, err := GetGoVersion(ctx)
if err != nil {
return cmdName, noopCleanupFunc, err
}
if !goVersion.GreaterThanOrEqual(requiredVersion) {
// found incompatible version, try downloading the desired one
return gb.installGoVersion(ctx, requiredVersion)
}
}
return cmdName, noopCleanupFunc, nil
}
// CleanupFunc represents a function to be called once Go is no longer needed
// e.g. to remove any version installed temporarily per requirements
type CleanupFunc func(context.Context)
func guessRequiredGoVersion(repoDir string) (*version.Version, bool) {
goEnvFile := filepath.Join(repoDir, ".go-version")
if fi, err := os.Stat(goEnvFile); err == nil && !fi.IsDir() {
b, err := ioutil.ReadFile(goEnvFile)
if err != nil {
return nil, false
}
requiredVersion, err := version.NewVersion(string(bytes.TrimSpace(b)))
if err != nil {
return nil, false
}
return requiredVersion, true
}
return nil, false
}