@@ -4,22 +4,26 @@ import (
44 "bytes"
55 "encoding/json"
66 "fmt"
7+ "io"
78 "io/ioutil"
89 "net/http"
910 "net/url"
11+ "os"
12+ "strconv"
1013)
1114
1215func infocmd (opt Options ) error {
1316 user := nvls (opt .Info .User , EnvUser )
1417 repo := nvls (opt .Info .Repo , EnvRepo )
1518 tag := opt .Upload .Tag
19+ token := nvls (opt .Info .Token , EnvToken )
1620
1721 if user == "" || repo == "" {
1822 return fmt .Errorf ("user and repo need to be passed as arguments" )
1923 }
2024
2125 /* list all tags */
22- tags , err := Tags (user , repo )
26+ tags , err := Tags (user , repo , token )
2327 if err != nil {
2428 return fmt .Errorf ("could not fetch tags, %v" , err )
2529 }
@@ -35,14 +39,14 @@ func infocmd(opt Options) error {
3539 if tag == "" {
3640 /* get all releases */
3741 vprintf ("%v/%v: getting information for all releases\n " , user , repo )
38- releases , err = Releases (user , repo )
42+ releases , err = Releases (user , repo , token )
3943 if err != nil {
4044 return err
4145 }
4246 } else {
4347 /* get only one release */
4448 vprintf ("%v/%v/%v: getting information for the release\n " , user , repo , tag )
45- release , err := ReleaseOfTag (user , repo , tag )
49+ release , err := ReleaseOfTag (user , repo , tag , token )
4650 if err != nil {
4751 return err
4852 }
@@ -75,7 +79,7 @@ func uploadcmd(opt Options) error {
7579 }
7680
7781 /* find the release corresponding to the entered tag, if any */
78- rel , err := ReleaseOfTag (user , repo , tag )
82+ rel , err := ReleaseOfTag (user , repo , tag , token )
7983 if err != nil {
8084 return err
8185 }
@@ -86,7 +90,7 @@ func uploadcmd(opt Options) error {
8690 url := rel .CleanUploadUrl () + "?" + v .Encode ()
8791
8892 resp , err := DoAuthRequest ("POST" , url , "application/octet-stream" ,
89- token , file )
93+ token , nil , file )
9094 if err != nil {
9195 return fmt .Errorf ("can't create upload request to %v, %v" , url , err )
9296 }
@@ -113,7 +117,81 @@ func uploadcmd(opt Options) error {
113117 return nil
114118}
115119
116- func ValidateCredentials (user , repo , token , tag string ) error {
120+ func downloadcmd (opt Options ) error {
121+ user := nvls (opt .Download .User , EnvUser )
122+ repo := nvls (opt .Download .Repo , EnvRepo )
123+ token := nvls (opt .Download .Token , EnvToken )
124+ tag := opt .Download .Tag
125+ name := opt .Download .Name
126+
127+ vprintln ("downloading..." )
128+
129+ if err := ValidateTarget (user , repo , tag ); err != nil {
130+ return err
131+ }
132+
133+ /* find the release corresponding to the entered tag, if any */
134+ rel , err := ReleaseOfTag (user , repo , tag , token )
135+ if err != nil {
136+ return err
137+ }
138+
139+ assetId := 0
140+ for _ , asset := range rel .Assets {
141+ if asset .Name == name {
142+ assetId = asset .Id
143+ }
144+ }
145+
146+ if assetId == 0 {
147+ return fmt .Errorf ("coud not find asset named %s" , name )
148+ }
149+
150+ var resp * http.Response
151+ var url string
152+ if token == "" {
153+ url = GH_URL + fmt .Sprintf ("/%s/%s/releases/download/%s/%s" , user , repo , tag , name )
154+ resp , err = http .Get (url )
155+
156+ } else {
157+ url = ApiURL () + fmt .Sprintf (ASSET_DOWNLOAD_URI , user , repo , assetId )
158+
159+ resp , err = DoAuthRequest ("GET" , url , "" , token , map [string ]string {
160+ "Accept" : "application/octet-stream" ,
161+ }, nil )
162+ }
163+
164+ if err != nil {
165+ return fmt .Errorf ("could not fetch releases, %v" , err )
166+ }
167+
168+ defer resp .Body .Close ()
169+ vprintln ("GET" , url , "->" , resp )
170+
171+ contentLength , err := strconv .ParseInt (resp .Header .Get ("Content-Length" ), 10 , 64 )
172+ if err != nil {
173+ return err
174+ }
175+
176+ if resp .StatusCode != http .StatusOK {
177+ return fmt .Errorf ("github did not respond with 200 OK but with %v" , resp .Status )
178+ }
179+
180+ out , err := os .Create (name )
181+ defer out .Close ()
182+
183+ n , err := io .Copy (out , resp .Body )
184+ if err != nil {
185+ return err
186+ }
187+ if n != contentLength {
188+ return fmt .Errorf ("downloaded data did not match content length %s != %s" , contentLength , n )
189+ }
190+
191+ return nil
192+ }
193+
194+ func ValidateTarget (user , repo , tag string ) error {
117195 if user == "" {
118196 return fmt .Errorf ("empty user" )
119197 }
@@ -123,6 +201,14 @@ func ValidateCredentials(user, repo, token, tag string) error {
123201 if tag == "" {
124202 return fmt .Errorf ("empty tag" )
125203 }
204+ return nil
205+ }
206+
207+ func ValidateCredentials (user , repo , token , tag string ) error {
208+ err := ValidateTarget (user , repo , tag )
209+ if err != nil {
210+ return err
211+ }
126212 if token == "" {
127213 return fmt .Errorf ("empty token" )
128214 }
@@ -163,7 +249,7 @@ func releasecmd(opt Options) error {
163249
164250 uri := fmt .Sprintf ("/repos/%s/%s/releases" , user , repo )
165251 resp , err := DoAuthRequest ("POST" , ApiURL ()+ uri , "application/json" ,
166- token , reader )
252+ token , nil , reader )
167253 if err != nil {
168254 return fmt .Errorf ("while submitting %v, %v" , string (payload ), err )
169255 }
@@ -206,7 +292,7 @@ func editcmd(opt Options) error {
206292 return err
207293 }
208294
209- id , err := IdOfTag (user , repo , tag )
295+ id , err := IdOfTag (user , repo , tag , token )
210296 if err != nil {
211297 return err
212298 }
@@ -230,7 +316,7 @@ func editcmd(opt Options) error {
230316
231317 uri := fmt .Sprintf ("/repos/%s/%s/releases/%d" , user , repo , id )
232318 resp , err := DoAuthRequest ("PATCH" , ApiURL ()+ uri , "application/json" ,
233- token , bytes .NewReader (payload ))
319+ token , nil , bytes .NewReader (payload ))
234320 if err != nil {
235321 return fmt .Errorf ("while submitting %v, %v" , string (payload ), err )
236322 }
@@ -263,7 +349,7 @@ func deletecmd(opt Options) error {
263349 opt .Delete .Tag
264350 vprintln ("deleting..." )
265351
266- id , err := IdOfTag (user , repo , tag )
352+ id , err := IdOfTag (user , repo , tag , token )
267353 if err != nil {
268354 return err
269355 }
@@ -286,7 +372,7 @@ func deletecmd(opt Options) error {
286372}
287373
288374func httpDelete (url , token string ) (* http.Response , error ) {
289- resp , err := DoAuthRequest ("DELETE" , url , "application/json" , token , nil )
375+ resp , err := DoAuthRequest ("DELETE" , url , "application/json" , token , nil , nil )
290376 if err != nil {
291377 return nil , err
292378 }
0 commit comments