Skip to content

Commit 5cedce9

Browse files
committed
Auto merge of #12153 - weihanglo:source-doc, r=epage
docs(source): doc comments for `Source` and friends
2 parents 09276c7 + 4f00929 commit 5cedce9

File tree

4 files changed

+146
-20
lines changed

4 files changed

+146
-20
lines changed

Diff for: src/cargo/core/source/mod.rs

+67-20
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
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+
116
use std::collections::hash_map::HashMap;
217
use std::fmt;
318
use std::task::Poll;
@@ -10,32 +25,53 @@ mod source_id;
1025

1126
pub use self::source_id::{GitReference, SourceId};
1227

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
1446
pub trait Source {
15-
/// Returns the `SourceId` corresponding to this source.
47+
/// Returns the [`SourceId`] corresponding to this source.
1648
fn source_id(&self) -> SourceId;
1749

18-
/// Returns the replaced `SourceId` corresponding to this source.
50+
/// Returns the replaced [`SourceId`] corresponding to this source.
1951
fn replaced_source_id(&self) -> SourceId {
2052
self.source_id()
2153
}
2254

23-
/// Returns whether or not this source will return summaries with
55+
/// Returns whether or not this source will return [`Summary`] items with
2456
/// checksums listed.
2557
fn supports_checksums(&self) -> bool;
2658

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.
2961
fn requires_precise(&self) -> bool;
3062

3163
/// 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.
3266
fn query(
3367
&mut self,
3468
dep: &Dependency,
3569
kind: QueryKind,
3670
f: &mut dyn FnMut(Summary),
3771
) -> Poll<CargoResult<()>>;
3872

73+
/// A helper function that collects and returns the result from
74+
/// [`Source::query`] as a list of [`Summary`] items when available.
3975
fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll<CargoResult<Vec<Summary>>> {
4076
let mut ret = Vec::new();
4177
self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret)
@@ -50,6 +86,7 @@ pub trait Source {
5086
/// Fetches the full package for each name and version specified.
5187
fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
5288

89+
/// Fetches the full package **immediately** for each name and version specified.
5390
fn download_now(self: Box<Self>, package: PackageId, config: &Config) -> CargoResult<Package>
5491
where
5592
Self: std::marker::Sized,
@@ -61,7 +98,8 @@ pub trait Source {
6198
Ok(Package::clone(pkg))
6299
}
63100

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>;
65103

66104
/// Generates a unique string which represents the fingerprint of the
67105
/// current state of the source.
@@ -103,56 +141,67 @@ pub trait Source {
103141
/// as yanked. This ignores the yanked whitelist.
104142
fn is_yanked(&mut self, _pkg: PackageId) -> Poll<CargoResult<bool>>;
105143

106-
/// Block until all outstanding Poll::Pending requests are `Poll::Ready`.
144+
/// Block until all outstanding [`Poll::Pending`] requests are [`Poll::Ready`].
107145
///
108146
/// After calling this function, the source should return `Poll::Ready` for
109147
/// any queries that previously returned `Poll::Pending`.
110148
///
111-
/// If no queries previously returned `Poll::Pending`, and `invalidate_cache`
149+
/// If no queries previously returned `Poll::Pending`, and [`Source::invalidate_cache`]
112150
/// was not called, this function should be a no-op.
113151
fn block_until_ready(&mut self) -> CargoResult<()>;
114152
}
115153

154+
/// Defines how a dependency query will be performed for a [`Source`].
116155
#[derive(Copy, Clone, PartialEq, Eq)]
117156
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.
118160
Exact,
161+
/// A query for packages close to the given dependency requirement.
162+
///
119163
/// Each source gets to define what `close` means for it.
164+
///
120165
/// 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.
122168
Fuzzy,
123169
}
124170

171+
/// A download status that represents if a [`Package`] has already been
172+
/// downloaded, or if not then a location to download.
125173
pub enum MaybePackage {
174+
/// The [`Package`] is already downloaded.
126175
Ready(Package),
176+
/// Not yet downloaded. Here is the URL to download the [`Package`] from.
127177
Download {
178+
/// URL to download the content.
128179
url: String,
180+
/// Text to display to the user of what is being downloaded.
129181
descriptor: String,
182+
/// Authorization data that may be required to attach when downloading.
130183
authorization: Option<String>,
131184
},
132185
}
133186

187+
/// A blanket implementation forwards all methods to [`Source`].
134188
impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
135-
/// Forwards to `Source::source_id`.
136189
fn source_id(&self) -> SourceId {
137190
(**self).source_id()
138191
}
139192

140-
/// Forwards to `Source::replaced_source_id`.
141193
fn replaced_source_id(&self) -> SourceId {
142194
(**self).replaced_source_id()
143195
}
144196

145-
/// Forwards to `Source::supports_checksums`.
146197
fn supports_checksums(&self) -> bool {
147198
(**self).supports_checksums()
148199
}
149200

150-
/// Forwards to `Source::requires_precise`.
151201
fn requires_precise(&self) -> bool {
152202
(**self).requires_precise()
153203
}
154204

155-
/// Forwards to `Source::query`.
156205
fn query(
157206
&mut self,
158207
dep: &Dependency,
@@ -170,7 +219,6 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
170219
(**self).set_quiet(quiet)
171220
}
172221

173-
/// Forwards to `Source::download`.
174222
fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
175223
(**self).download(id)
176224
}
@@ -179,12 +227,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
179227
(**self).finish_download(id, data)
180228
}
181229

