Skip to content

Commit 440a42d

Browse files
committed
Merge pull request #204 from Tonkpils/upgrade-enhancement
Upgrade enhancement
2 parents 0048c2b + 2e6342a commit 440a42d

4 files changed

Lines changed: 149 additions & 140 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The exercism CLI follows [semantic versioning](http://semver.org/).
77
## Next Release
88

99
* [#200](https://github.com/exercism/cli/pull/200): Add guard to unsubmit command - [@kytrinyx](https://github.com/kytrinyx)
10+
* [#204](https://github.com/exercism/cli/pull/204): Improve upgrade failure messages and increase timeout - [@Tonkpils](https://github.com/Tonkpils)
1011
* **Your contribution here**
1112

1213
## v2.2.0 (2015-06-27)

cmd/debug.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package cmd
22

33
import (
4-
"encoding/json"
5-
"errors"
64
"fmt"
75
"log"
86
"net/http"
@@ -23,9 +21,9 @@ func Debug(ctx *cli.Context) {
2321
fmt.Printf("\n**** Debug Information ****\n")
2422
fmt.Printf("Exercism CLI Version: %s\n", ctx.App.Version)
2523

26-
rel, err := checkLatestRelease(client)
24+
rel, err := fetchLatestRelease(client)
2725
if err != nil {
28-
log.Println(err)
26+
log.Println("unable to fetch latest release: " + err.Error())
2927
} else {
3028
if rel.Version() != ctx.App.Version {
3129
defer fmt.Printf("\nA newer version of the CLI (%s) can be downloaded here: %s\n", rel.TagName, rel.Location)
@@ -72,20 +70,6 @@ func Debug(ctx *cli.Context) {
7270
fmt.Printf("Exercises Directory: %s\n", c.Dir)
7371
}
7472

75-
func checkLatestRelease(client http.Client) (*release, error) {
76-
resp, err := client.Get("https://api.github.com/repos/exercism/cli/releases/latest")
77-
if err != nil {
78-
return nil, errors.New("unable to get latest CLI release: " + err.Error())
79-
}
80-
81-
var rel release
82-
if err := json.NewDecoder(resp.Body).Decode(&rel); err != nil {
83-
return nil, errors.New("error decoding latest release response: " + err.Error())
84-
}
85-
86-
return &rel, nil
87-
}
88-
8973
func pingURL(client http.Client, url string) string {
9074
res, err := client.Get(url)
9175
if err != nil {

cmd/release_utils.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package cmd
2+
3+
import (
4+
"archive/tar"
5+
"archive/zip"
6+
"bytes"
7+
"compress/gzip"
8+
"encoding/json"
9+
"fmt"
10+
"io"
11+
"io/ioutil"
12+
"net/http"
13+
"os"
14+
"strings"
15+
)
16+
17+
var (
18+
osMap = map[string]string{
19+
"darwin": "mac",
20+
"linux": "linux",
21+
"windows": "windows",
22+
}
23+
24+
archMap = map[string]string{
25+
"amd64": "64bit",
26+
"386": "32bit",
27+
"arm": "arm",
28+
}
29+
)
30+
31+
type asset struct {
32+
ID int `json:"id"`
33+
Name string `json:"name"`
34+
ContentType string `json:"content_type"`
35+
}
36+
37+
func (a *asset) Download() (*bytes.Reader, error) {
38+
downloadURL := fmt.Sprintf("https://api.github.com/repos/exercism/cli/releases/assets/%d", a.ID)
39+
req, err := http.NewRequest("GET", downloadURL, nil)
40+
if err != nil {
41+
return nil, err
42+
}
43+
// https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
44+
req.Header.Set("Accept", "application/octet-stream")
45+
res, err := http.DefaultClient.Do(req)
46+
if err != nil {
47+
return nil, err
48+
}
49+
defer res.Body.Close()
50+
51+
bs, err := ioutil.ReadAll(res.Body)
52+
if err != nil {
53+
return nil, err
54+
}
55+
56+
return bytes.NewReader(bs), nil
57+
}
58+
59+
type release struct {
60+
Location string `json:"html_url"`
61+
TagName string `json:"tag_name"`
62+
Assets []asset `json:"assets"`
63+
}
64+
65+
func (r *release) Version() string {
66+
return strings.TrimPrefix(r.TagName, "v")
67+
}
68+
69+
const installFlag = os.O_RDWR | os.O_CREATE | os.O_TRUNC
70+
71+
func installTgz(source *bytes.Reader, dest string) error {
72+
gr, err := gzip.NewReader(source)
73+
if err != nil {
74+
return err
75+
}
76+
defer gr.Close()
77+
78+
tr := tar.NewReader(gr)
79+
for {
80+
hdr, err := tr.Next()
81+
if err == io.EOF {
82+
break
83+
}
84+
if err != nil {
85+
return err
86+
}
87+
88+
fileCopy, err := os.OpenFile(dest, installFlag, hdr.FileInfo().Mode())
89+
if err != nil {
90+
return err
91+
}
92+
defer fileCopy.Close()
93+
94+
if _, err = io.Copy(fileCopy, tr); err != nil {
95+
return err
96+
}
97+
}
98+
99+
return nil
100+
}
101+
102+
func installZip(source *bytes.Reader, dest string) error {
103+
zr, err := zip.NewReader(source, int64(source.Len()))
104+
if err != nil {
105+
return err
106+
}
107+
108+
for _, f := range zr.File {
109+
fileCopy, err := os.OpenFile(dest, installFlag, f.Mode())
110+
if err != nil {
111+
return err
112+
}
113+
defer fileCopy.Close()
114+
115+
rc, err := f.Open()
116+
if err != nil {
117+
return err
118+
}
119+
defer rc.Close()
120+
121+
_, err = io.Copy(fileCopy, rc)
122+
if err != nil {
123+
return err
124+
}
125+
}
126+
127+
return nil
128+
}
129+
130+
func fetchLatestRelease(client http.Client) (*release, error) {
131+
resp, err := client.Get("https://api.github.com/repos/exercism/cli/releases/latest")
132+
if err != nil {
133+
return nil, err
134+
}
135+
defer resp.Body.Close()
136+
137+
var rel release
138+
if err := json.NewDecoder(resp.Body).Decode(&rel); err != nil {
139+
return nil, err
140+
}
141+
142+
return &rel, nil
143+
}

cmd/upgrade.go

Lines changed: 3 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
package cmd
22

33
import (
4-
"archive/tar"
5-
"archive/zip"
64
"bytes"
7-
"compress/gzip"
85
"fmt"
9-
"io"
10-
"io/ioutil"
116
"log"
127
"net/http"
13-
"os"
148
"runtime"
159
"strings"
1610
"time"
@@ -30,10 +24,10 @@ var (
3024

3125
// Upgrade command allows the user to upgrade to the latest CLI version
3226
func Upgrade(ctx *cli.Context) {
33-
client := http.Client{Timeout: 5 * time.Second}
34-
rel, err := checkLatestRelease(client)
27+
client := http.Client{Timeout: 10 * time.Second}
28+
rel, err := fetchLatestRelease(client)
3529
if err != nil {
36-
log.Fatal(err)
30+
log.Fatal("unable to check latest release version: " + err.Error())
3731
}
3832

3933
// TODO: This checks strings against string
@@ -94,116 +88,3 @@ func Upgrade(ctx *cli.Context) {
9488

9589
fmt.Println("Successfully upgraded!")
9690
}
97-
98-
var (
99-
osMap = map[string]string{
100-
"darwin": "mac",
101-
"linux": "linux",
102-
"windows": "windows",
103-
}
104-
105-
archMap = map[string]string{
106-
"amd64": "64bit",
107-
"386": "32bit",
108-
"arm": "arm",
109-
}
110-
)
111-
112-
const installFlag = os.O_RDWR | os.O_CREATE | os.O_TRUNC
113-
114-
func installTgz(source *bytes.Reader, dest string) error {
115-
gr, err := gzip.NewReader(source)
116-
if err != nil {
117-
return err
118-
}
119-
defer gr.Close()
120-
121-
tr := tar.NewReader(gr)
122-
for {
123-
hdr, err := tr.Next()
124-
if err == io.EOF {
125-
break
126-
}
127-
if err != nil {
128-
return err
129-
}
130-
131-
fileCopy, err := os.OpenFile(dest, installFlag, hdr.FileInfo().Mode())
132-
if err != nil {
133-
return err
134-
}
135-
defer fileCopy.Close()
136-
137-
if _, err = io.Copy(fileCopy, tr); err != nil {
138-
return err
139-
}
140-
}
141-
142-
return nil
143-
}
144-
145-
func installZip(source *bytes.Reader, dest string) error {
146-
zr, err := zip.NewReader(source, int64(source.Len()))
147-
if err != nil {
148-
return err
149-
}
150-
151-
for _, f := range zr.File {
152-
fileCopy, err := os.OpenFile(dest, installFlag, f.Mode())
153-
if err != nil {
154-
return err
155-
}
156-
defer fileCopy.Close()
157-
158-
rc, err := f.Open()
159-
if err != nil {
160-
return err
161-
}
162-
defer rc.Close()
163-
164-
_, err = io.Copy(fileCopy, rc)
165-
if err != nil {
166-
return err
167-
}
168-
}
169-
170-
return nil
171-
}
172-
173-
type asset struct {
174-
ID int `json:"id"`
175-
Name string `json:"name"`
176-
ContentType string `json:"content_type"`
177-
}
178-
179-
func (a *asset) Download() (*bytes.Reader, error) {
180-
downloadURL := fmt.Sprintf("https://api.github.com/repos/exercism/cli/releases/assets/%d", a.ID)
181-
req, err := http.NewRequest("GET", downloadURL, nil)
182-
if err != nil {
183-
return nil, err
184-
}
185-
// https://developer.github.com/v3/repos/releases/#get-a-single-release-asset
186-
req.Header.Set("Accept", "application/octet-stream")
187-
res, err := http.DefaultClient.Do(req)
188-
if err != nil {
189-
return nil, err
190-
}
191-
defer res.Body.Close()
192-
193-
bs, err := ioutil.ReadAll(res.Body)
194-
if err != nil {
195-
return nil, err
196-
}
197-
198-
return bytes.NewReader(bs), nil
199-
}
200-
201-
type release struct {
202-
Location string `json:"html_url"`
203-
TagName string `json:"tag_name"`
204-
Assets []asset `json:"assets"`
205-
}
206-
207-
func (r *release) Version() string {
208-
return strings.TrimPrefix(r.TagName, "v")
209-
}

0 commit comments

Comments
 (0)