forked from lazyhacker/getgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgetgo.go
147 lines (129 loc) · 3.75 KB
/
getgo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// getgo is a command line tool to download the latest stable version of Go
// (http://golang.org) that matches the OS and architecture that it is executed
// from. It will check the sha256 checksum to make sure the downloaded file is
// verified or delete it if it doesn't.
package main // import "lazyhacker.dev/getgo"
import (
"crypto/sha256"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"runtime"
)
const (
STABLE_VERSION = "https://golang.org/VERSION?m=text"
GO_DOWNLOAD_URL = "https://dl.google.com/go"
)
var (
sha_extension = ".sha256"
dl = flag.String("dir", "", "Directory path to download to.")
version = *flag.String("version", "", "Specific version to download (e.g. 1.14.7)")
show = flag.Bool("show", true, "If true, print out the file downloaded.")
tar = flag.Bool("tar", false, "If true, download the tar version for Windows and MacOS.")
)
func main() {
flag.Parse()
// Get the OS and architecture
goos := runtime.GOOS
arch := runtime.GOARCH
resp, err := http.Get(STABLE_VERSION)
if version == "" {
if err != nil {
log.Fatalf("Unable to get the latest version number. %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Unable to read the version number. %v", err)
}
version = string(body)
}
if arch == "arm" {
arch = "armv6l"
}
var gofile string
// Construct the file name for the stable binary.
switch goos {
case "linux":
gofile = fmt.Sprintf("%v.%v-%v.tar.gz", version, goos, arch)
case "freebsd":
gofile = fmt.Sprintf("%v.%v-%v.tar.gz", version, goos, arch)
case "windows":
if *tar {
gofile = fmt.Sprintf("%v.%v-%v.tar.gz", version, goos, arch)
} else {
gofile = fmt.Sprintf("%v.%v-%v.msi", version, goos, arch)
}
case "darwin":
if *tar {
gofile = fmt.Sprintf("%v.%v-%v.tar.gz", version, goos, arch)
} else {
gofile = fmt.Sprintf("%v.%v-%v.pkg", version, goos, arch)
}
default:
log.Fatalln("Unknown OS... can't download.")
}
// Get the checksum value from the checksum file.
resp, err = http.Get(fmt.Sprintf("%v/%v", GO_DOWNLOAD_URL, gofile+sha_extension))
if err != nil {
log.Fatalf("Unable to download sha256 file for %v. %v", gofile, err)
}
c, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Unable to read the checksum from file. %v", err)
}
sha256content := string(c)
// Check if the binary has already been downloaded.
var filepath string
if *dl != "" {
filepath = *dl + string(os.PathSeparator) + gofile
} else {
filepath = gofile
}
if _, err := os.Stat(filepath); err == nil {
if m, _ := checksumMatch(filepath, sha256content); m {
log.Println("Existing file is the latest stable and checksum verified. Skipping download.")
return
}
}
// Download the golang binary
download := fmt.Sprintf("%v/%v", GO_DOWNLOAD_URL, gofile)
out, err := os.Create(filepath)
if err != nil {
log.Fatalf("Unable to create %v locally. %v", gofile, err)
}
defer out.Close()
resp, err = http.Get(download)
if err != nil {
log.Fatalf("Unable to get the latest version number. %v", err)
}
_, err = io.Copy(out, resp.Body)
if err != nil {
log.Fatalf("Unable to download %v. %v", gofile, err)
}
// Compute the checksum
if m, v := checksumMatch(filepath, sha256content); !m {
log.Printf("Calcuated checksum %v != %v. Removing download.\n", v, sha256content)
os.Remove(filepath)
}
if *show {
fmt.Printf("%v\n", filepath)
}
}
func checksumMatch(f, v string) (bool, string) {
hash := sha256.New()
gf, err := os.Open(f)
defer gf.Close()
if _, err = io.Copy(hash, gf); err != nil {
log.Printf("Unable to compute sha256 checksum. %v", err)
}
sha256sum := fmt.Sprintf("%x", hash.Sum(nil))
if sha256sum != v {
return false, sha256sum
}
return true, sha256sum
}