-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathensure_git.go
More file actions
150 lines (129 loc) · 4.59 KB
/
ensure_git.go
File metadata and controls
150 lines (129 loc) · 4.59 KB
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
import (
"errors"
"github.com/testributor/agent/system_command"
"io/ioutil"
"os/exec"
"regexp"
"runtime"
)
// This function checks if Git is installed. If not it tries to install it.
// It will return an error if unsuccessful.
func EnsureGit(logger Logger) error {
foundGit, err := CheckForGit(logger)
if err != nil {
return err
}
if !foundGit {
logger.Log("I will try to install git.")
switch runtime.GOOS {
case "windows":
return WindowsInstallGit(logger)
case "linux":
return LinuxInstallGit(logger)
case "darwin":
return MacInstallGit(logger)
}
}
return nil
}
// CheckForSuitableGitVersion checks if a suitable Git version (> 2.3) is present on the
// current operating system.
// We need a version greater or equal to 2.3 in order to use the SSH_GIT_COMMAND
// feature. We need this feature to be able to use our custom ssh config file
// when pulling the repo from the VCS (GitHub, Bitbucket, etc).
func CheckForGit(logger Logger) (bool, error) {
logger.Log("Checking if git command is available...")
path, err := exec.LookPath("git")
if err == nil {
logger.Log("Found git executable: " + path)
return true, nil
} else {
logger.Log("Couldn't find git executable")
return false, nil
}
}
func WindowsInstallGit(logger Logger) error {
return errors.New("I don't know how to install Git on Windows. Please install it manually and run the agent again.")
}
func MacInstallGit(logger Logger) error {
return errors.New("I don't know how to install Git on Mac. Please install it manually and run the agent again.")
}
// This function assumes we are on a linux system and tries to find the distro
// type (debian based, fedora based etc). If "git" command is not available,
// it will try to install git using the system's package manager. If that is
// not possible (e.g. permission denied), it will simply return and error.
// This list of commands can be useful: https://git-scm.com/download/linux
func LinuxInstallGit(logger Logger) error {
distribution, _ := DetectLinuxDistro(logger)
distroFuncMap := map[string](func(Logger) error){
"Debian": InstallGitOnDebian,
"Ubuntu": InstallGitOnDebian,
"Arch": InstallGitOnArch,
}
for distro, function := range distroFuncMap {
matched, err := regexp.MatchString(distro, distribution)
if err != nil {
return err
}
if matched {
return function(logger)
}
}
return errors.New("I don't know how to install git on your distribution.\n Please install Git and run the agent again.")
}
// DetectLinuxDistro tryied to find the current linux distribution name using
// lsb_release if present or else guesses a distribution based on the package
// manager found (e.g. apt-get -> Debian). Even if wrong, it will work in most
// cases. E.g. `apt-get install -y git` will work both on Ubuntu and Debian.
func DetectLinuxDistro(logger Logger) (string, error) {
distribution := ""
if _, err := exec.LookPath("lsb_release"); err == nil {
distributorID, err := system_command.Run("lsb_release -i", ioutil.Discard)
if err == nil {
re := regexp.MustCompile(`Distributor ID: (.*)`)
match := re.FindAllStringSubmatch(distributorID.Output, -1)
if match != nil && match[0][1] != "" {
distribution = match[0][1]
logger.Log("We seem to be on " + distribution + ".")
return distribution, nil
} else {
return "", nil
}
} else {
return "", err
}
} else {
logger.Log("Could not determine the Linux distribution.")
// Try blindly with package managers
if _, err := exec.LookPath("apt-get"); err == nil {
logger.Log("Found apt-get. I will assume we are on Debian and see how it goes.")
return "Debian", nil
} else if _, err := exec.LookPath("pacman"); err == nil {
logger.Log("Found apt-get. I will assume we are on Arch and see how it goes.")
return "Arch", nil
} else {
logger.Log("Didn't find a package manager I can use either.")
return "", nil
}
}
return "", nil
}
func InstallGitOnDebian(logger Logger) error {
logger.Log("Trying with apt-get.")
res, err := system_command.Run("apt-get update && apt-get install -y git", logger)
if err == nil && !res.Success {
// Stderr is already written no need to return it.
return errors.New("I wasn't able to install git. Please install it manually and run the agent again.")
}
return err
}
func InstallGitOnArch(logger Logger) error {
logger.Log("Trying with pacman.")
res, err := system_command.Run("pacman -S --noconfirm git", logger)
if err == nil && !res.Success {
// Stderr is already written no need to return it.
return errors.New("I wasn't able to install git. Please install it manually and run the agent again.")
}
return err
}