1
- //! Access to a HTTP-based crate registry.
2
- //!
3
- //! See [`HttpRegistry`] for details.
1
+ //! Access to a HTTP-based crate registry. See [`HttpRegistry`] for details.
4
2
5
3
use crate :: core:: { PackageId , SourceId } ;
6
4
use crate :: ops:: { self } ;
@@ -52,8 +50,15 @@ const UNKNOWN: &'static str = "Unknown";
52
50
///
53
51
/// [RFC 2789]: https://github.com/rust-lang/rfcs/pull/2789
54
52
pub struct HttpRegistry < ' cfg > {
53
+ /// Path to the registry index (`$CARGO_HOME/registry/index/$REG-HASH`).
54
+ ///
55
+ /// To be fair, `HttpRegistry` doesn't store the registry index it
56
+ /// downloads on the file system, but other cached data like registry
57
+ /// configuration could be stored here.
55
58
index_path : Filesystem ,
59
+ /// Path to the cache of `.crate` files (`$CARGO_HOME/registry/cache/$REG-HASH`).
56
60
cache_path : Filesystem ,
61
+ /// The unique identifier of this registry source.
57
62
source_id : SourceId ,
58
63
config : & ' cfg Config ,
59
64
@@ -95,20 +100,20 @@ pub struct HttpRegistry<'cfg> {
95
100
quiet : bool ,
96
101
}
97
102
98
- /// Helper for downloading crates .
103
+ /// State for currently pending index file downloads .
99
104
struct Downloads < ' cfg > {
100
105
/// When a download is started, it is added to this map. The key is a
101
- /// "token" (see `Download::token`). It is removed once the download is
106
+ /// "token" (see [ `Download::token`] ). It is removed once the download is
102
107
/// finished.
103
108
pending : HashMap < usize , ( Download < ' cfg > , EasyHandle ) > ,
104
109
/// Set of paths currently being downloaded.
105
- /// This should stay in sync with `pending`.
110
+ /// This should stay in sync with the `pending` field .
106
111
pending_paths : HashSet < PathBuf > ,
107
112
/// Downloads that have failed and are waiting to retry again later.
108
113
sleeping : SleepTracker < ( Download < ' cfg > , Easy ) > ,
109
114
/// The final result of each download.
110
115
results : HashMap < PathBuf , CargoResult < CompletedDownload > > ,
111
- /// The next ID to use for creating a token (see `Download::token`).
116
+ /// The next ID to use for creating a token (see [ `Download::token`] ).
112
117
next : usize ,
113
118
/// Progress bar.
114
119
progress : RefCell < Option < Progress < ' cfg > > > ,
@@ -119,9 +124,10 @@ struct Downloads<'cfg> {
119
124
blocking_calls : usize ,
120
125
}
121
126
127
+ /// Represents a single index file download, including its progress and retry.
122
128
struct Download < ' cfg > {
123
- /// The token for this download, used as the key of the `Downloads::pending` map
124
- /// and stored in `EasyHandle` as well.
129
+ /// The token for this download, used as the key of the
130
+ /// [`Downloads::pending`] map and stored in [ `EasyHandle`] as well.
125
131
token : usize ,
126
132
127
133
/// The path of the package that we're downloading.
@@ -137,28 +143,39 @@ struct Download<'cfg> {
137
143
retry : Retry < ' cfg > ,
138
144
}
139
145
146
+ /// HTTPS headers [`HttpRegistry`] cares about.
140
147
#[ derive( Default ) ]
141
148
struct Headers {
142
149
last_modified : Option < String > ,
143
150
etag : Option < String > ,
144
151
www_authenticate : Vec < String > ,
152
+ /// We don't care about these headers. Put them here for debugging purpose.
145
153
others : Vec < String > ,
146
154
}
147
155
156
+ /// HTTP status code [`HttpRegistry`] cares about.
148
157
enum StatusCode {
149
158
Success ,
150
159
NotModified ,
151
160
NotFound ,
152
161
Unauthorized ,
153
162
}
154
163
164
+ /// Represents a complete [`Download`] from an HTTP request.
165
+ ///
166
+ /// Usually it is constructed in [`HttpRegistry::handle_completed_downloads`],
167
+ /// and then returns to the caller of [`HttpRegistry::load()`].
155
168
struct CompletedDownload {
156
169
response_code : StatusCode ,
157
170
data : Vec < u8 > ,
158
171
header_map : Headers ,
159
172
}
160
173
161
174
impl < ' cfg > HttpRegistry < ' cfg > {
175
+ /// Creates a HTTP-rebased remote registry for `source_id`.
176
+ ///
177
+ /// * `name` --- Name of a path segment where `.crate` tarballs and the
178
+ /// registry index are stored. Expect to be unique.
162
179
pub fn new (
163
180
source_id : SourceId ,
164
181
config : & ' cfg Config ,
@@ -208,6 +225,7 @@ impl<'cfg> HttpRegistry<'cfg> {
208
225
} )
209
226
}
210
227
228
+ /// Splits HTTP `HEADER: VALUE` to a tuple.
211
229
fn handle_http_header ( buf : & [ u8 ] ) -> Option < ( & str , & str ) > {
212
230
if buf. is_empty ( ) {
213
231
return None ;
@@ -222,6 +240,9 @@ impl<'cfg> HttpRegistry<'cfg> {
222
240
Some ( ( tag, value) )
223
241
}
224
242
243
+ /// Setup the necessary works before the first fetch gets started.
244
+ ///
245
+ /// This is a no-op if called more than one time.
225
246
fn start_fetch ( & mut self ) -> CargoResult < ( ) > {
226
247
if self . fetch_started {
227
248
// We only need to run the setup code once.
@@ -249,6 +270,8 @@ impl<'cfg> HttpRegistry<'cfg> {
249
270
Ok ( ( ) )
250
271
}
251
272
273
+ /// Checks the results inside the [`HttpRegistry::multi`] handle, and
274
+ /// updates relevant state in [`HttpRegistry::downloads`] accordingly.
252
275
fn handle_completed_downloads ( & mut self ) -> CargoResult < ( ) > {
253
276
assert_eq ! (
254
277
self . downloads. pending. len( ) ,
@@ -322,11 +345,15 @@ impl<'cfg> HttpRegistry<'cfg> {
322
345
Ok ( ( ) )
323
346
}
324
347
348
+ /// Constructs the full URL to download a index file.
325
349
fn full_url ( & self , path : & Path ) -> String {
326
350
// self.url always ends with a slash.
327
351
format ! ( "{}{}" , self . url, path. display( ) )
328
352
}
329
353
354
+ /// Check if an index file of `path` is up-to-date.
355
+ ///
356
+ /// The `path` argument is the same as in [`RegistryData::load`].
330
357
fn is_fresh ( & self , path : & Path ) -> bool {
331
358
if !self . requested_update {
332
359
trace ! (
@@ -373,7 +400,7 @@ impl<'cfg> HttpRegistry<'cfg> {
373
400
Ok ( self . registry_config . as_ref ( ) )
374
401
}
375
402
376
- /// Get the registry configuration.
403
+ /// Get the registry configuration from either cache or remote .
377
404
fn config ( & mut self ) -> Poll < CargoResult < & RegistryConfig > > {
378
405
debug ! ( "loading config" ) ;
379
406
let index_path = self . assert_index_locked ( & self . index_path ) ;
@@ -405,6 +432,7 @@ impl<'cfg> HttpRegistry<'cfg> {
405
432
}
406
433
}
407
434
435
+ /// Moves failed [`Download`]s that are ready to retry to the pending queue.
408
436
fn add_sleepers ( & mut self ) -> CargoResult < ( ) > {
409
437
for ( dl, handle) in self . downloads . sleeping . to_retry ( ) {
410
438
let mut handle = self . multi . add ( handle) ?;
@@ -790,6 +818,7 @@ impl<'cfg> RegistryData for HttpRegistry<'cfg> {
790
818
}
791
819
792
820
impl < ' cfg > Downloads < ' cfg > {
821
+ /// Updates the state of the progress bar for downloads.
793
822
fn tick ( & self ) -> CargoResult < ( ) > {
794
823
let mut progress = self . progress . borrow_mut ( ) ;
795
824
let Some ( progress) = progress. as_mut ( ) else { return Ok ( ( ) ) ; } ;
0 commit comments