aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/go-getter/get_git.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter/get_git.go')
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_git.go81
1 files changed, 65 insertions, 16 deletions
diff --git a/vendor/github.com/hashicorp/go-getter/get_git.go b/vendor/github.com/hashicorp/go-getter/get_git.go
index cb1d029..67e8b2f 100644
--- a/vendor/github.com/hashicorp/go-getter/get_git.go
+++ b/vendor/github.com/hashicorp/go-getter/get_git.go
@@ -1,6 +1,7 @@
1package getter 1package getter
2 2
3import ( 3import (
4 "context"
4 "encoding/base64" 5 "encoding/base64"
5 "fmt" 6 "fmt"
6 "io/ioutil" 7 "io/ioutil"
@@ -8,28 +9,43 @@ import (
8 "os" 9 "os"
9 "os/exec" 10 "os/exec"
10 "path/filepath" 11 "path/filepath"
12 "runtime"
13 "strconv"
11 "strings" 14 "strings"
12 15
13 urlhelper "github.com/hashicorp/go-getter/helper/url" 16 urlhelper "github.com/hashicorp/go-getter/helper/url"
14 "github.com/hashicorp/go-safetemp" 17 safetemp "github.com/hashicorp/go-safetemp"
15 "github.com/hashicorp/go-version" 18 version "github.com/hashicorp/go-version"
16) 19)
17 20
18// GitGetter is a Getter implementation that will download a module from 21// GitGetter is a Getter implementation that will download a module from
19// a git repository. 22// a git repository.
20type GitGetter struct{} 23type GitGetter struct {
24 getter
25}
21 26
22func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) { 27func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) {
23 return ClientModeDir, nil 28 return ClientModeDir, nil
24} 29}
25 30
26func (g *GitGetter) Get(dst string, u *url.URL) error { 31func (g *GitGetter) Get(dst string, u *url.URL) error {
32 ctx := g.Context()
27 if _, err := exec.LookPath("git"); err != nil { 33 if _, err := exec.LookPath("git"); err != nil {
28 return fmt.Errorf("git must be available and on the PATH") 34 return fmt.Errorf("git must be available and on the PATH")
29 } 35 }
30 36
37 // The port number must be parseable as an integer. If not, the user
38 // was probably trying to use a scp-style address, in which case the
39 // ssh:// prefix must be removed to indicate that.
40 if portStr := u.Port(); portStr != "" {
41 if _, err := strconv.ParseUint(portStr, 10, 16); err != nil {
42 return fmt.Errorf("invalid port number %q; if using the \"scp-like\" git address scheme where a colon introduces the path instead, remove the ssh:// portion and use just the git:: prefix", portStr)
43 }
44 }
45
31 // Extract some query parameters we use 46 // Extract some query parameters we use
32 var ref, sshKey string 47 var ref, sshKey string
48 var depth int
33 q := u.Query() 49 q := u.Query()
34 if len(q) > 0 { 50 if len(q) > 0 {
35 ref = q.Get("ref") 51 ref = q.Get("ref")
@@ -38,6 +54,11 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
38 sshKey = q.Get("sshkey") 54 sshKey = q.Get("sshkey")
39 q.Del("sshkey") 55 q.Del("sshkey")
40 56
57 if n, err := strconv.Atoi(q.Get("depth")); err == nil {
58 depth = n
59 }
60 q.Del("depth")
61
41 // Copy the URL 62 // Copy the URL
42 var newU url.URL = *u 63 var newU url.URL = *u
43 u = &newU 64 u = &newU
@@ -84,9 +105,9 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
84 return err 105 return err
85 } 106 }
86 if err == nil { 107 if err == nil {
87 err = g.update(dst, sshKeyFile, ref) 108 err = g.update(ctx, dst, sshKeyFile, ref, depth)
88 } else { 109 } else {
89 err = g.clone(dst, sshKeyFile, u) 110 err = g.clone(ctx, dst, sshKeyFile, u, depth)
90 } 111 }
91 if err != nil { 112 if err != nil {
92 return err 113 return err
@@ -100,7 +121,7 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
100 } 121 }
101 122
102 // Lastly, download any/all submodules. 123 // Lastly, download any/all submodules.
103 return g.fetchSubmodules(dst, sshKeyFile) 124 return g.fetchSubmodules(ctx, dst, sshKeyFile, depth)
104} 125}
105 126
106// GetFile for Git doesn't support updating at this time. It will download 127// GetFile for Git doesn't support updating at this time. It will download
@@ -138,16 +159,23 @@ func (g *GitGetter) checkout(dst string, ref string) error {
138 return getRunCommand(cmd) 159 return getRunCommand(cmd)
139} 160}
140 161
141func (g *GitGetter) clone(dst, sshKeyFile string, u *url.URL) error { 162func (g *GitGetter) clone(ctx context.Context, dst, sshKeyFile string, u *url.URL, depth int) error {
142 cmd := exec.Command("git", "clone", u.String(), dst) 163 args := []string{"clone"}
164
165 if depth > 0 {
166 args = append(args, "--depth", strconv.Itoa(depth))
167 }
168
169 args = append(args, u.String(), dst)
170 cmd := exec.CommandContext(ctx, "git", args...)
143 setupGitEnv(cmd, sshKeyFile) 171 setupGitEnv(cmd, sshKeyFile)
144 return getRunCommand(cmd) 172 return getRunCommand(cmd)
145} 173}
146 174
147func (g *GitGetter) update(dst, sshKeyFile, ref string) error { 175func (g *GitGetter) update(ctx context.Context, dst, sshKeyFile, ref string, depth int) error {
148 // Determine if we're a branch. If we're NOT a branch, then we just 176 // Determine if we're a branch. If we're NOT a branch, then we just
149 // switch to master prior to checking out 177 // switch to master prior to checking out
150 cmd := exec.Command("git", "show-ref", "-q", "--verify", "refs/heads/"+ref) 178 cmd := exec.CommandContext(ctx, "git", "show-ref", "-q", "--verify", "refs/heads/"+ref)
151 cmd.Dir = dst 179 cmd.Dir = dst
152 180
153 if getRunCommand(cmd) != nil { 181 if getRunCommand(cmd) != nil {
@@ -162,15 +190,24 @@ func (g *GitGetter) update(dst, sshKeyFile, ref string) error {
162 return err 190 return err
163 } 191 }
164 192
165 cmd = exec.Command("git", "pull", "--ff-only") 193 if depth > 0 {
194 cmd = exec.Command("git", "pull", "--depth", strconv.Itoa(depth), "--ff-only")
195 } else {
196 cmd = exec.Command("git", "pull", "--ff-only")
197 }
198
166 cmd.Dir = dst 199 cmd.Dir = dst
167 setupGitEnv(cmd, sshKeyFile) 200 setupGitEnv(cmd, sshKeyFile)
168 return getRunCommand(cmd) 201 return getRunCommand(cmd)
169} 202}
170 203
171// fetchSubmodules downloads any configured submodules recursively. 204// fetchSubmodules downloads any configured submodules recursively.
172func (g *GitGetter) fetchSubmodules(dst, sshKeyFile string) error { 205func (g *GitGetter) fetchSubmodules(ctx context.Context, dst, sshKeyFile string, depth int) error {
173 cmd := exec.Command("git", "submodule", "update", "--init", "--recursive") 206 args := []string{"submodule", "update", "--init", "--recursive"}
207 if depth > 0 {
208 args = append(args, "--depth", strconv.Itoa(depth))
209 }
210 cmd := exec.CommandContext(ctx, "git", args...)
174 cmd.Dir = dst 211 cmd.Dir = dst
175 setupGitEnv(cmd, sshKeyFile) 212 setupGitEnv(cmd, sshKeyFile)
176 return getRunCommand(cmd) 213 return getRunCommand(cmd)
@@ -187,7 +224,7 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
187 // with versions of Go < 1.9. 224 // with versions of Go < 1.9.
188 env := os.Environ() 225 env := os.Environ()
189 for i, v := range env { 226 for i, v := range env {
190 if strings.HasPrefix(v, gitSSHCommand) { 227 if strings.HasPrefix(v, gitSSHCommand) && len(v) > len(gitSSHCommand) {
191 sshCmd = []string{v} 228 sshCmd = []string{v}
192 229
193 env[i], env[len(env)-1] = env[len(env)-1], env[i] 230 env[i], env[len(env)-1] = env[len(env)-1], env[i]
@@ -202,6 +239,9 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
202 239
203 if sshKeyFile != "" { 240 if sshKeyFile != "" {
204 // We have an SSH key temp file configured, tell ssh about this. 241 // We have an SSH key temp file configured, tell ssh about this.
242 if runtime.GOOS == "windows" {
243 sshKeyFile = strings.Replace(sshKeyFile, `\`, `/`, -1)
244 }
205 sshCmd = append(sshCmd, "-i", sshKeyFile) 245 sshCmd = append(sshCmd, "-i", sshKeyFile)
206 } 246 }
207 247
@@ -224,11 +264,20 @@ func checkGitVersion(min string) error {
224 } 264 }
225 265
226 fields := strings.Fields(string(out)) 266 fields := strings.Fields(string(out))
227 if len(fields) != 3 { 267 if len(fields) < 3 {
228 return fmt.Errorf("Unexpected 'git version' output: %q", string(out)) 268 return fmt.Errorf("Unexpected 'git version' output: %q", string(out))
229 } 269 }
270 v := fields[2]
271 if runtime.GOOS == "windows" && strings.Contains(v, ".windows.") {
272 // on windows, git version will return for example:
273 // git version 2.20.1.windows.1
274 // Which does not follow the semantic versionning specs
275 // https://semver.org. We remove that part in order for
276 // go-version to not error.
277 v = v[:strings.Index(v, ".windows.")]
278 }
230 279
231 have, err := version.NewVersion(fields[2]) 280 have, err := version.NewVersion(v)
232 if err != nil { 281 if err != nil {
233 return err 282 return err
234 } 283 }