| use crate::sources::IndexSummary; |
| use crate::sources::source::MaybePackage; |
| use crate::sources::source::QueryKind; |
| use crate::sources::source::Source; |
| use crate::util::errors::CargoResult; |
| use crate::workspace::{Dependency, Package, PackageId, SourceId}; |
| |
| /// A source that replaces one source with the other. This manages the [source |
| /// replacement] feature. |
| /// |
| /// The implementation is merely redirecting from the original to the replacement. |
| /// |
| /// [source replacement]: https://doc.rust-lang.org/nightly/cargo/reference/source-replacement.html |
| pub struct ReplacedSource<'gctx> { |
| /// The identifier of the original source. |
| to_replace: SourceId, |
| /// The identifier of the new replacement source. |
| replace_with: SourceId, |
| inner: Box<dyn Source + 'gctx>, |
| } |
| |
| impl<'gctx> ReplacedSource<'gctx> { |
| /// Creates a replaced source. |
| /// |
| /// The `src` argument is the new replacement source. |
| pub fn new( |
| to_replace: SourceId, |
| replace_with: SourceId, |
| src: Box<dyn Source + 'gctx>, |
| ) -> ReplacedSource<'gctx> { |
| ReplacedSource { |
| to_replace, |
| replace_with, |
| inner: src, |
| } |
| } |
| |
| /// Is this source a built-in replacement of crates.io? |
| /// |
| /// Built-in source replacement of crates.io for sparse registry or tests |
| /// should not show messages indicating source replacement. |
| fn is_builtin_replacement(&self) -> bool { |
| self.replace_with.is_crates_io() && self.to_replace.is_crates_io() |
| } |
| } |
| |
| #[async_trait::async_trait(?Send)] |
| impl<'gctx> Source for ReplacedSource<'gctx> { |
| fn source_id(&self) -> SourceId { |
| self.to_replace |
| } |
| |
| fn replaced_source_id(&self) -> SourceId { |
| self.replace_with |
| } |
| |
| fn supports_checksums(&self) -> bool { |
| self.inner.supports_checksums() |
| } |
| |
| fn requires_precise(&self) -> bool { |
| self.inner.requires_precise() |
| } |
| |
| async fn query( |
| &self, |
| dep: &Dependency, |
| kind: QueryKind, |
| f: &mut dyn FnMut(IndexSummary), |
| ) -> CargoResult<()> { |
| let (replace_with, to_replace) = (self.replace_with, self.to_replace); |
| let dep = dep.clone().map_source(to_replace, replace_with); |
| |
| self.inner |
| .query(&dep, kind, &mut |summary| { |
| f(summary.map_summary(|s| s.map_source(replace_with, to_replace))) |
| }) |
| .await |
| .map_err(|e| { |
| if self.is_builtin_replacement() { |
| e |
| } else { |
| e.context(format!( |
| "failed to query replaced source {}", |
| self.to_replace |
| )) |
| } |
| }) |
| } |
| |
| fn invalidate_cache(&self) { |
| self.inner.invalidate_cache() |
| } |
| |
| fn set_quiet(&mut self, quiet: bool) { |
| self.inner.set_quiet(quiet); |
| } |
| |
| async fn download(&self, id: PackageId) -> CargoResult<MaybePackage> { |
| let id = id.with_source_id(self.replace_with); |
| let pkg = self.inner.download(id).await.map_err(|e| { |
| if self.is_builtin_replacement() { |
| e |
| } else { |
| e.context(format!( |
| "failed to download replaced source {}", |
| self.to_replace |
| )) |
| } |
| })?; |
| Ok(match pkg { |
| MaybePackage::Ready(pkg) => { |
| MaybePackage::Ready(pkg.map_source(self.replace_with, self.to_replace)) |
| } |
| other @ MaybePackage::Download { .. } => other, |
| }) |
| } |
| |
| async fn finish_download(&self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> { |
| let id = id.with_source_id(self.replace_with); |
| let pkg = self.inner.finish_download(id, data).await.map_err(|e| { |
| if self.is_builtin_replacement() { |
| e |
| } else { |
| e.context(format!( |
| "failed to download replaced source {}", |
| self.to_replace |
| )) |
| } |
| })?; |
| Ok(pkg.map_source(self.replace_with, self.to_replace)) |
| } |
| |
| fn fingerprint(&self, id: &Package) -> CargoResult<String> { |
| self.inner.fingerprint(id) |
| } |
| |
| fn verify(&self, id: PackageId) -> CargoResult<()> { |
| let id = id.with_source_id(self.replace_with); |
| self.inner.verify(id) |
| } |
| |
| fn describe(&self) -> String { |
| if self.is_builtin_replacement() { |
| self.inner.describe() |
| } else { |
| format!( |
| "{} (which is replacing {})", |
| self.inner.describe(), |
| self.to_replace |
| ) |
| } |
| } |
| |
| fn is_replaced(&self) -> bool { |
| !self.is_builtin_replacement() |
| } |
| } |