1use std::collections::hash_map::HashMap;
2use std::fmt;
3
4use crate::core::package::PackageSet;
5use crate::core::{Dependency, Package, PackageId, Summary};
6use crate::util::{CargoResult, Config};
7
8mod source_id;
9
10pub use self::source_id::{GitReference, SourceId};
11
12pub trait Source {
14 fn source_id(&self) -> SourceId;
16
17 fn replaced_source_id(&self) -> SourceId {
19 self.source_id()
20 }
21
22 fn supports_checksums(&self) -> bool;
25
26 fn requires_precise(&self) -> bool;
29
30 fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()>;
32
33 fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()>;
38
39 fn query_vec(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
40 let mut ret = Vec::new();
41 self.query(dep, &mut |s| ret.push(s))?;
42 Ok(ret)
43 }
44
45 fn update(&mut self) -> CargoResult<()>;
48
49 fn download(&mut self, package: PackageId) -> CargoResult<MaybePackage>;
51
52 fn download_now(self: Box<Self>, package: PackageId, config: &Config) -> CargoResult<Package>
53 where
54 Self: std::marker::Sized,
55 {
56 let mut sources = SourceMap::new();
57 sources.insert(self);
58 let pkg_set = PackageSet::new(&[package], sources, config)?;
59 Ok(pkg_set.get_one(package)?.clone())
60 }
61
62 fn finish_download(&mut self, package: PackageId, contents: Vec<u8>) -> CargoResult<Package>;
63
64 fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
74
75 fn verify(&self, _pkg: PackageId) -> CargoResult<()> {
83 Ok(())
84 }
85
86 fn describe(&self) -> String;
89
90 fn is_replaced(&self) -> bool {
92 false
93 }
94
95 fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]);
99
100 fn is_yanked(&mut self, _pkg: PackageId) -> CargoResult<bool>;
103}
104
105pub enum MaybePackage {
106 Ready(Package),
107 Download { url: String, descriptor: String },
108}
109
110impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
111 fn source_id(&self) -> SourceId {
113 (**self).source_id()
114 }
115
116 fn replaced_source_id(&self) -> SourceId {
118 (**self).replaced_source_id()
119 }
120
121 fn supports_checksums(&self) -> bool {
123 (**self).supports_checksums()
124 }
125
126 fn requires_precise(&self) -> bool {
128 (**self).requires_precise()
129 }
130
131 fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
133 (**self).query(dep, f)
134 }
135
136 fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
138 (**self).fuzzy_query(dep, f)
139 }
140
141 fn update(&mut self) -> CargoResult<()> {
143 (**self).update()
144 }
145
146 fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
148 (**self).download(id)
149 }
150
151 fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
152 (**self).finish_download(id, data)
153 }
154
155 fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
157 (**self).fingerprint(pkg)
158 }
159
160 fn verify(&self, pkg: PackageId) -> CargoResult<()> {
162 (**self).verify(pkg)
163 }
164
165 fn describe(&self) -> String {
166 (**self).describe()
167 }
168
169 fn is_replaced(&self) -> bool {
170 (**self).is_replaced()
171 }
172
173 fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
174 (**self).add_to_yanked_whitelist(pkgs);
175 }
176
177 fn is_yanked(&mut self, pkg: PackageId) -> CargoResult<bool> {
178 (**self).is_yanked(pkg)
179 }
180}
181
182impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T {
183 fn source_id(&self) -> SourceId {
184 (**self).source_id()
185 }
186
187 fn replaced_source_id(&self) -> SourceId {
188 (**self).replaced_source_id()
189 }
190
191 fn supports_checksums(&self) -> bool {
192 (**self).supports_checksums()
193 }
194
195 fn requires_precise(&self) -> bool {
196 (**self).requires_precise()
197 }
198
199 fn query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
200 (**self).query(dep, f)
201 }
202
203 fn fuzzy_query(&mut self, dep: &Dependency, f: &mut dyn FnMut(Summary)) -> CargoResult<()> {
204 (**self).fuzzy_query(dep, f)
205 }
206
207 fn update(&mut self) -> CargoResult<()> {
208 (**self).update()
209 }
210
211 fn download(&mut self, id: PackageId) -> CargoResult<MaybePackage> {
212 (**self).download(id)
213 }
214
215 fn finish_download(&mut self, id: PackageId, data: Vec<u8>) -> CargoResult<Package> {
216 (**self).finish_download(id, data)
217 }
218
219 fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
220 (**self).fingerprint(pkg)
221 }
222
223 fn verify(&self, pkg: PackageId) -> CargoResult<()> {
224 (**self).verify(pkg)
225 }
226
227 fn describe(&self) -> String {
228 (**self).describe()
229 }
230
231 fn is_replaced(&self) -> bool {
232 (**self).is_replaced()
233 }
234
235 fn add_to_yanked_whitelist(&mut self, pkgs: &[PackageId]) {
236 (**self).add_to_yanked_whitelist(pkgs);
237 }
238
239 fn is_yanked(&mut self, pkg: PackageId) -> CargoResult<bool> {
240 (**self).is_yanked(pkg)
241 }
242}
243
244#[derive(Default)]
246pub struct SourceMap<'src> {
247 map: HashMap<SourceId, Box<dyn Source + 'src>>,
248}
249
250impl<'src> fmt::Debug for SourceMap<'src> {
252 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253 write!(f, "SourceMap ")?;
254 f.debug_set().entries(self.map.keys()).finish()
255 }
256}
257
258impl<'src> SourceMap<'src> {
259 pub fn new() -> SourceMap<'src> {
261 SourceMap {
262 map: HashMap::new(),
263 }
264 }
265
266 pub fn contains(&self, id: SourceId) -> bool {
268 self.map.contains_key(&id)
269 }
270
271 pub fn get(&self, id: SourceId) -> Option<&(dyn Source + 'src)> {
273 let source = self.map.get(&id);
274
275 source.map(|s| {
276 let s: &(dyn Source + 'src) = &**s;
277 s
278 })
279 }
280
281 pub fn get_mut(&mut self, id: SourceId) -> Option<&mut (dyn Source + 'src)> {
283 self.map.get_mut(&id).map(|s| {
284 let s: &mut (dyn Source + 'src) = &mut **s;
285 s
286 })
287 }
288
289 pub fn get_by_package_id(&self, pkg_id: PackageId) -> Option<&(dyn Source + 'src)> {
291 self.get(pkg_id.source_id())
292 }
293
294 pub fn insert(&mut self, source: Box<dyn Source + 'src>) {
296 let id = source.source_id();
297 self.map.insert(id, source);
298 }
299
300 pub fn is_empty(&self) -> bool {
302 self.map.is_empty()
303 }
304
305 pub fn len(&self) -> usize {
307 self.map.len()
308 }
309
310 pub fn sources<'a>(&'a self) -> impl Iterator<Item = &'a Box<dyn Source + 'src>> {
312 self.map.values()
313 }
314
315 pub fn sources_mut<'a>(
317 &'a mut self,
318 ) -> impl Iterator<Item = (&'a SourceId, &'a mut (dyn Source + 'src))> {
319 self.map.iter_mut().map(|(a, b)| (a, &mut **b))
320 }
321
322 pub fn add_source_map(&mut self, other: SourceMap<'src>) {
324 for (key, value) in other.map {
325 self.map.entry(key).or_insert(value);
326 }
327 }
328}