1
+ //! Fundamental types and traits for sources of Cargo packages.
2
+ //!
3
+ //! A source is a provider that contains source files and metadata of packages.
4
+ //! It provides a number of methods to fetch those package informations, for
5
+ //! example, querying metadata or downloading files for a package. These
6
+ //! informations then can be used as dependencies for other Cargo packages.
7
+ //!
8
+ //! Notably, this module contains
9
+ //!
10
+ //! * [`Source`] trait as an abstraction of different sources
11
+ //! * [`SourceMap`] struct as a map of all available sources
12
+ //! * [`SourceId`] struct as an unique identifier for a certain source
13
+ //!
14
+ //! For implementations of `Source` trait, see [`crate::sources`].
15
+
1
16
use std:: collections:: hash_map:: HashMap ;
2
17
use std:: fmt;
3
18
use std:: task:: Poll ;
@@ -10,32 +25,53 @@ mod source_id;
10
25
11
26
pub use self :: source_id:: { GitReference , SourceId } ;
12
27
13
- /// Something that finds and downloads remote packages based on names and versions.
28
+ /// An abstraction of different sources of Cargo packages.
29
+ ///
30
+ /// The [`Source`] trait generalizes the API to interact with these providers.
31
+ /// For example,
32
+ ///
33
+ /// * [`Source::query`] is for querying package metadata on a given
34
+ /// [`Dependency`] requested by a Cargo manifest.
35
+ /// * [`Source::download`] is for fetching the full package information on
36
+ /// given names and versions.
37
+ /// * [`Source::source_id`] is for defining an unique identifier of a source to
38
+ /// distinguish one source from another, keeping Cargo safe from [dependency
39
+ /// confusion attack].
40
+ ///
41
+ /// Normally, developers don't need to implement their own [`Source`]s. Cargo
42
+ /// provides several kinds of sources implementations that should cover almost
43
+ /// all use cases. See [`crate::sources`] for implementations provided by Cargo.
44
+ ///
45
+ /// [dependency confusion attack]: https://medium.com/@alex.birsan/dependency-confusion-4a5d60fec610
14
46
pub trait Source {
15
- /// Returns the `SourceId` corresponding to this source.
47
+ /// Returns the [ `SourceId`] corresponding to this source.
16
48
fn source_id ( & self ) -> SourceId ;
17
49
18
- /// Returns the replaced `SourceId` corresponding to this source.
50
+ /// Returns the replaced [ `SourceId`] corresponding to this source.
19
51
fn replaced_source_id ( & self ) -> SourceId {
20
52
self . source_id ( )
21
53
}
22
54
23
- /// Returns whether or not this source will return summaries with
55
+ /// Returns whether or not this source will return [`Summary`] items with
24
56
/// checksums listed.
25
57
fn supports_checksums ( & self ) -> bool ;
26
58
27
- /// Returns whether or not this source will return summaries with
28
- /// the `precise` field in the source id listed.
59
+ /// Returns whether or not this source will return [`Summary`] items with
60
+ /// the `precise` field in the [`SourceId`] listed.
29
61
fn requires_precise ( & self ) -> bool ;
30
62
31
63
/// Attempts to find the packages that match a dependency request.
64
+ ///
65
+ /// The `f` argument is expected to get called when any [`Summary`] becomes available.
32
66
fn query (
33
67
& mut self ,
34
68
dep : & Dependency ,
35
69
kind : QueryKind ,
36
70
f : & mut dyn FnMut ( Summary ) ,
37
71
) -> Poll < CargoResult < ( ) > > ;
38
72
73
+ /// A helper function that collects and returns the result from
74
+ /// [`Source::query`] as a list of [`Summary`] items when available.
39
75
fn query_vec ( & mut self , dep : & Dependency , kind : QueryKind ) -> Poll < CargoResult < Vec < Summary > > > {
40
76
let mut ret = Vec :: new ( ) ;
41
77
self . query ( dep, kind, & mut |s| ret. push ( s) ) . map_ok ( |_| ret)
@@ -50,6 +86,7 @@ pub trait Source {
50
86
/// Fetches the full package for each name and version specified.
51
87
fn download ( & mut self , package : PackageId ) -> CargoResult < MaybePackage > ;
52
88
89
+ /// Fetches the full package **immediately** for each name and version specified.
53
90
fn download_now ( self : Box < Self > , package : PackageId , config : & Config ) -> CargoResult < Package >
54
91
where
55
92
Self : std:: marker:: Sized ,
@@ -61,7 +98,8 @@ pub trait Source {
61
98
Ok ( Package :: clone ( pkg) )
62
99
}
63
100
64
- fn finish_download ( & mut self , package : PackageId , contents : Vec < u8 > ) -> CargoResult < Package > ;
101
+ /// Finalizes the download contents of the given [`PackageId`] to a [`Package`].
102
+ fn finish_download ( & mut self , pkg_id : PackageId , contents : Vec < u8 > ) -> CargoResult < Package > ;
65
103
66
104
/// Generates a unique string which represents the fingerprint of the
67
105
/// current state of the source.
@@ -103,56 +141,67 @@ pub trait Source {
103
141
/// as yanked. This ignores the yanked whitelist.
104
142
fn is_yanked ( & mut self , _pkg : PackageId ) -> Poll < CargoResult < bool > > ;
105
143
106
- /// Block until all outstanding Poll::Pending requests are `Poll::Ready`.
144
+ /// Block until all outstanding [` Poll::Pending`] requests are [ `Poll::Ready`] .
107
145
///
108
146
/// After calling this function, the source should return `Poll::Ready` for
109
147
/// any queries that previously returned `Poll::Pending`.
110
148
///
111
- /// If no queries previously returned `Poll::Pending`, and ` invalidate_cache`
149
+ /// If no queries previously returned `Poll::Pending`, and [`Source:: invalidate_cache`]
112
150
/// was not called, this function should be a no-op.
113
151
fn block_until_ready ( & mut self ) -> CargoResult < ( ) > ;
114
152
}
115
153
154
+ /// Defines how a dependency query will be performed for a [`Source`].
116
155
#[ derive( Copy , Clone , PartialEq , Eq ) ]
117
156
pub enum QueryKind {
157
+ /// A query for packages exactly matching the given dependency requirement.
158
+ ///
159
+ /// Each source gets to define what `exact` means for it.
118
160
Exact ,
161
+ /// A query for packages close to the given dependency requirement.
162
+ ///
119
163
/// Each source gets to define what `close` means for it.
164
+ ///
120
165
/// Path/Git sources may return all dependencies that are at that URI,
121
- /// whereas an `Index` source may return dependencies that have the same canonicalization.
166
+ /// whereas an `Registry` source may return dependencies that have the same
167
+ /// canonicalization.
122
168
Fuzzy ,
123
169
}
124
170
171
+ /// A download status that represents if a [`Package`] has already been
172
+ /// downloaded, or if not then a location to download.
125
173
pub enum MaybePackage {
174
+ /// The [`Package`] is already downloaded.
126
175
Ready ( Package ) ,
176
+ /// Not yet downloaded. Here is the URL to download the [`Package`] from.
127
177
Download {
178
+ /// URL to download the content.
128
179
url : String ,
180
+ /// Text to display to the user of what is being downloaded.
129
181
descriptor : String ,
182
+ /// Authorization data that may be required to attach when downloading.
130
183
authorization : Option < String > ,
131
184
} ,
132
185
}
133
186
187
+ /// A blanket implementation forwards all methods to [`Source`].
134
188
impl < ' a , T : Source + ?Sized + ' a > Source for Box < T > {
135
- /// Forwards to `Source::source_id`.
136
189
fn source_id ( & self ) -> SourceId {
137
190
( * * self ) . source_id ( )
138
191
}
139
192
140
- /// Forwards to `Source::replaced_source_id`.
141
193
fn replaced_source_id ( & self ) -> SourceId {
142
194
( * * self ) . replaced_source_id ( )
143
195
}
144
196
145
- /// Forwards to `Source::supports_checksums`.
146
197
fn supports_checksums ( & self ) -> bool {
147
198
( * * self ) . supports_checksums ( )
148
199
}
149
200
150
- /// Forwards to `Source::requires_precise`.
151
201
fn requires_precise ( & self ) -> bool {
152
202
( * * self ) . requires_precise ( )
153
203
}
154
204
155
- /// Forwards to `Source::query`.
156
205
fn query (
157
206
& mut self ,
158
207
dep : & Dependency ,
@@ -170,7 +219,6 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
170
219
( * * self ) . set_quiet ( quiet)
171
220
}
172
221
173
- /// Forwards to `Source::download`.
174
222
fn download ( & mut self , id : PackageId ) -> CargoResult < MaybePackage > {
175
223
( * * self ) . download ( id)
176
224
}
@@ -179,12 +227,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
179
227
( * * self ) . finish_download ( id, data)
180
228
}
181
229
182
- /// Forwards to `Source::fingerprint`.
183
230
fn fingerprint ( & self , pkg : & Package ) -> CargoResult < String > {
184
231
( * * self ) . fingerprint ( pkg)
185
232
}
186
233
187
- /// Forwards to `Source::verify`.
188
234
fn verify ( & self , pkg : PackageId ) -> CargoResult < ( ) > {
189
235
( * * self ) . verify ( pkg)
190
236
}
@@ -210,6 +256,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
210
256
}
211
257
}
212
258
259
+ /// A blanket implementation forwards all methods to [`Source`].
213
260
impl < ' a , T : Source + ?Sized + ' a > Source for & ' a mut T {
214
261
fn source_id ( & self ) -> SourceId {
215
262
( * * self ) . source_id ( )
@@ -281,7 +328,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
281
328
}
282
329
}
283
330
284
- /// A `HashMap` of `SourceId` -> `Box<Source>`.
331
+ /// A [ `HashMap`] of [ `SourceId`] to `Box<Source>`.
285
332
#[ derive( Default ) ]
286
333
pub struct SourceMap < ' src > {
287
334
map : HashMap < SourceId , Box < dyn Source + ' src > > ,
@@ -313,7 +360,7 @@ impl<'src> SourceMap<'src> {
313
360
self . map . get_mut ( & id) . map ( |s| s. as_mut ( ) )
314
361
}
315
362
316
- /// Like `HashMap::insert`, but derives the `SourceId` key from the `Source`.
363
+ /// Like `HashMap::insert`, but derives the [ `SourceId`] key from the [ `Source`] .
317
364
pub fn insert ( & mut self , source : Box < dyn Source + ' src > ) {
318
365
let id = source. source_id ( ) ;
319
366
self . map . insert ( id, source) ;
0 commit comments