@@ -13,21 +13,35 @@ use serialize::json;
1313
1414pub struct Registry {
1515 host : String ,
16- token : String ,
16+ token : Option < String > ,
1717 handle : http:: Handle ,
1818}
1919
2020pub type Result < T > = result:: Result < T , Error > ;
2121
22+ #[ deriving( PartialEq ) ]
23+ pub enum Auth {
24+ Authorized ,
25+ Unauthorized
26+ }
27+
2228pub enum Error {
2329 Curl ( curl:: ErrCode ) ,
2430 NotOkResponse ( http:: Response ) ,
2531 NonUtf8Body ,
2632 Api ( Vec < String > ) ,
2733 Unauthorized ,
34+ TokenMissing ,
2835 Io ( io:: IoError ) ,
2936}
3037
38+ #[ deriving( Decodable ) ]
39+ pub struct Crate {
40+ pub name : String ,
41+ pub description : Option < String > ,
42+ pub max_version : String
43+ }
44+
3145#[ deriving( Encodable ) ]
3246pub struct NewCrate {
3347 pub name : String ,
@@ -68,13 +82,14 @@ pub struct User {
6882#[ deriving( Decodable ) ] struct ApiError { detail : String }
6983#[ deriving( Encodable ) ] struct OwnersReq < ' a > { users : & ' a [ & ' a str ] }
7084#[ deriving( Decodable ) ] struct Users { users : Vec < User > }
85+ #[ deriving( Decodable ) ] struct Crates { crates : Vec < Crate > }
7186
7287impl Registry {
73- pub fn new ( host : String , token : String ) -> Registry {
88+ pub fn new ( host : String , token : Option < String > ) -> Registry {
7489 Registry :: new_handle ( host, token, http:: Handle :: new ( ) )
7590 }
7691
77- pub fn new_handle ( host : String , token : String ,
92+ pub fn new_handle ( host : String , token : Option < String > ,
7893 handle : http:: Handle ) -> Registry {
7994 Registry {
8095 host : host,
@@ -126,16 +141,23 @@ impl Registry {
126141 box tarball as Box <Reader >] . into_iter ( ) ) ;
127142
128143 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 ( ) ) ;
135151 let _body = try!( response) ;
136152 Ok ( ( ) )
137153 }
138154
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+
139161 pub fn yank ( & mut self , krate : & str , version : & str ) -> Result < ( ) > {
140162 let body = try!( self . delete ( format ! ( "/crates/{}/{}/yank" , krate, version) ,
141163 None ) ) ;
@@ -151,24 +173,28 @@ impl Registry {
151173 }
152174
153175 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 )
155177 }
156178
157179 fn get ( & mut self , path : String ) -> Result < String > {
158- self . req ( path, None , Get )
180+ self . req ( path, None , Get , Auth :: Authorized )
159181 }
160182
161183 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 )
163185 }
164186
165187 fn req ( & mut self , path : String , body : Option < & [ u8 ] > ,
166- method : Method ) -> Result < String > {
188+ method : Method , authorized : Auth ) -> Result < String > {
167189 let mut req = Request :: new ( & mut self . handle , method)
168190 . uri ( format ! ( "{}/api/v1{}" , self . host, path) )
169- . header ( "Authorization" , self . token . as_slice ( ) )
170191 . header ( "Accept" , "application/json" )
171192 . 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+ }
172198 match body {
173199 Some ( b) => req = req. body ( b) ,
174200 None => { }
@@ -213,6 +239,7 @@ impl fmt::Show for Error {
213239 write ! ( f, "api errors: {}" , errs. connect( ", " ) )
214240 }
215241 Error :: Unauthorized => write ! ( f, "unauthorized API access" ) ,
242+ Error :: TokenMissing => write ! ( f, "no upload token found, please run `cargo login`" ) ,
216243 Error :: Io ( ref e) => write ! ( f, "io error: {}" , e) ,
217244 }
218245 }
0 commit comments