cargo/sources/
replaced.rs1use 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;
7
8pub struct ReplacedSource<'gctx> {
15 to_replace: SourceId,
17 replace_with: SourceId,
19 inner: Box<dyn Source + 'gctx>,
20}
21
22impl<'gctx> ReplacedSource<'gctx> {
23 pub fn new(
27 to_replace: SourceId,
28 replace_with: SourceId,
29 src: Box<dyn Source + 'gctx>,
30 ) -> ReplacedSource<'gctx> {
31 ReplacedSource {
32 to_replace,
33 replace_with,
34 inner: src,
35 }
36 }
37
38 fn is_builtin_replacement(&self) -> bool {
43 self.replace_with.is_crates_io() && self.to_replace.is_crates_io()
44 }
45}
46
47#[async_trait::async_trait(?Send)]
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 async fn query(
66 &self,
67 dep: &Dependency,
68 kind: QueryKind,
69 f: &mut dyn FnMut(IndexSummary),
70 ) -> 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 .await
79 .map_err(|e| {
80 if self.is_builtin_replacement() {
81 e
82 } else {
83 e.context(format!(
84 "failed to query replaced source {}",
85 self.to_replace
86 ))
87 }
88 })
89 }
90
91 fn invalidate_cache(&self) {
92 self.inner.invalidate_cache()
93 }
94
95 fn set_quiet(&mut self, quiet: bool) {
96 self.inner.set_quiet(quiet);
97 }
98
99 fn download(&self, id: PackageId) -> CargoResult<MaybePackage> {
100 let id = id.with_source_id(self.replace_with);
101 let pkg = self.inner.download(id).map_err(|e| {
102 if self.is_builtin_replacement() {
103 e
104 } else {
105 e.context(format!(
106 "failed to download replaced source {}",
107 self.to_replace
108 ))
109 }
110 })?;
111 Ok(match pkg {
112 MaybePackage::Ready(pkg) => {
113 MaybePackage::Ready(pkg.map_source(self.replace_with, self.to_replace))
114 }
115 other @ MaybePackage::Download { .. } => other,
116 })
117 }
118
119 fn finish_download(&self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
120 let id = id.with_source_id(self.replace_with);
121 let pkg = self.inner.finish_download(id, data).map_err(|e| {
122 if self.is_builtin_replacement() {
123 e
124 } else {
125 e.context(format!(
126 "failed to download replaced source {}",
127 self.to_replace
128 ))
129 }
130 })?;
131 Ok(pkg.map_source(self.replace_with, self.to_replace))
132 }
133
134 fn fingerprint(&self, id: &Package) -> CargoResult<String> {
135 self.inner.fingerprint(id)
136 }
137
138 fn verify(&self, id: PackageId) -> CargoResult<()> {
139 let id = id.with_source_id(self.replace_with);
140 self.inner.verify(id)
141 }
142
143 fn describe(&self) -> String {
144 if self.is_builtin_replacement() {
145 self.inner.describe()
146 } else {
147 format!(
148 "{} (which is replacing {})",
149 self.inner.describe(),
150 self.to_replace
151 )
152 }
153 }
154
155 fn is_replaced(&self) -> bool {
156 !self.is_builtin_replacement()
157 }
158
159 fn add_to_yanked_whitelist(&self, pkgs: &[PackageId]) {
160 let pkgs = pkgs
161 .iter()
162 .map(|id| id.with_source_id(self.replace_with))
163 .collect::<Vec<_>>();
164 self.inner.add_to_yanked_whitelist(&pkgs);
165 }
166
167 async fn is_yanked(&self, pkg: PackageId) -> CargoResult<bool> {
168 self.inner.is_yanked(pkg).await
169 }
170}