aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/go-getter/client.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter/client.go')
-rw-r--r--vendor/github.com/hashicorp/go-getter/client.go140
1 files changed, 44 insertions, 96 deletions
diff --git a/vendor/github.com/hashicorp/go-getter/client.go b/vendor/github.com/hashicorp/go-getter/client.go
index 300301c..007a78b 100644
--- a/vendor/github.com/hashicorp/go-getter/client.go
+++ b/vendor/github.com/hashicorp/go-getter/client.go
@@ -1,15 +1,8 @@
1package getter 1package getter
2 2
3import ( 3import (
4 "bytes" 4 "context"
5 "crypto/md5"
6 "crypto/sha1"
7 "crypto/sha256"
8 "crypto/sha512"
9 "encoding/hex"
10 "fmt" 5 "fmt"
11 "hash"
12 "io"
13 "io/ioutil" 6 "io/ioutil"
14 "os" 7 "os"
15 "path/filepath" 8 "path/filepath"
@@ -17,7 +10,7 @@ import (
17 "strings" 10 "strings"
18 11
19 urlhelper "github.com/hashicorp/go-getter/helper/url" 12 urlhelper "github.com/hashicorp/go-getter/helper/url"
20 "github.com/hashicorp/go-safetemp" 13 safetemp "github.com/hashicorp/go-safetemp"
21) 14)
22 15
23// Client is a client for downloading things. 16// Client is a client for downloading things.
@@ -26,6 +19,9 @@ import (
26// Using a client directly allows more fine-grained control over how downloading 19// Using a client directly allows more fine-grained control over how downloading
27// is done, as well as customizing the protocols supported. 20// is done, as well as customizing the protocols supported.
28type Client struct { 21type Client struct {
22 // Ctx for cancellation
23 Ctx context.Context
24
29 // Src is the source URL to get. 25 // Src is the source URL to get.
30 // 26 //
31 // Dst is the path to save the downloaded thing as. If Dir is set to 27 // Dst is the path to save the downloaded thing as. If Dir is set to
@@ -62,10 +58,20 @@ type Client struct {
62 // 58 //
63 // WARNING: deprecated. If Mode is set, that will take precedence. 59 // WARNING: deprecated. If Mode is set, that will take precedence.
64 Dir bool 60 Dir bool
61
62 // ProgressListener allows to track file downloads.
63 // By default a no op progress listener is used.
64 ProgressListener ProgressTracker
65
66 Options []ClientOption
65} 67}
66 68
67// Get downloads the configured source to the destination. 69// Get downloads the configured source to the destination.
68func (c *Client) Get() error { 70func (c *Client) Get() error {
71 if err := c.Configure(c.Options...); err != nil {
72 return err
73 }
74
69 // Store this locally since there are cases we swap this 75 // Store this locally since there are cases we swap this
70 mode := c.Mode 76 mode := c.Mode
71 if mode == ClientModeInvalid { 77 if mode == ClientModeInvalid {
@@ -76,18 +82,7 @@ func (c *Client) Get() error {
76 } 82 }
77 } 83 }
78 84
79 // Default decompressor value 85 src, err := Detect(c.Src, c.Pwd, c.Detectors)
80 decompressors := c.Decompressors
81 if decompressors == nil {
82 decompressors = Decompressors
83 }
84
85 // Detect the URL. This is safe if it is already detected.
86 detectors := c.Detectors
87 if detectors == nil {
88 detectors = Detectors
89 }
90 src, err := Detect(c.Src, c.Pwd, detectors)
91 if err != nil { 86 if err != nil {
92 return err 87 return err
93 } 88 }
@@ -119,12 +114,7 @@ func (c *Client) Get() error {
119 force = u.Scheme 114 force = u.Scheme
120 } 115 }
121 116
122 getters := c.Getters 117 g, ok := c.Getters[force]
123 if getters == nil {
124 getters = Getters
125 }
126
127 g, ok := getters[force]
128 if !ok { 118 if !ok {
129 return fmt.Errorf( 119 return fmt.Errorf(
130 "download not supported for scheme '%s'", force) 120 "download not supported for scheme '%s'", force)
@@ -150,7 +140,7 @@ func (c *Client) Get() error {
150 if archiveV == "" { 140 if archiveV == "" {
151 // We don't appear to... but is it part of the filename? 141 // We don't appear to... but is it part of the filename?
152 matchingLen := 0 142 matchingLen := 0
153 for k, _ := range decompressors { 143 for k := range c.Decompressors {
154 if strings.HasSuffix(u.Path, "."+k) && len(k) > matchingLen { 144 if strings.HasSuffix(u.Path, "."+k) && len(k) > matchingLen {
155 archiveV = k 145 archiveV = k
156 matchingLen = len(k) 146 matchingLen = len(k)
@@ -163,7 +153,7 @@ func (c *Client) Get() error {
163 // real path. 153 // real path.
164 var decompressDst string 154 var decompressDst string
165 var decompressDir bool 155 var decompressDir bool
166 decompressor := decompressors[archiveV] 156 decompressor := c.Decompressors[archiveV]
167 if decompressor != nil { 157 if decompressor != nil {
168 // Create a temporary directory to store our archive. We delete 158 // Create a temporary directory to store our archive. We delete
169 // this at the end of everything. 159 // this at the end of everything.
@@ -182,44 +172,16 @@ func (c *Client) Get() error {
182 mode = ClientModeFile 172 mode = ClientModeFile
183 } 173 }
184 174
185 // Determine if we have a checksum 175 // Determine checksum if we have one
186 var checksumHash hash.Hash 176 checksum, err := c.extractChecksum(u)
187 var checksumValue []byte 177 if err != nil {
188 if v := q.Get("checksum"); v != "" { 178 return fmt.Errorf("invalid checksum: %s", err)
189 // Delete the query parameter if we have it.
190 q.Del("checksum")
191 u.RawQuery = q.Encode()
192
193 // Determine the checksum hash type
194 checksumType := ""
195 idx := strings.Index(v, ":")
196 if idx > -1 {
197 checksumType = v[:idx]
198 }
199 switch checksumType {
200 case "md5":
201 checksumHash = md5.New()
202 case "sha1":
203 checksumHash = sha1.New()
204 case "sha256":
205 checksumHash = sha256.New()
206 case "sha512":
207 checksumHash = sha512.New()
208 default:
209 return fmt.Errorf(
210 "unsupported checksum type: %s", checksumType)
211 }
212
213 // Get the remainder of the value and parse it into bytes
214 b, err := hex.DecodeString(v[idx+1:])
215 if err != nil {
216 return fmt.Errorf("invalid checksum: %s", err)
217 }
218
219 // Set our value
220 checksumValue = b
221 } 179 }
222 180
181 // Delete the query parameter if we have it.
182 q.Del("checksum")
183 u.RawQuery = q.Encode()
184
223 if mode == ClientModeAny { 185 if mode == ClientModeAny {
224 // Ask the getter which client mode to use 186 // Ask the getter which client mode to use
225 mode, err = g.ClientMode(u) 187 mode, err = g.ClientMode(u)
@@ -248,15 +210,24 @@ func (c *Client) Get() error {
248 // If we're not downloading a directory, then just download the file 210 // If we're not downloading a directory, then just download the file
249 // and return. 211 // and return.
250 if mode == ClientModeFile { 212 if mode == ClientModeFile {
251 err := g.GetFile(dst, u) 213 getFile := true
252 if err != nil { 214 if checksum != nil {
253 return err 215 if err := checksum.checksum(dst); err == nil {
216 // don't get the file if the checksum of dst is correct
217 getFile = false
218 }
254 } 219 }
255 220 if getFile {
256 if checksumHash != nil { 221 err := g.GetFile(dst, u)
257 if err := checksum(dst, checksumHash, checksumValue); err != nil { 222 if err != nil {
258 return err 223 return err
259 } 224 }
225
226 if checksum != nil {
227 if err := checksum.checksum(dst); err != nil {
228 return err
229 }
230 }
260 } 231 }
261 232
262 if decompressor != nil { 233 if decompressor != nil {
@@ -291,7 +262,7 @@ func (c *Client) Get() error {
291 if decompressor == nil { 262 if decompressor == nil {
292 // If we're getting a directory, then this is an error. You cannot 263 // If we're getting a directory, then this is an error. You cannot
293 // checksum a directory. TODO: test 264 // checksum a directory. TODO: test
294 if checksumHash != nil { 265 if checksum != nil {
295 return fmt.Errorf( 266 return fmt.Errorf(
296 "checksum cannot be specified for directory download") 267 "checksum cannot be specified for directory download")
297 } 268 }
@@ -320,30 +291,7 @@ func (c *Client) Get() error {
320 return err 291 return err
321 } 292 }
322 293
323 return copyDir(realDst, subDir, false) 294 return copyDir(c.Ctx, realDst, subDir, false)
324 }
325
326 return nil
327}
328
329// checksum is a simple method to compute the checksum of a source file
330// and compare it to the given expected value.
331func checksum(source string, h hash.Hash, v []byte) error {
332 f, err := os.Open(source)
333 if err != nil {
334 return fmt.Errorf("Failed to open file for checksum: %s", err)
335 }
336 defer f.Close()
337
338 if _, err := io.Copy(h, f); err != nil {
339 return fmt.Errorf("Failed to hash: %s", err)
340 }
341
342 if actual := h.Sum(nil); !bytes.Equal(actual, v) {
343 return fmt.Errorf(
344 "Checksums did not match.\nExpected: %s\nGot: %s",
345 hex.EncodeToString(v),
346 hex.EncodeToString(actual))
347 } 295 }
348 296
349 return nil 297 return nil