1
1
use crate :: core:: PackageId ;
2
- use crate :: sources:: DirectorySource ;
3
- use crate :: sources:: { GitSource , PathSource , RegistrySource , CRATES_IO_INDEX } ;
2
+ use crate :: sources:: { DirectorySource , CRATES_IO_DOMAIN , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
3
+ use crate :: sources:: { GitSource , PathSource , RegistrySource } ;
4
4
use crate :: util:: { CanonicalUrl , CargoResult , Config , IntoUrl } ;
5
5
use log:: trace;
6
6
use serde:: de;
@@ -24,7 +24,7 @@ pub struct SourceId {
24
24
inner : & ' static SourceIdInner ,
25
25
}
26
26
27
- #[ derive( PartialEq , Eq , Clone , Debug , Hash ) ]
27
+ #[ derive( Eq , Clone , Debug ) ]
28
28
struct SourceIdInner {
29
29
/// The source URL.
30
30
url : Url ,
@@ -73,13 +73,13 @@ impl SourceId {
73
73
/// Creates a `SourceId` object from the kind and URL.
74
74
///
75
75
/// The canonical url will be calculated, but the precise field will not
76
- fn new ( kind : SourceKind , url : Url ) -> CargoResult < SourceId > {
76
+ fn new ( kind : SourceKind , url : Url , name : Option < & str > ) -> CargoResult < SourceId > {
77
77
let source_id = SourceId :: wrap ( SourceIdInner {
78
78
kind,
79
79
canonical_url : CanonicalUrl :: new ( & url) ?,
80
80
url,
81
81
precise : None ,
82
- name : None ,
82
+ name : name . map ( |n| n . into ( ) ) ,
83
83
} ) ;
84
84
Ok ( source_id)
85
85
}
@@ -132,12 +132,12 @@ impl SourceId {
132
132
}
133
133
"registry" => {
134
134
let url = url. into_url ( ) ?;
135
- Ok ( SourceId :: new ( SourceKind :: Registry , url) ?
135
+ Ok ( SourceId :: new ( SourceKind :: Registry , url, None ) ?
136
136
. with_precise ( Some ( "locked" . to_string ( ) ) ) )
137
137
}
138
138
"path" => {
139
139
let url = url. into_url ( ) ?;
140
- SourceId :: new ( SourceKind :: Path , url)
140
+ SourceId :: new ( SourceKind :: Path , url, None )
141
141
}
142
142
kind => Err ( anyhow:: format_err!( "unsupported source protocol: {}" , kind) ) ,
143
143
}
@@ -155,43 +155,53 @@ impl SourceId {
155
155
/// `path`: an absolute path.
156
156
pub fn for_path ( path : & Path ) -> CargoResult < SourceId > {
157
157
let url = path. into_url ( ) ?;
158
- SourceId :: new ( SourceKind :: Path , url)
158
+ SourceId :: new ( SourceKind :: Path , url, None )
159
159
}
160
160
161
161
/// Creates a `SourceId` from a Git reference.
162
162
pub fn for_git ( url : & Url , reference : GitReference ) -> CargoResult < SourceId > {
163
- SourceId :: new ( SourceKind :: Git ( reference) , url. clone ( ) )
163
+ SourceId :: new ( SourceKind :: Git ( reference) , url. clone ( ) , None )
164
164
}
165
165
166
- /// Creates a SourceId from a registry URL.
166
+ /// Creates a SourceId from a remote registry URL when the registry name
167
+ /// cannot be determined, e.g. an user passes `--index` directly from CLI.
168
+ ///
169
+ /// Use [`SourceId::for_alt_registry`] if a name can provided, which
170
+ /// generates better messages for cargo.
167
171
pub fn for_registry ( url : & Url ) -> CargoResult < SourceId > {
168
- SourceId :: new ( SourceKind :: Registry , url. clone ( ) )
172
+ SourceId :: new ( SourceKind :: Registry , url. clone ( ) , None )
173
+ }
174
+
175
+ /// Creates a `SourceId` from a remote registry URL with given name.
176
+ pub fn for_alt_registry ( url : & Url , name : & str ) -> CargoResult < SourceId > {
177
+ SourceId :: new ( SourceKind :: Registry , url. clone ( ) , Some ( name) )
169
178
}
170
179
171
180
/// Creates a SourceId from a local registry path.
172
181
pub fn for_local_registry ( path : & Path ) -> CargoResult < SourceId > {
173
182
let url = path. into_url ( ) ?;
174
- SourceId :: new ( SourceKind :: LocalRegistry , url)
183
+ SourceId :: new ( SourceKind :: LocalRegistry , url, None )
175
184
}
176
185
177
186
/// Creates a `SourceId` from a directory path.
178
187
pub fn for_directory ( path : & Path ) -> CargoResult < SourceId > {
179
188
let url = path. into_url ( ) ?;
180
- SourceId :: new ( SourceKind :: Directory , url)
189
+ SourceId :: new ( SourceKind :: Directory , url, None )
181
190
}
182
191
183
192
/// Returns the `SourceId` corresponding to the main repository.
184
193
///
185
194
/// This is the main cargo registry by default, but it can be overridden in
186
- /// a `.cargo/config`.
195
+ /// a `.cargo/config.toml `.
187
196
pub fn crates_io ( config : & Config ) -> CargoResult < SourceId > {
188
197
config. crates_io_source_id ( || {
189
198
config. check_registry_index_not_set ( ) ?;
190
199
let url = CRATES_IO_INDEX . into_url ( ) . unwrap ( ) ;
191
- SourceId :: for_registry ( & url)
200
+ SourceId :: new ( SourceKind :: Registry , url, Some ( CRATES_IO_REGISTRY ) )
192
201
} )
193
202
}
194
203
204
+ /// Gets the `SourceId` associated with given name of the remote regsitry.
195
205
pub fn alt_registry ( config : & Config , key : & str ) -> CargoResult < SourceId > {
196
206
let url = config. get_registry_index ( key) ?;
197
207
Ok ( SourceId :: wrap ( SourceIdInner {
@@ -216,17 +226,21 @@ impl SourceId {
216
226
217
227
pub fn display_index ( self ) -> String {
218
228
if self . is_default_registry ( ) {
219
- "crates.io index". to_string ( )
229
+ format ! ( "{} index", CRATES_IO_DOMAIN )
220
230
} else {
221
- format ! ( "`{}` index" , url_display ( self . url ( ) ) )
231
+ format ! ( "`{}` index" , self . display_registry_name ( ) )
222
232
}
223
233
}
224
234
225
235
pub fn display_registry_name ( self ) -> String {
226
236
if self . is_default_registry ( ) {
227
- "crates.io" . to_string ( )
237
+ CRATES_IO_REGISTRY . to_string ( )
228
238
} else if let Some ( name) = & self . inner . name {
229
239
name. clone ( )
240
+ } else if self . precise ( ) . is_some ( ) {
241
+ // We remove `precise` here to retrieve an permissive version of
242
+ // `SourceIdInner`, which may contain the registry name.
243
+ self . with_precise ( None ) . display_registry_name ( )
230
244
} else {
231
245
url_display ( self . url ( ) )
232
246
}
@@ -463,7 +477,7 @@ impl fmt::Display for SourceId {
463
477
Ok ( ( ) )
464
478
}
465
479
SourceKind :: Path => write ! ( f, "{}" , url_display( & self . inner. url) ) ,
466
- SourceKind :: Registry => write ! ( f, "registry `{}`" , url_display ( & self . inner . url ) ) ,
480
+ SourceKind :: Registry => write ! ( f, "registry `{}`" , self . display_registry_name ( ) ) ,
467
481
SourceKind :: LocalRegistry => write ! ( f, "registry `{}`" , url_display( & self . inner. url) ) ,
468
482
SourceKind :: Directory => write ! ( f, "dir {}" , url_display( & self . inner. url) ) ,
469
483
}
@@ -483,6 +497,29 @@ impl Hash for SourceId {
483
497
}
484
498
}
485
499
500
+ impl Hash for SourceIdInner {
501
+ /// The hash of `SourceIdInner` is used to retrieve its interned value. We
502
+ /// only care about fields that make `SourceIdInner` unique, which are:
503
+ ///
504
+ /// - `kind`
505
+ /// - `precise`
506
+ /// - `canonical_url`
507
+ fn hash < S : hash:: Hasher > ( & self , into : & mut S ) {
508
+ self . kind . hash ( into) ;
509
+ self . precise . hash ( into) ;
510
+ self . canonical_url . hash ( into) ;
511
+ }
512
+ }
513
+
514
+ impl PartialEq for SourceIdInner {
515
+ /// This implementation must be synced with [`SourceIdInner::hash`].
516
+ fn eq ( & self , other : & Self ) -> bool {
517
+ self . kind == other. kind
518
+ && self . precise == other. precise
519
+ && self . canonical_url == other. canonical_url
520
+ }
521
+ }
522
+
486
523
// forward to `Ord`
487
524
impl PartialOrd for SourceKind {
488
525
fn partial_cmp ( & self , other : & SourceKind ) -> Option < Ordering > {
@@ -670,15 +707,15 @@ mod tests {
670
707
fn github_sources_equal ( ) {
671
708
let loc = "https://github.com/foo/bar" . into_url ( ) . unwrap ( ) ;
672
709
let default = SourceKind :: Git ( GitReference :: DefaultBranch ) ;
673
- let s1 = SourceId :: new ( default. clone ( ) , loc) . unwrap ( ) ;
710
+ let s1 = SourceId :: new ( default. clone ( ) , loc, None ) . unwrap ( ) ;
674
711
675
712
let loc = "git://github.com/foo/bar" . into_url ( ) . unwrap ( ) ;
676
- let s2 = SourceId :: new ( default, loc. clone ( ) ) . unwrap ( ) ;
713
+ let s2 = SourceId :: new ( default, loc. clone ( ) , None ) . unwrap ( ) ;
677
714
678
715
assert_eq ! ( s1, s2) ;
679
716
680
717
let foo = SourceKind :: Git ( GitReference :: Branch ( "foo" . to_string ( ) ) ) ;
681
- let s3 = SourceId :: new ( foo, loc) . unwrap ( ) ;
718
+ let s3 = SourceId :: new ( foo, loc, None ) . unwrap ( ) ;
682
719
assert_ne ! ( s1, s3) ;
683
720
}
684
721
}
0 commit comments