|
85 | 85 | //! ```
|
86 | 86 | //!
|
87 | 87 | //! The root of the index contains a `config.json` file with a few entries
|
88 |
| -//! corresponding to the registry (see `RegistryConfig` below). |
| 88 | +//! corresponding to the registry (see [`RegistryConfig`] below). |
89 | 89 | //!
|
90 | 90 | //! Otherwise, there are three numbered directories (1, 2, 3) for crates with
|
91 | 91 | //! names 1, 2, and 3 characters in length. The 1/2 directories simply have the
|
@@ -189,16 +189,42 @@ const VERSION_TEMPLATE: &str = "{version}";
|
189 | 189 | const PREFIX_TEMPLATE: &str = "{prefix}";
|
190 | 190 | const LOWER_PREFIX_TEMPLATE: &str = "{lowerprefix}";
|
191 | 191 |
|
| 192 | +/// A "source" for a [local](local::LocalRegistry) or |
| 193 | +/// [remote](remote::RemoteRegistry) registry. |
| 194 | +/// |
| 195 | +/// This contains common functionality that is shared between the two registry |
| 196 | +/// kinds, with the registry-specific logic implemented as part of the |
| 197 | +/// [`RegistryData`] trait referenced via the `ops` field. |
192 | 198 | pub struct RegistrySource<'cfg> {
|
193 | 199 | source_id: SourceId,
|
| 200 | + /// The path where crate files are extracted (`$CARGO_HOME/registry/src/$REG-HASH`). |
194 | 201 | src_path: Filesystem,
|
| 202 | + /// Local reference to [`Config`] for convenience. |
195 | 203 | config: &'cfg Config,
|
| 204 | + /// Whether or not the index has been updated. |
| 205 | + /// |
| 206 | + /// This is used as an optimization to avoid updating if not needed, such |
| 207 | + /// as `Cargo.lock` already exists and the index already contains the |
| 208 | + /// locked entries. Or, to avoid updating multiple times. |
| 209 | + /// |
| 210 | + /// Only remote registries really need to update. Local registries only |
| 211 | + /// check that the index exists. |
196 | 212 | updated: bool,
|
| 213 | + /// Abstraction for interfacing to the different registry kinds. |
197 | 214 | ops: Box<dyn RegistryData + 'cfg>,
|
| 215 | + /// Interface for managing the on-disk index. |
198 | 216 | index: index::RegistryIndex<'cfg>,
|
| 217 | + /// A set of packages that should be allowed to be used, even if they are |
| 218 | + /// yanked. |
| 219 | + /// |
| 220 | + /// This is populated from the entries in `Cargo.lock` to ensure that |
| 221 | + /// `cargo update -p somepkg` won't unlock yanked entries in `Cargo.lock`. |
| 222 | + /// Otherwise, the resolver would think that those entries no longer |
| 223 | + /// exist, and it would trigger updates to unrelated packages. |
199 | 224 | yanked_whitelist: HashSet<PackageId>,
|
200 | 225 | }
|
201 | 226 |
|
| 227 | +/// The `config.json` file stored in the index. |
202 | 228 | #[derive(Deserialize)]
|
203 | 229 | pub struct RegistryConfig {
|
204 | 230 | /// Download endpoint for all crates.
|
@@ -278,18 +304,7 @@ fn escaped_char_in_json() {
|
278 | 304 | .unwrap();
|
279 | 305 | }
|
280 | 306 |
|
281 |
| -#[derive(Deserialize)] |
282 |
| -#[serde(field_identifier, rename_all = "lowercase")] |
283 |
| -enum Field { |
284 |
| - Name, |
285 |
| - Vers, |
286 |
| - Deps, |
287 |
| - Features, |
288 |
| - Cksum, |
289 |
| - Yanked, |
290 |
| - Links, |
291 |
| -} |
292 |
| - |
| 307 | +/// A dependency as encoded in the index JSON. |
293 | 308 | #[derive(Deserialize)]
|
294 | 309 | struct RegistryDependency<'a> {
|
295 | 310 | name: InternedString,
|
@@ -369,30 +384,108 @@ impl<'a> RegistryDependency<'a> {
|
369 | 384 | }
|
370 | 385 | }
|
371 | 386 |
|
| 387 | +/// An abstract interface to handle both a [local](local::LocalRegistry) and |
| 388 | +/// [remote](remote::RemoteRegistry) registry. |
| 389 | +/// |
| 390 | +/// This allows [`RegistrySource`] to abstractly handle both registry kinds. |
372 | 391 | pub trait RegistryData {
|
| 392 | + /// Performs initialization for the registry. |
| 393 | + /// |
| 394 | + /// This should be safe to call multiple times, the implementation is |
| 395 | + /// expected to not do any work if it is already prepared. |
373 | 396 | fn prepare(&self) -> CargoResult<()>;
|
| 397 | + |
| 398 | + /// Returns the path to the index. |
| 399 | + /// |
| 400 | + /// Note that different registries store the index in different formats |
| 401 | + /// (remote=git, local=files). |
374 | 402 | fn index_path(&self) -> &Filesystem;
|
| 403 | + |
| 404 | + /// Loads the JSON for a specific named package from the index. |
| 405 | + /// |
| 406 | + /// * `root` is the root path to the index. |
| 407 | + /// * `path` is the relative path to the package to load (like `ca/rg/cargo`). |
| 408 | + /// * `data` is a callback that will receive the raw bytes of the index JSON file. |
375 | 409 | fn load(
|
376 | 410 | &self,
|
377 | 411 | root: &Path,
|
378 | 412 | path: &Path,
|
379 | 413 | data: &mut dyn FnMut(&[u8]) -> CargoResult<()>,
|
380 | 414 | ) -> CargoResult<()>;
|
| 415 | + |
| 416 | + /// Loads the `config.json` file and returns it. |
| 417 | + /// |
| 418 | + /// Local registries don't have a config, and return `None`. |
381 | 419 | fn config(&mut self) -> CargoResult<Option<RegistryConfig>>;
|
| 420 | + |
| 421 | + /// Updates the index. |
| 422 | + /// |
| 423 | + /// For a remote registry, this updates the index over the network. Local |
| 424 | + /// registries only check that the index exists. |
382 | 425 | fn update_index(&mut self) -> CargoResult<()>;
|
| 426 | + |
| 427 | + /// Prepare to start downloading a `.crate` file. |
| 428 | + /// |
| 429 | + /// Despite the name, this doesn't actually download anything. If the |
| 430 | + /// `.crate` is already downloaded, then it returns [`MaybeLock::Ready`]. |
| 431 | + /// If it hasn't been downloaded, then it returns [`MaybeLock::Download`] |
| 432 | + /// which contains the URL to download. The [`crate::core::package::Download`] |
| 433 | + /// system handles the actual download process. After downloading, it |
| 434 | + /// calls [`finish_download`] to save the downloaded file. |
| 435 | + /// |
| 436 | + /// `checksum` is currently only used by local registries to verify the |
| 437 | + /// file contents (because local registries never actually download |
| 438 | + /// anything). Remote registries will validate the checksum in |
| 439 | + /// `finish_download`. For already downloaded `.crate` files, it does not |
| 440 | + /// validate the checksum, assuming the filesystem does not suffer from |
| 441 | + /// corruption or manipulation. |
383 | 442 | fn download(&mut self, pkg: PackageId, checksum: &str) -> CargoResult<MaybeLock>;
|
| 443 | + |
| 444 | + /// Finish a download by saving a `.crate` file to disk. |
| 445 | + /// |
| 446 | + /// After [`crate::core::package::Download`] has finished a download, |
| 447 | + /// it will call this to save the `.crate` file. This is only relevant |
| 448 | + /// for remote registries. This should validate the checksum and save |
| 449 | + /// the given data to the on-disk cache. |
| 450 | + /// |
| 451 | + /// Returns a [`File`] handle to the `.crate` file, positioned at the start. |
384 | 452 | fn finish_download(&mut self, pkg: PackageId, checksum: &str, data: &[u8])
|
385 | 453 | -> CargoResult<File>;
|
386 | 454 |
|
| 455 | + /// Returns whether or not the `.crate` file is already downloaded. |
387 | 456 | fn is_crate_downloaded(&self, _pkg: PackageId) -> bool {
|
388 | 457 | true
|
389 | 458 | }
|
| 459 | + |
| 460 | + /// Validates that the global package cache lock is held. |
| 461 | + /// |
| 462 | + /// Given the [`Filesystem`], this will make sure that the package cache |
| 463 | + /// lock is held. If not, it will panic. See |
| 464 | + /// [`Config::acquire_package_cache_lock`] for acquiring the global lock. |
| 465 | + /// |
| 466 | + /// Returns the [`Path`] to the [`Filesystem`]. |
390 | 467 | fn assert_index_locked<'a>(&self, path: &'a Filesystem) -> &'a Path;
|
| 468 | + |
| 469 | + /// Returns the current "version" of the index. |
| 470 | + /// |
| 471 | + /// For local registries, this returns `None` because there is no |
| 472 | + /// versioning. For remote registries, this returns the SHA hash of the |
| 473 | + /// git index on disk (or None if the index hasn't been downloaded yet). |
| 474 | + /// |
| 475 | + /// This is used by index caching to check if the cache is out of date. |
391 | 476 | fn current_version(&self) -> Option<InternedString>;
|
392 | 477 | }
|
393 | 478 |
|
| 479 | +/// The status of [`RegistryData::download`] which indicates if a `.crate` |
| 480 | +/// file has already been downloaded, or if not then the URL to download. |
394 | 481 | pub enum MaybeLock {
|
| 482 | + /// The `.crate` file is already downloaded. [`File`] is a handle to the |
| 483 | + /// opened `.crate` file on the filesystem. |
395 | 484 | Ready(File),
|
| 485 | + /// The `.crate` file is not downloaded, here's the URL to download it from. |
| 486 | + /// |
| 487 | + /// `descriptor` is just a text string to display to the user of what is |
| 488 | + /// being downloaded. |
396 | 489 | Download { url: String, descriptor: String },
|
397 | 490 | }
|
398 | 491 |
|
|
0 commit comments