-
Notifications
You must be signed in to change notification settings - Fork 1
/
git_ref.go
103 lines (86 loc) · 2.22 KB
/
git_ref.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package gitref
import (
"context"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
)
type Option struct {
installDir string
repoURL string
ref string
}
func Install(ref, repo, installDir string) *Option {
return &Option{
installDir: installDir,
repoURL: repo,
ref: ref,
}
}
func (opt *Option) ExecPath(ctx context.Context) (string, error) {
installDir, err := ensureInstallDir(opt.installDir)
if err != nil {
return "", err
}
ref := plumbing.ReferenceName(opt.ref)
if opt.ref == "" {
ref = plumbing.ReferenceName("refs/heads/main")
}
repoURL := opt.repoURL
if repoURL == "" {
repoURL = "https://github.com/hashicorp/terraform.git"
}
_, err = git.PlainClone(installDir, false, &git.CloneOptions{
URL: repoURL,
ReferenceName: ref,
Depth: 1,
Tags: git.NoTags,
})
if err != nil {
return "", fmt.Errorf("unable to clone %q: %w", repoURL, err)
}
var binName string
{
// TODO: maybe there is a better way to make sure this filename is available?
// I guess we could locate it in a different dir, or nest the git underneath
// the root tmp dir, etc.
binPattern := "terraform"
if runtime.GOOS == "windows" {
binPattern = "terraform*.exe"
}
binFile, err := ioutil.TempFile(installDir, binPattern)
if err != nil {
return "", fmt.Errorf("unable to create bin file: %w", err)
}
binName = binFile.Name()
binFile.Close()
}
goArgs := []string{"build", "-o", binName}
vendorDir := filepath.Join(installDir, "vendor")
if fi, err := os.Stat(vendorDir); err == nil && fi.IsDir() {
goArgs = append(goArgs, "-mod", "vendor")
}
cmd := exec.CommandContext(ctx, "go", goArgs...)
cmd.Dir = installDir
out, err := cmd.CombinedOutput()
log.Print(string(out))
if err != nil {
return "", fmt.Errorf("unable to build Terraform: %w\n%s", err, out)
}
return binName, nil
}
func ensureInstallDir(installDir string) (string, error) {
if installDir == "" {
return ioutil.TempDir("", "tfexec")
}
if _, err := os.Stat(installDir); err != nil {
return "", fmt.Errorf("could not access directory %s for installing Terraform: %w", installDir, err)
}
return installDir, nil
}