@@ -74,7 +74,19 @@ impl RegistryConfigExtended {
74
74
}
75
75
76
76
/// Get the list of credential providers for a registry source.
77
- fn credential_provider ( config : & Config , sid : & SourceId ) -> CargoResult < Vec < Vec < String > > > {
77
+ fn credential_provider (
78
+ config : & Config ,
79
+ sid : & SourceId ,
80
+ show_warnings : bool ,
81
+ ) -> CargoResult < Vec < Vec < String > > > {
82
+ let warn = |message : String | {
83
+ if show_warnings {
84
+ config. shell ( ) . warn ( message)
85
+ } else {
86
+ Ok ( ( ) )
87
+ }
88
+ } ;
89
+
78
90
let cfg = registry_credential_config_raw ( config, sid) ?;
79
91
let default_providers = || {
80
92
if config. cli_unstable ( ) . asymmetric_token {
@@ -111,7 +123,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
111
123
let provider = resolve_credential_alias ( config, provider) ;
112
124
if let Some ( token) = token {
113
125
if provider[ 0 ] != "cargo:token" {
114
- config . shell ( ) . warn ( format ! (
126
+ warn ( format ! (
115
127
"{sid} has a token configured in {} that will be ignored \
116
128
because this registry is configured to use credential-provider `{}`",
117
129
token. definition, provider[ 0 ] ,
@@ -120,7 +132,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
120
132
}
121
133
if let Some ( secret_key) = secret_key {
122
134
if provider[ 0 ] != "cargo:paseto" {
123
- config . shell ( ) . warn ( format ! (
135
+ warn ( format ! (
124
136
"{sid} has a secret-key configured in {} that will be ignored \
125
137
because this registry is configured to use credential-provider `{}`",
126
138
secret_key. definition, provider[ 0 ] ,
@@ -145,14 +157,14 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
145
157
match ( token_pos, paseto_pos) {
146
158
( Some ( token_pos) , Some ( paseto_pos) ) => {
147
159
if token_pos < paseto_pos {
148
- config . shell ( ) . warn ( format ! (
160
+ warn ( format ! (
149
161
"{sid} has a `secret_key` configured in {} that will be ignored \
150
162
because a `token` is also configured, and the `cargo:token` provider is \
151
163
configured with higher precedence",
152
164
secret_key. definition
153
165
) ) ?;
154
166
} else {
155
- config . shell ( ) . warn ( format ! ( "{sid} has a `token` configured in {} that will be ignored \
167
+ warn ( format ! ( "{sid} has a `token` configured in {} that will be ignored \
156
168
because a `secret_key` is also configured, and the `cargo:paseto` provider is \
157
169
configured with higher precedence", token. definition) ) ?;
158
170
}
@@ -172,7 +184,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
172
184
. iter ( )
173
185
. any ( |p| p. first ( ) . map ( String :: as_str) == Some ( "cargo:token" ) )
174
186
{
175
- config . shell ( ) . warn ( format ! (
187
+ warn ( format ! (
176
188
"{sid} has a token configured in {} that will be ignored \
177
189
because the `cargo:token` credential provider is not listed in \
178
190
`registry.global-credential-providers`",
@@ -191,7 +203,7 @@ fn credential_provider(config: &Config, sid: &SourceId) -> CargoResult<Vec<Vec<S
191
203
. iter ( )
192
204
. any ( |p| p. first ( ) . map ( String :: as_str) == Some ( "cargo:paseto" ) )
193
205
{
194
- config . shell ( ) . warn ( format ! (
206
+ warn ( format ! (
195
207
"{sid} has a secret-key configured in {} that will be ignored \
196
208
because the `cargo:paseto` credential provider is not listed in \
197
209
`registry.global-credential-providers`",
@@ -360,14 +372,40 @@ impl fmt::Display for AuthorizationErrorReason {
360
372
#[ derive( Debug ) ]
361
373
pub struct AuthorizationError {
362
374
/// Url that was attempted
363
- pub sid : SourceId ,
375
+ sid : SourceId ,
364
376
/// The `registry.default` config value.
365
- pub default_registry : Option < String > ,
377
+ default_registry : Option < String > ,
366
378
/// Url where the user could log in.
367
379
pub login_url : Option < Url > ,
368
380
/// Specific reason indicating what failed
369
- pub reason : AuthorizationErrorReason ,
381
+ reason : AuthorizationErrorReason ,
382
+ /// Should the _TOKEN environment variable name be included when displaying this error?
383
+ display_token_env_help : bool ,
370
384
}
385
+
386
+ impl AuthorizationError {
387
+ pub fn new (
388
+ config : & Config ,
389
+ sid : SourceId ,
390
+ login_url : Option < Url > ,
391
+ reason : AuthorizationErrorReason ,
392
+ ) -> CargoResult < Self > {
393
+ // Only display the _TOKEN environment variable suggestion if the `cargo:token` credential
394
+ // provider is available for the source. Otherwise setting the environment variable will
395
+ // have no effect.
396
+ let display_token_env_help = credential_provider ( config, & sid, false ) ?
397
+ . iter ( )
398
+ . any ( |p| p. first ( ) . map ( String :: as_str) == Some ( "cargo:token" ) ) ;
399
+ Ok ( AuthorizationError {
400
+ sid,
401
+ default_registry : config. default_registry ( ) ?,
402
+ login_url,
403
+ reason,
404
+ display_token_env_help,
405
+ } )
406
+ }
407
+ }
408
+
371
409
impl Error for AuthorizationError { }
372
410
impl fmt:: Display for AuthorizationError {
373
411
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
@@ -377,20 +415,23 @@ impl fmt::Display for AuthorizationError {
377
415
} else {
378
416
""
379
417
} ;
380
- write ! (
381
- f ,
382
- "{}, please run `cargo login{args}` \n or use environment variable CARGO_REGISTRY_TOKEN",
383
- self . reason
384
- )
418
+ write ! ( f , "{}, please run `cargo login{args}`" , self . reason ) ? ;
419
+ if self . display_token_env_help {
420
+ write ! ( f , " \n or use environment variable CARGO_REGISTRY_TOKEN") ? ;
421
+ }
422
+ Ok ( ( ) )
385
423
} else if let Some ( name) = self . sid . alt_registry_key ( ) {
386
424
let key = ConfigKey :: from_str ( & format ! ( "registries.{name}.token" ) ) ;
387
425
write ! (
388
426
f,
389
- "{} for `{}`, please run `cargo login --registry {name}`\n or use environment variable {} " ,
427
+ "{} for `{}`, please run `cargo login --registry {name}`" ,
390
428
self . reason,
391
429
self . sid. display_registry_name( ) ,
392
- key. as_env_key( ) ,
393
- )
430
+ ) ?;
431
+ if self . display_token_env_help {
432
+ write ! ( f, "\n or use environment variable {}" , key. as_env_key( ) ) ?;
433
+ }
434
+ Ok ( ( ) )
394
435
} else if self . reason == AuthorizationErrorReason :: TokenMissing {
395
436
write ! (
396
437
f,
@@ -416,7 +457,7 @@ my-registry = {{ index = "{}" }}
416
457
}
417
458
}
418
459
419
- // Store a token in the cache for future calls.
460
+ /// Store a token in the cache for future calls.
420
461
pub fn cache_token_from_commandline ( config : & Config , sid : & SourceId , token : Secret < & str > ) {
421
462
let url = sid. canonical_url ( ) ;
422
463
config. credential_cache ( ) . insert (
@@ -446,7 +487,7 @@ fn credential_action(
446
487
name,
447
488
headers,
448
489
} ;
449
- let providers = credential_provider ( config, sid) ?;
490
+ let providers = credential_provider ( config, sid, true ) ?;
450
491
let mut any_not_found = false ;
451
492
for provider in providers {
452
493
let args: Vec < & str > = provider
@@ -511,12 +552,12 @@ pub fn auth_token(
511
552
) -> CargoResult < String > {
512
553
match auth_token_optional ( config, sid, operation, headers) ? {
513
554
Some ( token) => Ok ( token. expose ( ) ) ,
514
- None => Err ( AuthorizationError {
515
- sid : sid . clone ( ) ,
516
- default_registry : config . default_registry ( ) ? ,
517
- login_url : login_url . cloned ( ) ,
518
- reason : AuthorizationErrorReason :: TokenMissing ,
519
- }
555
+ None => Err ( AuthorizationError :: new (
556
+ config ,
557
+ * sid ,
558
+ login_url. cloned ( ) ,
559
+ AuthorizationErrorReason :: TokenMissing ,
560
+ ) ?
520
561
. into ( ) ) ,
521
562
}
522
563
}
0 commit comments