4
4
"archive/tar"
5
5
"archive/zip"
6
6
"compress/gzip"
7
+ "errors"
7
8
"fmt"
8
9
"io"
9
10
"net/http"
@@ -15,17 +16,24 @@ import (
15
16
humanize "github.com/dustin/go-humanize"
16
17
)
17
18
19
+ var (
20
+ NeedInstallError = errors .New (
21
+ "detected deb/rpm/apk package, download directly" )
22
+ NoBinError = errors .New ("binary file not found" )
23
+ )
24
+
18
25
type GHReleaseDl struct {
19
26
BinaryName string
20
27
Url string
21
28
Size int64
22
29
}
23
30
24
31
// Download asset from github release
25
- // dl.BinaryName path might change mutably
26
- func (dl * GHReleaseDl ) DlTo (path string ) error {
27
- if path != "" {
28
- dl .BinaryName = filepath .Join (path , dl .BinaryName )
32
+ // dl.BinaryName shall change with full path mutably
33
+ func (dl * GHReleaseDl ) DlTo (path string ) (err error ) {
34
+ dl .BinaryName , err = filepath .Abs (filepath .Join (path , dl .BinaryName ))
35
+ if err != nil {
36
+ return err
29
37
}
30
38
req , err := http .NewRequest ("GET" , dl .Url , nil )
31
39
if err != nil {
@@ -42,14 +50,15 @@ func (dl *GHReleaseDl) DlTo(path string) error {
42
50
return err
43
51
}
44
52
45
- file , err := os .Create (dl .BinaryName )
53
+ tmpfile , err := os .Create (dl .BinaryName + ".tmp" )
46
54
if err != nil {
47
55
return err
48
56
}
57
+ defer tmpfile .Close ()
49
58
50
59
// create progress tui
51
60
starter := func (updater func (float64 )) {
52
- if _ , err := io .Copy (file , & pg.ProgressBytesReader {Reader : resp .Body , Handler : func (p int ) {
61
+ if _ , err := io .Copy (tmpfile , & pg.ProgressBytesReader {Reader : resp .Body , Handler : func (p int ) {
53
62
updater (float64 (p ) / float64 (dl .Size ))
54
63
}}); err != nil {
55
64
panic (err )
@@ -60,18 +69,22 @@ func (dl *GHReleaseDl) DlTo(path string) error {
60
69
}
61
70
62
71
func (dl GHReleaseDl ) ExtractBinary () error {
63
- // `file` has no content, we must open it for reading
64
- openfile , err := os .Open (dl . BinaryName )
72
+ tmpfileName := dl . BinaryName + ".tmp"
73
+ openfile , err := os .Open (tmpfileName )
65
74
if err != nil {
66
75
return err
67
76
}
68
77
defer openfile .Close ()
69
78
70
79
fileExt := filepath .Ext (dl .Url )
71
- var decompressedBinary io.Reader = nil
80
+ var decompressedBinary io.Reader
72
81
switch fileExt {
73
82
case ".zip" :
74
- decompressedBinary , err = dl .ZipBinary (openfile )
83
+ zipFile , err := dl .ZipBinary (openfile )
84
+ if err != nil {
85
+ return err
86
+ }
87
+ decompressedBinary , err = zipFile .Open ()
75
88
if err != nil {
76
89
return err
77
90
}
@@ -93,48 +106,42 @@ func (dl GHReleaseDl) ExtractBinary() error {
93
106
case ".rpm" :
94
107
case ".apk" :
95
108
fileName := dl .BinaryName + fileExt
96
- fmt .Printf ("Detected deb/rpm/apk package, download directly to ./%s\n You can install it with the appropriate commands\n " , fileName )
97
- if err := os .Rename (dl .BinaryName , fileName ); err != nil {
109
+ if err := os .Rename (tmpfileName , fileName ); err != nil {
98
110
panic (err )
99
111
}
100
- return nil
112
+ return NeedInstallError
101
113
default :
102
- defer os .Remove (dl . BinaryName )
103
- return fmt .Errorf ("unsupported file format" )
114
+ defer os .Remove (tmpfileName )
115
+ return fmt .Errorf ("unsupported file format: %v" , fileExt )
104
116
}
105
-
106
- // rewrite the file
117
+ defer os .Remove (tmpfileName )
107
118
out , err := os .Create (dl .BinaryName )
108
119
if err != nil {
109
120
return err
110
121
}
111
122
defer out .Close ()
112
123
if _ , err := io .Copy (out , decompressedBinary ); err != nil {
113
- return nil
124
+ return err
114
125
}
115
-
116
126
return nil
117
127
}
118
128
119
- func (dl GHReleaseDl ) ZipBinary (r * os.File ) (io.Reader , error ) {
129
+ func (dl GHReleaseDl ) ZipBinary (r * os.File ) (* zip.File , error ) {
130
+ b := filepath .Base (dl .BinaryName )
120
131
zipR , err := zip .NewReader (r , dl .Size )
121
132
if err != nil {
122
133
return nil , err
123
134
}
124
135
125
136
for _ , f := range zipR .File {
126
- if filepath .Base (f .Name ) == dl .BinaryName || len (zipR .File ) == 1 {
127
- open , err := f .Open ()
128
- if err != nil {
129
- return nil , err
130
- }
131
- return open , nil
137
+ if filepath .Base (f .Name ) == b || len (zipR .File ) == 1 {
138
+ return f , nil
132
139
}
133
140
}
134
- return nil , fmt . Errorf ( "Binary file %v not found" , dl . BinaryName )
141
+ return nil , NoBinError
135
142
}
136
143
137
- func (GHReleaseDl ) GzBinary (r * os.File ) (io .Reader , error ) {
144
+ func (GHReleaseDl ) GzBinary (r * os.File ) (* gzip .Reader , error ) {
138
145
gzR , err := gzip .NewReader (r )
139
146
if err != nil {
140
147
return nil , err
@@ -143,7 +150,8 @@ func (GHReleaseDl) GzBinary(r *os.File) (io.Reader, error) {
143
150
return gzR , nil
144
151
}
145
152
146
- func (dl GHReleaseDl ) TargzBinary (r * os.File ) (io.Reader , error ) {
153
+ func (dl GHReleaseDl ) TargzBinary (r * os.File ) (* tar.Reader , error ) {
154
+ b := filepath .Base (dl .BinaryName )
147
155
gzR , err := gzip .NewReader (r )
148
156
if err != nil {
149
157
return nil , err
@@ -159,13 +167,12 @@ func (dl GHReleaseDl) TargzBinary(r *os.File) (io.Reader, error) {
159
167
if err != nil {
160
168
return nil , err
161
169
}
162
- if (header .Typeflag != tar .TypeDir ) && filepath .Base (header .Name ) == dl .BinaryName {
163
-
170
+ if (header .Typeflag != tar .TypeDir ) && filepath .Base (header .Name ) == b {
164
171
if err != nil {
165
172
return nil , err
166
173
}
167
- break
174
+ return tarR , nil
168
175
}
169
176
}
170
- return tarR , nil
177
+ return nil , NoBinError
171
178
}
0 commit comments