182-
/// Forwards to `Source::fingerprint`.
183230
fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
184231
(**self).fingerprint(pkg)
185232
}
186233

187-
/// Forwards to `Source::verify`.
188234
fn verify(&self, pkg: PackageId) -> CargoResult<()> {
189235
(**self).verify(pkg)
190236
}
@@ -210,6 +256,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
210256
}
211257
}
212258

259+
/// A blanket implementation forwards all methods to [`Source`].
213260
impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
214261
fn source_id(&self) -> SourceId {
215262
(**self).source_id()
@@ -281,7 +328,7 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
281328
}
282329
}
283330

284-
/// A `HashMap` of `SourceId` -> `Box<Source>`.
331+
/// A [`HashMap`] of [`SourceId`] to `Box<Source>`.
285332
#[derive(Default)]
286333
pub struct SourceMap<'src> {
287334
map: HashMap<SourceId, Box<dyn Source + 'src>>,
@@ -313,7 +360,7 @@ impl<'src> SourceMap<'src> {
313360
self.map.get_mut(&id).map(|s| s.as_mut())
314361
}
315362

316-
/// Like `HashMap::insert`, but derives the `SourceId` key from the `Source`.
363+
/// Like `HashMap::insert`, but derives the [`SourceId`] key from the [`Source`].
317364
pub fn insert(&mut self, source: Box<dyn Source + 'src>) {
318365
let id = source.source_id();
319366
self.map.insert(id, source);

Diff for: src/cargo/sources/directory.rs

+47
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,64 @@ use anyhow::Context as _;
1313
use cargo_util::{paths, Sha256};
1414
use serde::Deserialize;
1515

16+
/// `DirectorySource` contains a number of crates on the file system. It was
17+
/// designed for representing vendored dependencies for `cargo vendor`.
18+
///
19+
/// `DirectorySource` at this moment is just a root directory containing other
20+
/// directories, which contain the source files of packages. Assumptions would
21+
/// be made to determine if a directory should be included as a package of a
22+
/// directory source's:
23+
///
24+
/// * Ignore directories starting with dot `.` (tend to be hidden).
25+
/// * Only when a `Cargo.toml` exists in a directory will it be included as
26+
/// a package. `DirectorySource` at this time only looks at one level of
27+
/// directories and never went deeper.
28+
/// * There must be a [`Checksum`] file `.cargo-checksum.json` file at the same
29+
/// level of `Cargo.toml` to ensure the integrity when a directory source was
30+
/// created (usually by `cargo vendor`). A failure to find or parse a single
31+
/// checksum results in a denial of loading any package in this source.
32+
/// * Otherwise, there is no other restrction of the name of directories. At
33+
/// this moment, it is `cargo vendor` that defines the layout and the name of
34+
/// each directory.
35+
///
36+
/// The file tree of a directory source may look like:
37+
///
38+
/// ```text
39+
/// [source root]
40+
/// ├── a-valid-crate/
41+
/// │ ├── src/
42+
/// │ ├── .cargo-checksum.json
43+
/// │ └── Cargo.toml
44+
/// ├── .ignored-a-dot-crate/
45+
/// │ ├── src/
46+
/// │ ├── .cargo-checksum.json
47+
/// │ └── Cargo.toml
48+
/// ├── skipped-no-manifest/
49+
/// │ ├── src/
50+
/// │ └── .cargo-checksum.json
51+
/// └── no-checksum-so-fails-the-entire-source-reading/
52+
/// └── Cargo.toml
53+
/// ```
1654
pub struct DirectorySource<'cfg> {
55+
/// The unique identifier of this source.
1756
source_id: SourceId,
57+
/// The root path of this source.
1858
root: PathBuf,
59+
/// Packages that this sources has discovered.
1960
packages: HashMap<PackageId, (Package, Checksum)>,
2061
config: &'cfg Config,
2162
updated: bool,
2263
}
2364

