#
cargo/sources/
replaced.rs

    1use crate::core::{Dependency, Package, PackageId, SourceId};
    2use crate::sources::IndexSummary;
    3use crate::sources::source::MaybePackage;
    4use crate::sources::source::QueryKind;
    5use crate::sources::source::Source;
    6use crate::util::errors::CargoResult;
    7use std::task::Poll;
    8
    9/// A source that replaces one source with the other. This manages the [source
    10/// replacement] feature.
    11///
    12/// The implementation is merely redirecting from the original to the replacement.
    13///
    14/// [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html
    15pub struct ReplacedSource<'gctx> {
    16    /// The identifier of the original source.
    17    to_replace: SourceId,
    18    /// The identifier of the new replacement source.
    19    replace_with: SourceId,
    20    inner: Box<dyn Source + 'gctx>,
    21}
    22
    23impl<'gctx> ReplacedSource<'gctx> {
    24    /// Creates a replaced source.
    25    ///
    26    /// The `src` argument is the new replacement source.
    27    pub fn new(
    28        to_replace: SourceId,
    29        replace_with: SourceId,
    30        src: Box<dyn Source + 'gctx>,
    31    ) -> ReplacedSource<'gctx> {
    32        ReplacedSource {
    33            to_replace,
    34            replace_with,
    35            inner: src,
    36        }
    37    }
    38
    39    /// Is this source a built-in replacement of crates.io?
    40    ///
    41    /// Built-in source replacement of crates.io for sparse registry or tests
    42    /// should not show messages indicating source replacement.
    43    fn is_builtin_replacement(&self) -> bool {
    44        self.replace_with.is_crates_io() && self.to_replace.is_crates_io()
    45    }
    46}
    47
    48impl<'gctx> Source for ReplacedSource<'gctx> {
    49    fn source_id(&self) -> SourceId {
    50        self.to_replace
    51    }
    52
    53    fn replaced_source_id(&self) -> SourceId {
    54        self.replace_with
    55    }
    56
    57    fn supports_checksums(&self) -> bool {
    58        self.inner.supports_checksums()
    59    }
    60
    61    fn requires_precise(&self) -> bool {
    62        self.inner.requires_precise()
    63    }
    64
    65    fn query(
    66        &mut self,
    67        dep: &Dependency,
    68        kind: QueryKind,
    69        f: &mut dyn FnMut(IndexSummary),
    70    ) -> Poll<CargoResult<()>> {
    71        let (replace_with, to_replace) = (self.replace_with, self.to_replace);
    72        let dep = dep.clone().map_source(to_replace, replace_with);
    73
    74        self.inner
    75            .query(&dep, kind, &mut |summary| {
    76                f(summary.map_summary(|s| s.map_source(replace_with, to_replace)))
    77            })
    78            .map_err(|e| {
    79                if self.is_builtin_replacement() {
    80                    e
    81                } else {
    82                    e.context(format!(
    83                        "failed to query replaced source {}",
    84                        self.to_replace
    85                    ))
    86                }
    87            })
    88    }
    89
    90    fn invalidate_cache(&mut self) {
    91        self.inner.invalidate_cache()
    92    }
    93
    94    fn set_quiet(&mut self, quiet: bool) {
    95        self.inner.set_quiet(quiet);
    96    }
    97
    98    fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
    99        let id = id.with_source_id(self.replace_with);
    100        let pkg = self.inner.download(id).map_err(|e| {
    101            if self.is_builtin_replacement() {
    102                e
    103            } else {
    104                e.context(format!(
    105                    "failed to download replaced source {}",
    106                    self.to_replace
    107                ))
    108            }
    109        })?;
    110        Ok(match pkg {
    111            MaybePackage::Ready(pkg) => {
    112                MaybePackage::Ready(pkg.map_source(self.replace_with, self.to_replace))
    113            }
    114            other @ MaybePackage::Download { .. } => other,
    115        })
    116    }
    117
    118    fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
    119        let id = id.with_source_id(self.replace_with);
    120        let pkg = self.inner.finish_download(id, data).map_err(|e| {
    121            if self.is_builtin_replacement() {
    122                e
    123            } else {
    124                e.context(format!(
    125                    "failed to download replaced source {}",
    126                    self.to_replace
    127                ))
    128            }
    129        })?;
    130        Ok(pkg.map_source(self.replace_with, self.to_replace))
    131    }
    132
    133    fn fingerprint(&self, id: &Package) -> CargoResult<String> {
    134        self.inner.fingerprint(id)
    135    }
    136
    137    fn verify(&self, id: PackageId) -> CargoResult<()> {
    138        let id = id.with_source_id(self.replace_with);
    139        self.inner.verify(id)
    140    }
    141
    142    fn describe(&self) -> String {
    143        if self.is_builtin_replacement() {
    144            self.inner.describe()
    145        } else {
    146            format!(
    147                "{} (which is replacing {})",
    148                self.inner.describe(),
    149                self.to_replace
    150            )
    151        }
    152    }
    153
    154    fn is_replaced(&self) -> bool {
    155        !self.is_builtin_replacement()
    156    }
    157
    158    fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
    159        let pkgs = pkgs
    160            .iter()
    161            .map(|id| id.with_source_id(self.replace_with))
    162            .collect::<Vec<_>>();
    163        self.inner.add_to_yanked_whitelist(&pkgs);
    164    }
    165
    166    fn is_yanked(&mut self, pkg: PackageId) -> Poll<CargoResult<bool>> {
    167        self.inner.is_yanked(pkg)
    168    }
    169
    170    fn block_until_ready(&mut self) -> CargoResult<()> {
    171        self.inner.block_until_ready().map_err(|e| {
    172            if self.is_builtin_replacement() {
    173                e
    174            } else {
    175                e.context(format!(
    176                    "failed to update replaced source {}",
    177                    self.to_replace
    178                ))
    179            }
    180        })
    181    }
    182}