diff options
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter/get_git.go')
-rw-r--r-- | vendor/github.com/hashicorp/go-getter/get_git.go | 81 |
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 @@ | |||
1 | package getter | 1 | package getter |
2 | 2 | ||
3 | import ( | 3 | import ( |
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. |
20 | type GitGetter struct{} | 23 | type GitGetter struct { |
24 | getter | ||
25 | } | ||
21 | 26 | ||
22 | func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) { | 27 | func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) { |
23 | return ClientModeDir, nil | 28 | return ClientModeDir, nil |
24 | } | 29 | } |
25 | 30 | ||
26 | func (g *GitGetter) Get(dst string, u *url.URL) error { | 31 | func (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 | ||
141 | func (g *GitGetter) clone(dst, sshKeyFile string, u *url.URL) error { | 162 | func (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 | ||
147 | func (g *GitGetter) update(dst, sshKeyFile, ref string) error { | 175 | func (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. |
172 | func (g *GitGetter) fetchSubmodules(dst, sshKeyFile string) error { | 205 | func (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 | } |