Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / cmd / getgo / download.go
1 // Copyright 2017 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build !plan9
6
7 package main
8
9 import (
10         "archive/tar"
11         "archive/zip"
12         "compress/gzip"
13         "crypto/sha256"
14         "fmt"
15         "io"
16         "io/ioutil"
17         "net/http"
18         "os"
19         "path/filepath"
20         "strings"
21 )
22
23 const (
24         currentVersionURL = "https://golang.org/VERSION?m=text"
25         downloadURLPrefix = "https://dl.google.com/go"
26 )
27
28 // downloadGoVersion downloads and upacks the specific go version to dest/go.
29 func downloadGoVersion(version, ops, arch, dest string) error {
30         suffix := "tar.gz"
31         if ops == "windows" {
32                 suffix = "zip"
33         }
34         uri := fmt.Sprintf("%s/%s.%s-%s.%s", downloadURLPrefix, version, ops, arch, suffix)
35
36         verbosef("Downloading %s", uri)
37
38         req, err := http.NewRequest("GET", uri, nil)
39         if err != nil {
40                 return err
41         }
42         req.Header.Add("User-Agent", fmt.Sprintf("golang.org-getgo/%s", version))
43
44         resp, err := http.DefaultClient.Do(req)
45         if err != nil {
46                 return fmt.Errorf("Downloading Go from %s failed: %v", uri, err)
47         }
48         if resp.StatusCode > 299 {
49                 return fmt.Errorf("Downloading Go from %s failed with HTTP status %s", uri, resp.Status)
50         }
51         defer resp.Body.Close()
52
53         tmpf, err := ioutil.TempFile("", "go")
54         if err != nil {
55                 return err
56         }
57         defer os.Remove(tmpf.Name())
58
59         h := sha256.New()
60
61         w := io.MultiWriter(tmpf, h)
62         if _, err := io.Copy(w, resp.Body); err != nil {
63                 return err
64         }
65
66         verbosef("Downloading SHA %s.sha256", uri)
67
68         sresp, err := http.Get(uri + ".sha256")
69         if err != nil {
70                 return fmt.Errorf("Downloading Go sha256 from %s.sha256 failed: %v", uri, err)
71         }
72         defer sresp.Body.Close()
73         if sresp.StatusCode > 299 {
74                 return fmt.Errorf("Downloading Go sha256 from %s.sha256 failed with HTTP status %s", uri, sresp.Status)
75         }
76
77         shasum, err := ioutil.ReadAll(sresp.Body)
78         if err != nil {
79                 return err
80         }
81
82         // Check the shasum.
83         sum := fmt.Sprintf("%x", h.Sum(nil))
84         if sum != string(shasum) {
85                 return fmt.Errorf("Shasum mismatch %s vs. %s", sum, string(shasum))
86         }
87
88         unpackFunc := unpackTar
89         if ops == "windows" {
90                 unpackFunc = unpackZip
91         }
92         if err := unpackFunc(tmpf.Name(), dest); err != nil {
93                 return fmt.Errorf("Unpacking Go to %s failed: %v", dest, err)
94         }
95         return nil
96 }
97
98 func unpack(dest, name string, fi os.FileInfo, r io.Reader) error {
99         if strings.HasPrefix(name, "go/") {
100                 name = name[len("go/"):]
101         }
102
103         path := filepath.Join(dest, name)
104         if fi.IsDir() {
105                 return os.MkdirAll(path, fi.Mode())
106         }
107
108         f, err := os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, fi.Mode())
109         if err != nil {
110                 return err
111         }
112         defer f.Close()
113
114         _, err = io.Copy(f, r)
115         return err
116 }
117
118 func unpackTar(src, dest string) error {
119         r, err := os.Open(src)
120         if err != nil {
121                 return err
122         }
123         defer r.Close()
124
125         archive, err := gzip.NewReader(r)
126         if err != nil {
127                 return err
128         }
129         defer archive.Close()
130
131         tarReader := tar.NewReader(archive)
132
133         for {
134                 header, err := tarReader.Next()
135                 if err == io.EOF {
136                         break
137                 } else if err != nil {
138                         return err
139                 }
140
141                 if err := unpack(dest, header.Name, header.FileInfo(), tarReader); err != nil {
142                         return err
143                 }
144         }
145
146         return nil
147 }
148
149 func unpackZip(src, dest string) error {
150         zr, err := zip.OpenReader(src)
151         if err != nil {
152                 return err
153         }
154
155         for _, f := range zr.File {
156                 fr, err := f.Open()
157                 if err != nil {
158                         return err
159                 }
160                 if err := unpack(dest, f.Name, f.FileInfo(), fr); err != nil {
161                         return err
162                 }
163                 fr.Close()
164         }
165
166         return nil
167 }
168
169 func getLatestGoVersion() (string, error) {
170         resp, err := http.Get(currentVersionURL)
171         if err != nil {
172                 return "", fmt.Errorf("Getting current Go version failed: %v", err)
173         }
174         defer resp.Body.Close()
175         if resp.StatusCode > 299 {
176                 b, _ := ioutil.ReadAll(io.LimitReader(resp.Body, 1024))
177                 return "", fmt.Errorf("Could not get current Go version: HTTP %d: %q", resp.StatusCode, b)
178         }
179         version, err := ioutil.ReadAll(resp.Body)
180         if err != nil {
181                 return "", err
182         }
183         return strings.TrimSpace(string(version)), nil
184 }