11use std:: collections:: BTreeMap ;
22use std:: fs:: { self , File } ;
3+ use std:: io:: { self , BufRead } ;
34use std:: iter:: repeat;
45use std:: str;
56use std:: time:: Duration ;
@@ -65,6 +66,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
6566 opts. token . clone ( ) ,
6667 opts. index . clone ( ) ,
6768 opts. registry . clone ( ) ,
69+ true ,
6870 ) ?;
6971 verify_dependencies ( pkg, reg_id) ?;
7072
@@ -80,7 +82,6 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
8082 allow_dirty : opts. allow_dirty ,
8183 target : opts. target . clone ( ) ,
8284 jobs : opts. jobs ,
83- registry : opts. registry . clone ( ) ,
8485 } ,
8586 ) ?
8687 . unwrap ( ) ;
@@ -320,6 +321,7 @@ pub fn registry(
320321 token : Option < String > ,
321322 index : Option < String > ,
322323 registry : Option < String > ,
324+ force_update : bool ,
323325) -> CargoResult < ( Registry , SourceId ) > {
324326 // Parse all configuration options
325327 let RegistryConfig {
@@ -330,9 +332,17 @@ pub fn registry(
330332 let sid = get_source_id ( config, index_config. or ( index) , registry) ?;
331333 let api_host = {
332334 let mut src = RegistrySource :: remote ( sid, config) ;
333- src. update ( )
334- . chain_err ( || format ! ( "failed to update {}" , sid) ) ?;
335- ( src. config ( ) ?) . unwrap ( ) . api . unwrap ( )
335+ // Only update the index if the config is not available or `force` is set.
336+ let cfg = src. config ( ) ;
337+ let cfg = if force_update || cfg. is_err ( ) {
338+ src. update ( )
339+ . chain_err ( || format ! ( "failed to update {}" , sid) ) ?;
340+ cfg. or_else ( |_| src. config ( ) ) ?
341+ } else {
342+ cfg. unwrap ( )
343+ } ;
344+ cfg. and_then ( |cfg| cfg. api )
345+ . ok_or_else ( || failure:: format_err!( "{} does not support API commands" , sid) ) ?
336346 } ;
337347 let handle = http_handle ( config) ?;
338348 Ok ( ( Registry :: new_handle ( api_host, token, handle) , sid) )
@@ -503,18 +513,51 @@ fn http_proxy_exists(config: &Config) -> CargoResult<bool> {
503513 }
504514}
505515
506- pub fn registry_login ( config : & Config , token : String , registry : Option < String > ) -> CargoResult < ( ) > {
516+ pub fn registry_login (
517+ config : & Config ,
518+ token : Option < String > ,
519+ reg : Option < String > ,
520+ ) -> CargoResult < ( ) > {
521+ let ( registry, _) = registry ( config, token. clone ( ) , None , reg. clone ( ) , false ) ?;
522+
523+ let token = match token {
524+ Some ( token) => token,
525+ None => {
526+ println ! (
527+ "please visit {}/me and paste the API Token below" ,
528+ registry. host( )
529+ ) ;
530+ let mut line = String :: new ( ) ;
531+ let input = io:: stdin ( ) ;
532+ input
533+ . lock ( )
534+ . read_line ( & mut line)
535+ . chain_err ( || "failed to read stdin" )
536+ . map_err ( failure:: Error :: from) ?;
537+ line. trim ( ) . to_string ( )
538+ }
539+ } ;
540+
507541 let RegistryConfig {
508542 token : old_token, ..
509- } = registry_configuration ( config, registry . clone ( ) ) ?;
543+ } = registry_configuration ( config, reg . clone ( ) ) ?;
510544
511545 if let Some ( old_token) = old_token {
512546 if old_token == token {
547+ config. shell ( ) . status ( "Login" , "already logged in" ) ?;
513548 return Ok ( ( ) ) ;
514549 }
515550 }
516551
517- config:: save_credentials ( config, token, registry)
552+ config:: save_credentials ( config, token, reg. clone ( ) ) ?;
553+ config. shell ( ) . status (
554+ "Login" ,
555+ format ! (
556+ "token for `{}` saved" ,
557+ reg. as_ref( ) . map_or( "crates.io" , String :: as_str)
558+ ) ,
559+ ) ?;
560+ Ok ( ( ) )
518561}
519562
520563pub struct OwnersOptions {
@@ -542,6 +585,7 @@ pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
542585 opts. token . clone ( ) ,
543586 opts. index . clone ( ) ,
544587 opts. registry . clone ( ) ,
588+ true ,
545589 ) ?;
546590
547591 if let Some ( ref v) = opts. to_add {
@@ -602,7 +646,7 @@ pub fn yank(
602646 None => failure:: bail!( "a version must be specified to yank" ) ,
603647 } ;
604648
605- let ( mut registry, _) = registry ( config, token, index, reg) ?;
649+ let ( mut registry, _) = registry ( config, token, index, reg, true ) ?;
606650
607651 if undo {
608652 config
@@ -658,22 +702,7 @@ pub fn search(
658702 prefix
659703 }
660704
661- let sid = get_source_id ( config, index, reg) ?;
662-
663- let mut regsrc = RegistrySource :: remote ( sid, config) ;
664- let cfg = match regsrc. config ( ) {
665- Ok ( c) => c,
666- Err ( _) => {
667- regsrc
668- . update ( )
669- . chain_err ( || format ! ( "failed to update {}" , & sid) ) ?;
670- regsrc. config ( ) ?
671- }
672- } ;
673-
674- let api_host = cfg. unwrap ( ) . api . unwrap ( ) ;
675- let handle = http_handle ( config) ?;
676- let mut registry = Registry :: new_handle ( api_host, None , handle) ;
705+ let ( mut registry, _) = registry ( config, None , index, reg, false ) ?;
677706 let ( crates, total_crates) = registry
678707 . search ( query, limit)
679708 . chain_err ( || "failed to retrieve search results from the registry" ) ?;
0 commit comments