65+
/// The checksum file to ensure the integrity of a package in a directory source.
66+
///
67+
/// The file name is simply `.cargo-checksum.json`. The checksum algorithm as
68+
/// of now is SHA256.
2469
#[derive(Deserialize)]
2570
struct Checksum {
71+
/// Checksum of the package. Normally it is computed from the `.crate` file.
2672
package: Option<String>,
73+
/// Checksums of each source file.
2774
files: HashMap<String, String>,
2875
}
2976

Diff for: src/cargo/sources/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
//! Implementations of `Source` trait.
2+
//!
3+
//! Cargo provides several built-in implementations of [`Source`] trait. Namely,
4+
//!
5+
//! * [`RegistrySource`] --- A source that provides an index for people to query
6+
//! a crate's metadata, and fetch files for a certain crate. crates.io falls
7+
//! into this category. So do local registry and sparse registry.
8+
//! * [`DirectorySource`] --- Files are downloaded ahead of time. Primarily
9+
//! designed for crates generated from `cargo vendor`.
10+
//! * [`GitSource`] --- This gets crate information from a git repository.
11+
//! * [`PathSource`] --- This gets crate information from a local path on the
12+
//! filesystem.
13+
//! * [`ReplacedSource`] --- This manages the [source replacement] feature,
14+
//! redirecting operations on the original source to the replacement.
15+
//!
16+
//! This module also contains [`SourceConfigMap`], which is effectively the
17+
//! representation of the `[source.*]` value in Cargo configuration.
18+
//!
19+
//! [`Source`]: crate::core::Source
20+
//! [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
21+
122
pub use self::config::SourceConfigMap;
223
pub use self::directory::DirectorySource;
324
pub use self::git::GitSource;

Diff for: src/cargo/sources/replaced.rs

+11
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@ use std::task::Poll;
55

66
use anyhow::Context as _;
77

8+
/// A source that replaces one source with the other. This manages the [source
9+
/// replacement] feature.
10+
///
11+
/// The implementation is merely redirecting from the original to the replacement.
12+
///
13+
/// [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
814
pub struct ReplacedSource<'cfg> {
15+
/// The identifier of the original source.
916
to_replace: SourceId,
17+
/// The identifier of the new replacement source.
1018
replace_with: SourceId,
1119
inner: Box<dyn Source + 'cfg>,
1220
}
1321

1422
impl<'cfg> ReplacedSource<'cfg> {
23+
/// Creates a replaced source.
24+
///
25+
/// The `src` argument is the new replacement source.
1526
pub fn new(
1627
to_replace: SourceId,
1728
replace_with: SourceId,

0 commit comments

Comments
 (0)