-
-
Notifications
You must be signed in to change notification settings - Fork 109
/
Copy pathinstaller.go
101 lines (80 loc) · 2.71 KB
/
installer.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
// Package install contains functions necessary for installing and checking
// if the necessary underlying Ruby tools have been properly installed
package install
import (
"fmt"
"log"
"os/exec"
"strings"
goversion "github.com/hashicorp/go-version"
)
// Installer manages the underlying Ruby installation
type Installer struct {
commander commander
}
const (
mockServiceRange = ">= 3.1.0, < 4.0.0"
verifierRange = ">= 1.23.0, < 3.0.0"
brokerRange = ">= 1.18.0, < 2.0.0"
)
var versionMap = map[string]string{
"pact-mock-service": mockServiceRange,
"pact-provider-verifier": verifierRange,
"pact-broker": brokerRange,
}
// NewInstaller creates a new initialised Installer
func NewInstaller() *Installer {
return &Installer{commander: realCommander{}}
}
// CheckInstallation checks installation of all of the tools
func (i *Installer) CheckInstallation() error {
for binary, versionRange := range versionMap {
log.Println("[INFO] checking", binary, "within range", versionRange)
version, err := i.GetVersionForBinary(binary)
if err != nil {
return err
}
if err = i.CheckVersion(binary, version); err != nil {
return err
}
}
return nil
}
// CheckVersion checks installation of a given binary using semver-compatible
// comparisions
func (i *Installer) CheckVersion(binary, version string) error {
log.Println("[DEBUG] checking version for binary", binary, "version", version)
v, err := goversion.NewVersion(version)
if err != nil {
log.Println("[DEBUG] err", err)
return err
}
versionRange, ok := versionMap[binary]
if !ok {
return fmt.Errorf("unable to find version range for binary %s", binary)
}
log.Println("[DEBUG] checking if version", v, "within semver range", versionRange)
constraints, err := goversion.NewConstraint(versionRange)
if constraints.Check(v) {
log.Println("[DEBUG]", v, "satisfies constraints", v, constraints)
return nil
}
return fmt.Errorf("version %s of %s does not match constraint %s", version, binary, versionRange)
}
// GetVersionForBinary gets the version of a given Ruby binary
func (i *Installer) GetVersionForBinary(binary string) (version string, err error) {
log.Println("[DEBUG] running binary", binary)
content, err := i.commander.Output(binary, "version")
elements := strings.Split(strings.TrimSpace(string(content)), "\n")
version = strings.TrimSpace(elements[len(elements)-1])
return version, err
}
// commander wraps the exec package, allowing us
// properly test the file system
type commander interface {
Output(command string, args ...string) ([]byte, error)
}
type realCommander struct{}
func (c realCommander) Output(command string, args ...string) ([]byte, error) {
return exec.Command(command, args...).CombinedOutput()
}