diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 3453c9d4d0d6..def3b54650ea 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -633,11 +633,11 @@ }, { "ImportPath": "github.com/hashicorp/go-getter", - "Rev": "848242c76c346ef0aeb34787753b068f5f6f92fe" + "Rev": "2822987a64e0df1236ac29dd277ddf79f4871f9a" }, { "ImportPath": "github.com/hashicorp/go-getter/helper/url", - "Rev": "848242c76c346ef0aeb34787753b068f5f6f92fe" + "Rev": "2822987a64e0df1236ac29dd277ddf79f4871f9a" }, { "ImportPath": "github.com/hashicorp/go-multierror", diff --git a/vendor/github.com/hashicorp/go-getter/README.md b/vendor/github.com/hashicorp/go-getter/README.md index c3cf4c226995..d7f5cc3f7d2a 100644 --- a/vendor/github.com/hashicorp/go-getter/README.md +++ b/vendor/github.com/hashicorp/go-getter/README.md @@ -1,10 +1,12 @@ # go-getter [![Build Status](http://img.shields.io/travis/hashicorp/go-getter.svg?style=flat-square)][travis] +[![Build status](https://ci.appveyor.com/api/projects/status/ulq3qr43n62croyq/branch/master?svg=true)][appveyor] [![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] [travis]: http://travis-ci.org/hashicorp/go-getter [godocs]: http://godoc.org/github.com/hashicorp/go-getter +[appveyor]: https://ci.appveyor.com/project/hashicorp/go-getter/branch/master go-getter is a library for Go (golang) for downloading files or directories from various sources using a URL as the primary form of input. @@ -34,9 +36,21 @@ Installation can be done with a normal `go get`: $ go get github.com/hashicorp/go-getter ``` +go-getter also has a command you can use to test URL strings: + +``` +$ go install github.com/hashicorp/go-getter/cmd/go-getter +... + +$ go-getter github.com/foo/bar ./foo +... +``` + +The command is useful for verifying URL structures. + ## URL Format -go-getter uses a single string URL as input to downlaod from a variety of +go-getter uses a single string URL as input to download from a variety of protocols. go-getter has various "tricks" with this URL to do certain things. This section documents the URL format. diff --git a/vendor/github.com/hashicorp/go-getter/appveyor.yml b/vendor/github.com/hashicorp/go-getter/appveyor.yml new file mode 100644 index 000000000000..159dad4dc25a --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/appveyor.yml @@ -0,0 +1,16 @@ +version: "build-{branch}-{build}" +image: Visual Studio 2015 +clone_folder: c:\gopath\github.com\hashicorp\go-getter +environment: + GOPATH: c:\gopath +install: +- cmd: >- + echo %Path% + + go version + + go env + + go get -d -v -t ./... +build_script: +- cmd: go test -v ./... diff --git a/vendor/github.com/hashicorp/go-getter/client.go b/vendor/github.com/hashicorp/go-getter/client.go index 0622b324c40e..5a039dbacb67 100644 --- a/vendor/github.com/hashicorp/go-getter/client.go +++ b/vendor/github.com/hashicorp/go-getter/client.go @@ -38,11 +38,9 @@ type Client struct { Dst string Pwd string - // Dir, if true, tells the Client it is downloading a directory (versus - // a single file). This distinction is necessary since filenames and - // directory names follow the same format so disambiguating is impossible - // without knowing ahead of time. - Dir bool + // Mode is the method of download the client will use. See ClientMode + // for documentation. + Mode ClientMode // Detectors is the list of detectors that are tried on the source. // If this is nil, then the default Detectors will be used. @@ -55,12 +53,27 @@ type Client struct { // Getters is the map of protocols supported by this client. If this // is nil, then the default Getters variable will be used. Getters map[string]Getter + + // Dir, if true, tells the Client it is downloading a directory (versus + // a single file). This distinction is necessary since filenames and + // directory names follow the same format so disambiguating is impossible + // without knowing ahead of time. + // + // WARNING: deprecated. If Mode is set, that will take precedence. + Dir bool } // Get downloads the configured source to the destination. func (c *Client) Get() error { // Store this locally since there are cases we swap this - dir := c.Dir + mode := c.Mode + if mode == ClientModeInvalid { + if c.Dir { + mode = ClientModeDir + } else { + mode = ClientModeFile + } + } // Default decompressor value decompressors := c.Decompressors @@ -166,9 +179,9 @@ func (c *Client) Get() error { // Swap the download directory to be our temporary path and // store the old values. decompressDst = dst - decompressDir = dir + decompressDir = mode != ClientModeFile dst = filepath.Join(td, "archive") - dir = false + mode = ClientModeFile } // Determine if we have a checksum @@ -179,13 +192,6 @@ func (c *Client) Get() error { q.Del("checksum") u.RawQuery = q.Encode() - // If we're getting a directory, then this is an error. You cannot - // checksum a directory. TODO: test - if dir { - return fmt.Errorf( - "checksum cannot be specified for directory download") - } - // Determine the checksum hash type checksumType := "" idx := strings.Index(v, ":") @@ -216,9 +222,18 @@ func (c *Client) Get() error { checksumValue = b } + // For now, any means file. In the future, we'll ask the getter + // what it thinks it is. + if mode == ClientModeAny { + mode = ClientModeFile + + // Destination is the base name of the URL path + dst = filepath.Join(dst, filepath.Base(u.Path)) + } + // If we're not downloading a directory, then just download the file // and return. - if !dir { + if mode == ClientModeFile { err := g.GetFile(dst, u) if err != nil { return err @@ -240,13 +255,17 @@ func (c *Client) Get() error { // Swap the information back dst = decompressDst - dir = decompressDir + if decompressDir { + mode = ClientModeAny + } else { + mode = ClientModeFile + } } // We check the dir value again because it can be switched back // if we were unarchiving. If we're still only Get-ing a file, then // we're done. - if !dir { + if mode == ClientModeFile { return nil } } @@ -256,6 +275,13 @@ func (c *Client) Get() error { // In the case we have a decompressor we don't Get because it was Get // above. if decompressor == nil { + // If we're getting a directory, then this is an error. You cannot + // checksum a directory. TODO: test + if checksumHash != nil { + return fmt.Errorf( + "checksum cannot be specified for directory download") + } + // We're downloading a directory, which might require a bit more work // if we're specifying a subdir. err := g.Get(dst, u) diff --git a/vendor/github.com/hashicorp/go-getter/client_mode.go b/vendor/github.com/hashicorp/go-getter/client_mode.go new file mode 100644 index 000000000000..7f02509a7894 --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/client_mode.go @@ -0,0 +1,24 @@ +package getter + +// ClientMode is the mode that the client operates in. +type ClientMode uint + +const ( + ClientModeInvalid ClientMode = iota + + // ClientModeAny downloads anything it can. In this mode, dst must + // be a directory. If src is a file, it is saved into the directory + // with the basename of the URL. If src is a directory or archive, + // it is unpacked directly into dst. + ClientModeAny + + // ClientModeFile downloads a single file. In this mode, dst must + // be a file path (doesn't have to exist). src must point to a single + // file. It is saved as dst. + ClientModeFile + + // ClientModeDir downloads a directory. In this mode, dst must be + // a directory path (doesn't have to exist). src must point to an + // archive or directory (such as in s3). + ClientModeDir +) diff --git a/vendor/github.com/hashicorp/go-getter/decompress_testing.go b/vendor/github.com/hashicorp/go-getter/decompress_testing.go index 5821ed66ef77..2834e399d559 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress_testing.go +++ b/vendor/github.com/hashicorp/go-getter/decompress_testing.go @@ -92,6 +92,11 @@ func testListDir(t *testing.T, path string) []string { } sub = sub[1:] // Trim the leading path sep. + // If it is a dir, add trailing sep + if info.IsDir() { + sub += "/" + } + result = append(result, sub) return nil }) diff --git a/vendor/github.com/hashicorp/go-getter/decompress_tgz.go b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go index 391bbc0ad9d0..e8b1c31cacd4 100644 --- a/vendor/github.com/hashicorp/go-getter/decompress_tgz.go +++ b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go @@ -60,7 +60,7 @@ func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error { } if hdr.FileInfo().IsDir() { - if dir { + if !dir { return fmt.Errorf("expected a single file: %s", src) } diff --git a/vendor/github.com/hashicorp/go-getter/get.go b/vendor/github.com/hashicorp/go-getter/get.go index cfdabaed6ee5..75d813cdb218 100644 --- a/vendor/github.com/hashicorp/go-getter/get.go +++ b/vendor/github.com/hashicorp/go-getter/get.go @@ -72,6 +72,21 @@ func Get(dst, src string) error { }).Get() } +// GetAny downloads a URL into the given destination. Unlike Get or +// GetFile, both directories and files are supported. +// +// dst must be a directory. If src is a file, it will be downloaded +// into dst with the basename of the URL. If src is a directory or +// archive, it will be unpacked directly into dst. +func GetAny(dst, src string) error { + return (&Client{ + Src: src, + Dst: dst, + Mode: ClientModeAny, + Getters: Getters, + }).Get() +} + // GetFile downloads the file specified by src into the path specified by // dst. func GetFile(dst, src string) error { diff --git a/vendor/github.com/hashicorp/go-getter/get_file.go b/vendor/github.com/hashicorp/go-getter/get_file.go index 9564c9f4872e..341cd0ed8f26 100644 --- a/vendor/github.com/hashicorp/go-getter/get_file.go +++ b/vendor/github.com/hashicorp/go-getter/get_file.go @@ -1,98 +1,8 @@ package getter -import ( - "fmt" - "io" - "net/url" - "os" - "path/filepath" -) - // FileGetter is a Getter implementation that will download a module from // a file scheme. type FileGetter struct { // Copy, if set to true, will copy data instead of using a symlink Copy bool } - -func (g *FileGetter) Get(dst string, u *url.URL) error { - // The source path must exist and be a directory to be usable. - if fi, err := os.Stat(u.Path); err != nil { - return fmt.Errorf("source path error: %s", err) - } else if !fi.IsDir() { - return fmt.Errorf("source path must be a directory") - } - - fi, err := os.Lstat(dst) - if err != nil && !os.IsNotExist(err) { - return err - } - - // If the destination already exists, it must be a symlink - if err == nil { - mode := fi.Mode() - if mode&os.ModeSymlink == 0 { - return fmt.Errorf("destination exists and is not a symlink") - } - - // Remove the destination - if err := os.Remove(dst); err != nil { - return err - } - } - - // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { - return err - } - - return os.Symlink(u.Path, dst) -} - -func (g *FileGetter) GetFile(dst string, u *url.URL) error { - // The source path must exist and be a directory to be usable. - if fi, err := os.Stat(u.Path); err != nil { - return fmt.Errorf("source path error: %s", err) - } else if fi.IsDir() { - return fmt.Errorf("source path must be a file") - } - - _, err := os.Lstat(dst) - if err != nil && !os.IsNotExist(err) { - return err - } - - // If the destination already exists, it must be a symlink - if err == nil { - // Remove the destination - if err := os.Remove(dst); err != nil { - return err - } - } - - // Create all the parent directories - if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { - return err - } - - // If we're not copying, just symlink and we're done - if !g.Copy { - return os.Symlink(u.Path, dst) - } - - // Copy - srcF, err := os.Open(u.Path) - if err != nil { - return err - } - defer srcF.Close() - - dstF, err := os.Create(dst) - if err != nil { - return err - } - defer dstF.Close() - - _, err = io.Copy(dstF, srcF) - return err -} diff --git a/vendor/github.com/hashicorp/go-getter/get_file_unix.go b/vendor/github.com/hashicorp/go-getter/get_file_unix.go new file mode 100644 index 000000000000..c69d34ad3b79 --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/get_file_unix.go @@ -0,0 +1,93 @@ +// +build !windows + +package getter + +import ( + "fmt" + "io" + "net/url" + "os" + "path/filepath" +) + +func (g *FileGetter) Get(dst string, u *url.URL) error { + // The source path must exist and be a directory to be usable. + if fi, err := os.Stat(u.Path); err != nil { + return fmt.Errorf("source path error: %s", err) + } else if !fi.IsDir() { + return fmt.Errorf("source path must be a directory") + } + + fi, err := os.Lstat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + + // If the destination already exists, it must be a symlink + if err == nil { + mode := fi.Mode() + if mode&os.ModeSymlink == 0 { + return fmt.Errorf("destination exists and is not a symlink") + } + + // Remove the destination + if err := os.Remove(dst); err != nil { + return err + } + } + + // Create all the parent directories + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + return err + } + + return os.Symlink(u.Path, dst) +} + +func (g *FileGetter) GetFile(dst string, u *url.URL) error { + // The source path must exist and be a directory to be usable. + if fi, err := os.Stat(u.Path); err != nil { + return fmt.Errorf("source path error: %s", err) + } else if fi.IsDir() { + return fmt.Errorf("source path must be a file") + } + + _, err := os.Lstat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + + // If the destination already exists, it must be a symlink + if err == nil { + // Remove the destination + if err := os.Remove(dst); err != nil { + return err + } + } + + // Create all the parent directories + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + return err + } + + // If we're not copying, just symlink and we're done + if !g.Copy { + return os.Symlink(u.Path, dst) + } + + // Copy + srcF, err := os.Open(u.Path) + if err != nil { + return err + } + defer srcF.Close() + + dstF, err := os.Create(dst) + if err != nil { + return err + } + defer dstF.Close() + + _, err = io.Copy(dstF, srcF) + return err +} diff --git a/vendor/github.com/hashicorp/go-getter/get_file_windows.go b/vendor/github.com/hashicorp/go-getter/get_file_windows.go new file mode 100644 index 000000000000..cc50ae7e1fe2 --- /dev/null +++ b/vendor/github.com/hashicorp/go-getter/get_file_windows.go @@ -0,0 +1,110 @@ +// +build windows + +package getter + +import ( + "fmt" + "io" + "net/url" + "os" + "os/exec" + "path/filepath" + "strings" +) + +func (g *FileGetter) Get(dst string, u *url.URL) error { + // The source path must exist and be a directory to be usable. + if fi, err := os.Stat(u.Path); err != nil { + return fmt.Errorf("source path error: %s", err) + } else if !fi.IsDir() { + return fmt.Errorf("source path must be a directory") + } + + fi, err := os.Lstat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + + // If the destination already exists, it must be a symlink + if err == nil { + mode := fi.Mode() + if mode&os.ModeSymlink == 0 { + return fmt.Errorf("destination exists and is not a symlink") + } + + // Remove the destination + if err := os.Remove(dst); err != nil { + return err + } + } + + // Create all the parent directories + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + return err + } + + sourcePath := toBackslash(u.Path) + + // Use mklink to create a junction point + output, err := exec.Command("cmd", "/c", "mklink", "/J", dst, sourcePath).CombinedOutput() + if err != nil { + return fmt.Errorf("failed to run mklink %v %v: %v %q", dst, sourcePath, err, output) + } + + return nil +} + +func (g *FileGetter) GetFile(dst string, u *url.URL) error { + // The source path must exist and be a directory to be usable. + if fi, err := os.Stat(u.Path); err != nil { + return fmt.Errorf("source path error: %s", err) + } else if fi.IsDir() { + return fmt.Errorf("source path must be a file") + } + + _, err := os.Lstat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + + // If the destination already exists, it must be a symlink + if err == nil { + // Remove the destination + if err := os.Remove(dst); err != nil { + return err + } + } + + // Create all the parent directories + if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil { + return err + } + + // If we're not copying, just symlink and we're done + if !g.Copy { + return os.Symlink(u.Path, dst) + } + + // Copy + srcF, err := os.Open(u.Path) + if err != nil { + return err + } + defer srcF.Close() + + dstF, err := os.Create(dst) + if err != nil { + return err + } + defer dstF.Close() + + _, err = io.Copy(dstF, srcF) + return err +} + +// toBackslash returns the result of replacing each slash character +// in path with a backslash ('\') character. Multiple separators are +// replaced by multiple backslashes. +func toBackslash(path string) string { + return strings.Replace(path, "/", "\\", -1) +} diff --git a/vendor/github.com/hashicorp/go-getter/get_hg.go b/vendor/github.com/hashicorp/go-getter/get_hg.go index eb170d1007db..542bef1f9c82 100644 --- a/vendor/github.com/hashicorp/go-getter/get_hg.go +++ b/vendor/github.com/hashicorp/go-getter/get_hg.go @@ -71,7 +71,12 @@ func (g *HgGetter) GetFile(dst string, u *url.URL) error { // Get the filename, and strip the filename from the URL so we can // just get the repository directly. filename := filepath.Base(u.Path) - u.Path = filepath.Dir(u.Path) + u.Path = filepath.ToSlash(filepath.Dir(u.Path)) + + // If we're on Windows, we need to set the host to "localhost" for hg + if runtime.GOOS == "windows" { + u.Host = "localhost" + } // Get the full repository if err := g.Get(td, u); err != nil {