@@ -13,21 +13,35 @@ use serialize::json;
13
13
14
14
pub struct Registry {
15
15
host : String ,
16
- token : String ,
16
+ token : Option < String > ,
17
17
handle : http:: Handle ,
18
18
}
19
19
20
20
pub type Result < T > = result:: Result < T , Error > ;
21
21
22
+ #[ deriving( PartialEq ) ]
23
+ pub enum Auth {
24
+ Authorized ,
25
+ Unauthorized
26
+ }
27
+
22
28
pub enum Error {
23
29
Curl ( curl:: ErrCode ) ,
24
30
NotOkResponse ( http:: Response ) ,
25
31
NonUtf8Body ,
26
32
Api ( Vec < String > ) ,
27
33
Unauthorized ,
34
+ TokenMissing ,
28
35
Io ( io:: IoError ) ,
29
36
}
30
37
38
+ #[ deriving( Decodable ) ]
39
+ pub struct Crate {
40
+ pub name : String ,
41
+ pub description : Option < String > ,
42
+ pub max_version : String
43
+ }
44
+
31
45
#[ deriving( Encodable ) ]
32
46
pub struct NewCrate {
33
47
pub name : String ,
@@ -68,13 +82,14 @@ pub struct User {
68
82
#[ deriving( Decodable ) ] struct ApiError { detail : String }
69
83
#[ deriving( Encodable ) ] struct OwnersReq < ' a > { users : & ' a [ & ' a str ] }
70
84
#[ deriving( Decodable ) ] struct Users { users : Vec < User > }
85
+ #[ deriving( Decodable ) ] struct Crates { crates : Vec < Crate > }
71
86
72
87
impl Registry {
73
- pub fn new ( host : String , token : String ) -> Registry {
88
+ pub fn new ( host : String , token : Option < String > ) -> Registry {
74
89
Registry :: new_handle ( host, token, http:: Handle :: new ( ) )
75
90
}
76
91
77
- pub fn new_handle ( host : String , token : String ,
92
+ pub fn new_handle ( host : String , token : Option < String > ,
78
93
handle : http:: Handle ) -> Registry {
79
94
Registry {
80
95
host : host,
@@ -126,16 +141,23 @@ impl Registry {
126
141
box tarball as Box <Reader >] . into_iter ( ) ) ;
127
142
128
143
let url = format ! ( "{}/api/v1/crates/new" , self . host) ;
129
- let response = handle ( self . handle . put ( url, & mut body)
130
- . content_length ( size)
131
- . header ( "Authorization" ,
132
- self . token . as_slice ( ) )
133
- . header ( "Accept" , "application/json" )
134
- . exec ( ) ) ;
144
+
145
+ let token = try!( self . token . as_ref ( ) . ok_or ( Error :: TokenMissing ) ) . as_slice ( ) ;
146
+ let request = self . handle . put ( url, & mut body)
147
+ . content_length ( size)
148
+ . header ( "Accept" , "application/json" )
149
+ . header ( "Authorization" , token) ;
150
+ let response = handle ( request. exec ( ) ) ;
135
151
let _body = try!( response) ;
136
152
Ok ( ( ) )
137
153
}
138
154
155
+ pub fn search ( & mut self , query : & str ) -> Result < Vec < Crate > > {
156
+ let body = try!( self . req ( format ! ( "/crates?q={}" , query) , None , Get , Auth :: Unauthorized ) ) ;
157
+
158
+ Ok ( json:: decode :: < Crates > ( body. as_slice ( ) ) . unwrap ( ) . crates )
159
+ }
160
+
139
161
pub fn yank ( & mut self , krate : & str , version : & str ) -> Result < ( ) > {
140
162
let body = try!( self . delete ( format ! ( "/crates/{}/{}/yank" , krate, version) ,
141
163
None ) ) ;
@@ -151,24 +173,28 @@ impl Registry {
151
173
}
152
174
153
175
fn put ( & mut self , path : String , b : & [ u8 ] ) -> Result < String > {
154
- self . req ( path, Some ( b) , Put )
176
+ self . req ( path, Some ( b) , Put , Auth :: Authorized )
155
177
}
156
178
157
179
fn get ( & mut self , path : String ) -> Result < String > {
158
- self . req ( path, None , Get )
180
+ self . req ( path, None , Get , Auth :: Authorized )
159
181
}
160
182
161
183
fn delete ( & mut self , path : String , b : Option < & [ u8 ] > ) -> Result < String > {
162
- self . req ( path, b, Delete )
184
+ self . req ( path, b, Delete , Auth :: Authorized )
163
185
}
164
186
165
187
fn req ( & mut self , path : String , body : Option < & [ u8 ] > ,
166
- method : Method ) -> Result < String > {
188
+ method : Method , authorized : Auth ) -> Result < String > {
167
189
let mut req = Request :: new ( & mut self . handle , method)
168
190
. uri ( format ! ( "{}/api/v1{}" , self . host, path) )
169
- . header ( "Authorization" , self . token . as_slice ( ) )
170
191
. header ( "Accept" , "application/json" )
171
192
. content_type ( "application/json" ) ;
193
+
194
+ let token = try!( self . token . as_ref ( ) . ok_or ( Error :: TokenMissing ) ) . as_slice ( ) ;
195
+ if authorized == Auth :: Authorized {
196
+ req = req. header ( "Authorization" , token) ;
197
+ }
172
198
match body {
173
199
Some ( b) => req = req. body ( b) ,
174
200
None => { }
@@ -213,6 +239,7 @@ impl fmt::Show for Error {
213
239
write ! ( f, "api errors: {}" , errs. connect( ", " ) )
214
240
}
215
241
Error :: Unauthorized => write ! ( f, "unauthorized API access" ) ,
242
+ Error :: TokenMissing => write ! ( f, "no upload token found, please run `cargo login`" ) ,
216
243
Error :: Io ( ref e) => write ! ( f, "io error: {}" , e) ,
217
244
}
218
245
}
0 commit comments