|
1 |
| -use std::collections::{HashSet, HashMap}; |
| 1 | +use std::collections::HashMap; |
2 | 2 |
|
3 | 3 | use core::{Source, SourceId, SourceMap, Summary, Dependency, PackageId, Package};
|
4 | 4 | use core::PackageSet;
|
@@ -188,17 +188,16 @@ impl<'cfg> PackageRegistry<'cfg> {
|
188 | 188 | }
|
189 | 189 |
|
190 | 190 | fn query_overrides(&mut self, dep: &Dependency)
|
191 |
| - -> CargoResult<Vec<Summary>> { |
192 |
| - let mut seen = HashSet::new(); |
193 |
| - let mut ret = Vec::new(); |
| 191 | + -> CargoResult<Option<Summary>> { |
194 | 192 | for s in self.overrides.iter() {
|
195 | 193 | let src = self.sources.get_mut(s).unwrap();
|
196 | 194 | let dep = Dependency::new_override(dep.name(), s);
|
197 |
| - ret.extend(try!(src.query(&dep)).into_iter().filter(|s| { |
198 |
| - seen.insert(s.name().to_string()) |
199 |
| - })); |
| 195 | + let mut results = try!(src.query(&dep)); |
| 196 | + if results.len() > 0 { |
| 197 | + return Ok(Some(results.remove(0))) |
| 198 | + } |
200 | 199 | }
|
201 |
| - Ok(ret) |
| 200 | + Ok(None) |
202 | 201 | }
|
203 | 202 |
|
204 | 203 | /// This function is used to transform a summary to another locked summary
|
@@ -271,25 +270,89 @@ impl<'cfg> PackageRegistry<'cfg> {
|
271 | 270 | }
|
272 | 271 | })
|
273 | 272 | }
|
| 273 | + |
| 274 | + fn warn_bad_override(&self, |
| 275 | + override_summary: &Summary, |
| 276 | + real_summary: &Summary) -> CargoResult<()> { |
| 277 | + let real = real_summary.package_id(); |
| 278 | + let map = try!(self.locked.get(real.source_id()).chain_error(|| { |
| 279 | + human(format!("failed to find lock source of {}", real)) |
| 280 | + })); |
| 281 | + let list = try!(map.get(real.name()).chain_error(|| { |
| 282 | + human(format!("failed to find lock name of {}", real)) |
| 283 | + })); |
| 284 | + let &(_, ref real_deps) = try!(list.iter().find(|&&(ref id, _)| { |
| 285 | + real == id |
| 286 | + }).chain_error(|| { |
| 287 | + human(format!("failed to find lock version of {}", real)) |
| 288 | + })); |
| 289 | + let mut real_deps = real_deps.clone(); |
| 290 | + |
| 291 | + let boilerplate = "\ |
| 292 | +This is currently allowed but is known to produce buggy behavior with spurious |
| 293 | +recompiles and changes to the crate graph. Path overrides unfortunately were |
| 294 | +never intended to support this feature, so for now this message is just a |
| 295 | +warning. In the future, however, this message will become a hard error. |
| 296 | +
|
| 297 | +To change the dependency graph via an override it's recommended to use the |
| 298 | +`[replace]` feature of Cargo instead of the path override feature. This is |
| 299 | +documented online at the url below for more information. |
| 300 | +
|
| 301 | +http://doc.crates.io/specifying-dependencies.html#overriding-dependencies |
| 302 | +"; |
| 303 | + |
| 304 | + for dep in override_summary.dependencies() { |
| 305 | + if let Some(i) = real_deps.iter().position(|id| dep.matches_id(id)) { |
| 306 | + real_deps.remove(i); |
| 307 | + continue |
| 308 | + } |
| 309 | + let msg = format!("\ |
| 310 | + path override for crate `{}` has altered the original list of\n\ |
| 311 | + dependencies; the dependency on `{}` was either added or\n\ |
| 312 | + modified to not match the previously resolved version\n\n\ |
| 313 | + {}", override_summary.package_id().name(), dep.name(), boilerplate); |
| 314 | + try!(self.source_config.config().shell().warn(&msg)); |
| 315 | + return Ok(()) |
| 316 | + } |
| 317 | + |
| 318 | + for id in real_deps { |
| 319 | + let msg = format!("\ |
| 320 | + path override for crate `{}` has altered the original list of |
| 321 | + dependencies; the dependency on `{}` was removed\n\n |
| 322 | + {}", override_summary.package_id().name(), id.name(), boilerplate); |
| 323 | + try!(self.source_config.config().shell().warn(&msg)); |
| 324 | + return Ok(()) |
| 325 | + } |
| 326 | + |
| 327 | + Ok(()) |
| 328 | + } |
274 | 329 | }
|
275 | 330 |
|
276 | 331 | impl<'cfg> Registry for PackageRegistry<'cfg> {
|
277 | 332 | fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
|
278 |
| - let overrides = try!(self.query_overrides(&dep)); |
279 |
| - |
280 |
| - let ret = if overrides.is_empty() { |
281 |
| - // Ensure the requested source_id is loaded |
282 |
| - try!(self.ensure_loaded(dep.source_id(), Kind::Normal).chain_error(|| { |
283 |
| - human(format!("failed to load source for a dependency \ |
284 |
| - on `{}`", dep.name())) |
285 |
| - })); |
286 |
| - |
287 |
| - match self.sources.get_mut(dep.source_id()) { |
288 |
| - Some(src) => try!(src.query(&dep)), |
289 |
| - None => Vec::new(), |
| 333 | + // Ensure the requested source_id is loaded |
| 334 | + try!(self.ensure_loaded(dep.source_id(), Kind::Normal).chain_error(|| { |
| 335 | + human(format!("failed to load source for a dependency \ |
| 336 | + on `{}`", dep.name())) |
| 337 | + })); |
| 338 | + |
| 339 | + let override_summary = try!(self.query_overrides(&dep)); |
| 340 | + let real_summaries = match self.sources.get_mut(dep.source_id()) { |
| 341 | + Some(src) => Some(try!(src.query(&dep))), |
| 342 | + None => None, |
| 343 | + }; |
| 344 | + |
| 345 | + let ret = match (override_summary, real_summaries) { |
| 346 | + (Some(candidate), Some(summaries)) => { |
| 347 | + if summaries.len() != 1 { |
| 348 | + bail!("found an override with a non-locked list"); |
| 349 | + } |
| 350 | + try!(self.warn_bad_override(&candidate, &summaries[0])); |
| 351 | + vec![candidate] |
290 | 352 | }
|
291 |
| - } else { |
292 |
| - overrides |
| 353 | + (Some(_), None) => bail!("override found but no real ones"), |
| 354 | + (None, Some(summaries)) => summaries, |
| 355 | + (None, None) => Vec::new(), |
293 | 356 | };
|
294 | 357 |
|
295 | 358 | // post-process all returned summaries to ensure that we lock all
|
|
0 commit comments