]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/go-getter/get_git.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / go-getter / get_git.go
index cb1d02947ab5bef3187171db74567e634fe71d8b..67e8b2f4902f5f9d64d5b3ed644aa44fa9a2c359 100644 (file)
@@ -1,6 +1,7 @@
 package getter
 
 import (
+       "context"
        "encoding/base64"
        "fmt"
        "io/ioutil"
@@ -8,28 +9,43 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "runtime"
+       "strconv"
        "strings"
 
        urlhelper "github.com/hashicorp/go-getter/helper/url"
-       "github.com/hashicorp/go-safetemp"
-       "github.com/hashicorp/go-version"
+       safetemp "github.com/hashicorp/go-safetemp"
+       version "github.com/hashicorp/go-version"
 )
 
 // GitGetter is a Getter implementation that will download a module from
 // a git repository.
-type GitGetter struct{}
+type GitGetter struct {
+       getter
+}
 
 func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) {
        return ClientModeDir, nil
 }
 
 func (g *GitGetter) Get(dst string, u *url.URL) error {
+       ctx := g.Context()
        if _, err := exec.LookPath("git"); err != nil {
                return fmt.Errorf("git must be available and on the PATH")
        }
 
+       // The port number must be parseable as an integer. If not, the user
+       // was probably trying to use a scp-style address, in which case the
+       // ssh:// prefix must be removed to indicate that.
+       if portStr := u.Port(); portStr != "" {
+               if _, err := strconv.ParseUint(portStr, 10, 16); err != nil {
+                       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)
+               }
+       }
+
        // Extract some query parameters we use
        var ref, sshKey string
+       var depth int
        q := u.Query()
        if len(q) > 0 {
                ref = q.Get("ref")
@@ -38,6 +54,11 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
                sshKey = q.Get("sshkey")
                q.Del("sshkey")
 
+               if n, err := strconv.Atoi(q.Get("depth")); err == nil {
+                       depth = n
+               }
+               q.Del("depth")
+
                // Copy the URL
                var newU url.URL = *u
                u = &newU
@@ -84,9 +105,9 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
                return err
        }
        if err == nil {
-               err = g.update(dst, sshKeyFile, ref)
+               err = g.update(ctx, dst, sshKeyFile, ref, depth)
        } else {
-               err = g.clone(dst, sshKeyFile, u)
+               err = g.clone(ctx, dst, sshKeyFile, u, depth)
        }
        if err != nil {
                return err
@@ -100,7 +121,7 @@ func (g *GitGetter) Get(dst string, u *url.URL) error {
        }
 
        // Lastly, download any/all submodules.
-       return g.fetchSubmodules(dst, sshKeyFile)
+       return g.fetchSubmodules(ctx, dst, sshKeyFile, depth)
 }
 
 // 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 {
        return getRunCommand(cmd)
 }
 
-func (g *GitGetter) clone(dst, sshKeyFile string, u *url.URL) error {
-       cmd := exec.Command("git", "clone", u.String(), dst)
+func (g *GitGetter) clone(ctx context.Context, dst, sshKeyFile string, u *url.URL, depth int) error {
+       args := []string{"clone"}
+
+       if depth > 0 {
+               args = append(args, "--depth", strconv.Itoa(depth))
+       }
+
+       args = append(args, u.String(), dst)
+       cmd := exec.CommandContext(ctx, "git", args...)
        setupGitEnv(cmd, sshKeyFile)
        return getRunCommand(cmd)
 }
 
-func (g *GitGetter) update(dst, sshKeyFile, ref string) error {
+func (g *GitGetter) update(ctx context.Context, dst, sshKeyFile, ref string, depth int) error {
        // Determine if we're a branch. If we're NOT a branch, then we just
        // switch to master prior to checking out
-       cmd := exec.Command("git", "show-ref", "-q", "--verify", "refs/heads/"+ref)
+       cmd := exec.CommandContext(ctx, "git", "show-ref", "-q", "--verify", "refs/heads/"+ref)
        cmd.Dir = dst
 
        if getRunCommand(cmd) != nil {
@@ -162,15 +190,24 @@ func (g *GitGetter) update(dst, sshKeyFile, ref string) error {
                return err
        }
 
-       cmd = exec.Command("git", "pull", "--ff-only")
+       if depth > 0 {
+               cmd = exec.Command("git", "pull", "--depth", strconv.Itoa(depth), "--ff-only")
+       } else {
+               cmd = exec.Command("git", "pull", "--ff-only")
+       }
+
        cmd.Dir = dst
        setupGitEnv(cmd, sshKeyFile)
        return getRunCommand(cmd)
 }
 
 // fetchSubmodules downloads any configured submodules recursively.
-func (g *GitGetter) fetchSubmodules(dst, sshKeyFile string) error {
-       cmd := exec.Command("git", "submodule", "update", "--init", "--recursive")
+func (g *GitGetter) fetchSubmodules(ctx context.Context, dst, sshKeyFile string, depth int) error {
+       args := []string{"submodule", "update", "--init", "--recursive"}
+       if depth > 0 {
+               args = append(args, "--depth", strconv.Itoa(depth))
+       }
+       cmd := exec.CommandContext(ctx, "git", args...)
        cmd.Dir = dst
        setupGitEnv(cmd, sshKeyFile)
        return getRunCommand(cmd)
@@ -187,7 +224,7 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
        // with versions of Go < 1.9.
        env := os.Environ()
        for i, v := range env {
-               if strings.HasPrefix(v, gitSSHCommand) {
+               if strings.HasPrefix(v, gitSSHCommand) && len(v) > len(gitSSHCommand) {
                        sshCmd = []string{v}
 
                        env[i], env[len(env)-1] = env[len(env)-1], env[i]
@@ -202,6 +239,9 @@ func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
 
        if sshKeyFile != "" {
                // We have an SSH key temp file configured, tell ssh about this.
+               if runtime.GOOS == "windows" {
+                       sshKeyFile = strings.Replace(sshKeyFile, `\`, `/`, -1)
+               }
                sshCmd = append(sshCmd, "-i", sshKeyFile)
        }
 
@@ -224,11 +264,20 @@ func checkGitVersion(min string) error {
        }
 
        fields := strings.Fields(string(out))
-       if len(fields) != 3 {
+       if len(fields) < 3 {
                return fmt.Errorf("Unexpected 'git version' output: %q", string(out))
        }
+       v := fields[2]
+       if runtime.GOOS == "windows" && strings.Contains(v, ".windows.") {
+               // on windows, git version will return for example:
+               // git version 2.20.1.windows.1
+               // Which does not follow the semantic versionning specs
+               // https://semver.org. We remove that part in order for
+               // go-version to not error.
+               v = v[:strings.Index(v, ".windows.")]
+       }
 
-       have, err := version.NewVersion(fields[2])
+       have, err := version.NewVersion(v)
        if err != nil {
                return err
        }