mirror of
https://github.com/rust-lang/cargo
synced 2024-09-17 23:01:51 +00:00
allow each source to recommend packages that are close to a dependency
This commit is contained in:
parent
8a717d32db
commit
84cc3d8b09
|
@ -14,11 +14,11 @@ use sources::config::SourceConfigMap;
|
|||
/// See also `core::Source`.
|
||||
pub trait Registry {
|
||||
/// Attempt to find the packages that match a dependency request.
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()>;
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary), fuzzy: bool) -> CargoResult<()>;
|
||||
|
||||
fn query_vec(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
|
||||
fn query_vec(&mut self, dep: &Dependency, fuzzy: bool) -> CargoResult<Vec<Summary>> {
|
||||
let mut ret = Vec::new();
|
||||
self.query(dep, &mut |s| ret.push(s))?;
|
||||
self.query(dep, &mut |s| ret.push(s), fuzzy)?;
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ http://doc.crates.io/specifying-dependencies.html#overriding-dependencies
|
|||
}
|
||||
|
||||
impl<'cfg> Registry for PackageRegistry<'cfg> {
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary), fuzzy: bool) -> CargoResult<()> {
|
||||
assert!(self.patches_locked);
|
||||
let (override_summary, n, to_warn) = {
|
||||
// Look for an override and get ready to query the real source.
|
||||
|
@ -476,7 +476,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
|
|||
// already selected, then we skip this `summary`.
|
||||
let locked = &self.locked;
|
||||
let all_patches = &self.patches_available;
|
||||
return source.query(dep, &mut |summary| {
|
||||
let callback = &mut |summary: Summary| {
|
||||
for patch in patches.iter() {
|
||||
let patch = patch.package_id().version();
|
||||
if summary.package_id().version() == patch {
|
||||
|
@ -484,7 +484,12 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
|
|||
}
|
||||
}
|
||||
f(lock(locked, all_patches, summary))
|
||||
});
|
||||
};
|
||||
return if fuzzy {
|
||||
source.fuzzy_query(dep, callback)
|
||||
} else {
|
||||
source.query(dep, callback)
|
||||
};
|
||||
}
|
||||
|
||||
// If we have an override summary then we query the source
|
||||
|
@ -496,10 +501,17 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
|
|||
}
|
||||
let mut n = 0;
|
||||
let mut to_warn = None;
|
||||
source.query(dep, &mut |summary| {
|
||||
n += 1;
|
||||
to_warn = Some(summary);
|
||||
})?;
|
||||
{
|
||||
let callback = &mut |summary| {
|
||||
n += 1;
|
||||
to_warn = Some(summary);
|
||||
};
|
||||
if fuzzy {
|
||||
source.fuzzy_query(dep, callback)?;
|
||||
} else {
|
||||
source.query(dep, callback)?;
|
||||
}
|
||||
}
|
||||
(override_summary, n, to_warn)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -922,17 +922,16 @@ fn activation_error(
|
|||
return format_err!("{}", msg);
|
||||
}
|
||||
|
||||
// Once we're all the way down here, we're definitely lost in the
|
||||
// weeds! We didn't actually find any candidates, so we need to
|
||||
// We didn't actually find any candidates, so we need to
|
||||
// give an error message that nothing was found.
|
||||
//
|
||||
// Note that we re-query the registry with a new dependency that
|
||||
// allows any version so we can give some nicer error reporting
|
||||
// which indicates a few versions that were actually found.
|
||||
// Maybe the user mistyped the ver_req? Like `dep="2"` when `dep=".2"`
|
||||
// was meant. So we re-query the registry with `deb="*"` so we can
|
||||
// list a few versions that were actually found.
|
||||
let all_req = semver::VersionReq::parse("*").unwrap();
|
||||
let mut new_dep = dep.clone();
|
||||
new_dep.set_version_req(all_req);
|
||||
let mut candidates = match registry.query_vec(&new_dep) {
|
||||
let mut candidates = match registry.query_vec(&new_dep, false) {
|
||||
Ok(candidates) => candidates,
|
||||
Err(e) => return e,
|
||||
};
|
||||
|
@ -977,12 +976,25 @@ fn activation_error(
|
|||
|
||||
msg
|
||||
} else {
|
||||
// Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
|
||||
// was meant. So we try asking the registry for a `fuzzy` search for suggestions.
|
||||
let mut candidates = Vec::new();
|
||||
if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.name()), true) {
|
||||
return e
|
||||
};
|
||||
candidates.sort_unstable();
|
||||
candidates.dedup();
|
||||
let mut msg = format!(
|
||||
"no matching package named `{}` found\n\
|
||||
location searched: {}\n",
|
||||
dep.name(),
|
||||
dep.source_id()
|
||||
);
|
||||
if !candidates.is_empty() {
|
||||
msg.push_str("did you mean: ");
|
||||
msg.push_str(&candidates.join(" or "));
|
||||
msg.push_str("\n");
|
||||
}
|
||||
msg.push_str("required by ");
|
||||
msg.push_str(&describe_path(&graph.path_to_top(parent.package_id())));
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ impl<'a> RegistryQueryer<'a> {
|
|||
summary: s,
|
||||
replace: None,
|
||||
});
|
||||
})?;
|
||||
}, false)?;
|
||||
for candidate in ret.iter_mut() {
|
||||
let summary = &candidate.summary;
|
||||
|
||||
|
@ -66,7 +66,7 @@ impl<'a> RegistryQueryer<'a> {
|
|||
};
|
||||
debug!("found an override for {} {}", dep.name(), dep.version_req());
|
||||
|
||||
let mut summaries = self.registry.query_vec(dep)?.into_iter();
|
||||
let mut summaries = self.registry.query_vec(dep, false)?.into_iter();
|
||||
let s = summaries.next().ok_or_else(|| {
|
||||
format_err!(
|
||||
"no matching package for override `{}` found\n\
|
||||
|
|
|
@ -25,6 +25,12 @@ pub trait Source {
|
|||
/// Attempt to find the packages that match a dependency request.
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()>;
|
||||
|
||||
/// Attempt to find the packages that are close to a dependency request.
|
||||
/// Each source gets to define what `close` means for it.
|
||||
/// path/git sources may return all dependencies that are at that uri.
|
||||
/// where as an Index source may return dependencies that have the same canonicalization.
|
||||
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()>;
|
||||
|
||||
fn query_vec(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
|
||||
let mut ret = Vec::new();
|
||||
self.query(dep, &mut |s| ret.push(s))?;
|
||||
|
@ -79,6 +85,11 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box<T> {
|
|||
(**self).query(dep, f)
|
||||
}
|
||||
|
||||
/// Forwards to `Source::query`
|
||||
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
(**self).fuzzy_query(dep, f)
|
||||
}
|
||||
|
||||
/// Forwards to `Source::source_id`
|
||||
fn source_id(&self) -> &SourceId {
|
||||
(**self).source_id()
|
||||
|
|
|
@ -54,6 +54,14 @@ impl<'cfg> Source for DirectorySource<'cfg> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fuzzy_query(&mut self, _dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
let packages = self.packages.values().map(|p| &p.0);
|
||||
for summary in packages.map(|pkg| pkg.summary().clone()) {
|
||||
f(summary);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_checksums(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
|
|
@ -130,6 +130,13 @@ impl<'cfg> Source for GitSource<'cfg> {
|
|||
src.query(dep, f)
|
||||
}
|
||||
|
||||
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
let src = self.path_source
|
||||
.as_mut()
|
||||
.expect("BUG: update() must be called before query()");
|
||||
src.fuzzy_query(dep, f)
|
||||
}
|
||||
|
||||
fn supports_checksums(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -508,6 +508,13 @@ impl<'cfg> Source for PathSource<'cfg> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fuzzy_query(&mut self, _dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
for s in self.packages.iter().map(|p| p.summary()) {
|
||||
f(s.clone())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_checksums(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ impl<'cfg> RegistryIndex<'cfg> {
|
|||
Ok((summary, yanked.unwrap_or(false)))
|
||||
}
|
||||
|
||||
pub fn query(
|
||||
pub fn query_inner(
|
||||
&mut self,
|
||||
dep: &Dependency,
|
||||
load: &mut RegistryData,
|
||||
|
@ -242,9 +242,7 @@ impl<'cfg> RegistryIndex<'cfg> {
|
|||
});
|
||||
|
||||
for summary in summaries {
|
||||
if dep.matches(&summary) {
|
||||
f(summary);
|
||||
}
|
||||
f(summary);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -463,9 +463,11 @@ impl<'cfg> Source for RegistrySource<'cfg> {
|
|||
if dep.source_id().precise().is_some() && !self.updated {
|
||||
debug!("attempting query without update");
|
||||
let mut called = false;
|
||||
self.index.query(dep, &mut *self.ops, &mut |s| {
|
||||
called = true;
|
||||
f(s);
|
||||
self.index.query_inner(dep, &mut *self.ops, &mut |s| {
|
||||
if dep.matches(&s) {
|
||||
called = true;
|
||||
f(s);
|
||||
}
|
||||
})?;
|
||||
if called {
|
||||
return Ok(());
|
||||
|
@ -475,7 +477,15 @@ impl<'cfg> Source for RegistrySource<'cfg> {
|
|||
}
|
||||
}
|
||||
|
||||
self.index.query(dep, &mut *self.ops, f)
|
||||
self.index.query_inner(dep, &mut *self.ops, &mut |s| {
|
||||
if dep.matches(&s) {
|
||||
f(s);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
self.index.query_inner(dep, &mut *self.ops, f)
|
||||
}
|
||||
|
||||
fn supports_checksums(&self) -> bool {
|
||||
|
|
|
@ -35,6 +35,19 @@ impl<'cfg> Source for ReplacedSource<'cfg> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn fuzzy_query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
let (replace_with, to_replace) = (&self.replace_with, &self.to_replace);
|
||||
let dep = dep.clone().map_source(to_replace, replace_with);
|
||||
|
||||
self.inner
|
||||
.fuzzy_query(
|
||||
&dep,
|
||||
&mut |summary| f(summary.map_source(replace_with, to_replace)),
|
||||
)
|
||||
.chain_err(|| format!("failed to query replaced source {}", self.to_replace))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn supports_checksums(&self) -> bool {
|
||||
self.inner.supports_checksums()
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ fn wrong_case() {
|
|||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
// TODO: #5678 to make this work or at least give better error message
|
||||
// #5678 to make this work
|
||||
assert_that(
|
||||
p.cargo("build"),
|
||||
execs().with_status(101).with_stderr(
|
||||
|
@ -169,6 +169,7 @@ fn wrong_case() {
|
|||
[UPDATING] registry [..]
|
||||
error: no matching package named `Init` found
|
||||
location searched: registry [..]
|
||||
did you mean: init
|
||||
required by package `foo v0.0.1 ([..])`
|
||||
",
|
||||
),
|
||||
|
@ -195,7 +196,7 @@ fn mis_hyphenated() {
|
|||
.file("src/main.rs", "fn main() {}")
|
||||
.build();
|
||||
|
||||
// TODO: #2775 to make this work or at least give better error message
|
||||
// #2775 to make this work
|
||||
assert_that(
|
||||
p.cargo("build"),
|
||||
execs().with_status(101).with_stderr(
|
||||
|
@ -203,6 +204,7 @@ fn mis_hyphenated() {
|
|||
[UPDATING] registry [..]
|
||||
error: no matching package named `mis_hyphenated` found
|
||||
location searched: registry [..]
|
||||
did you mean: mis-hyphenated
|
||||
required by package `foo v0.0.1 ([..])`
|
||||
",
|
||||
),
|
||||
|
|
|
@ -28,9 +28,9 @@ fn resolve_with_config(
|
|||
) -> CargoResult<Vec<PackageId>> {
|
||||
struct MyRegistry<'a>(&'a [Summary]);
|
||||
impl<'a> Registry for MyRegistry<'a> {
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary)) -> CargoResult<()> {
|
||||
fn query(&mut self, dep: &Dependency, f: &mut FnMut(Summary), fuzzy: bool) -> CargoResult<()> {
|
||||
for summary in self.0.iter() {
|
||||
if dep.matches(summary) {
|
||||
if fuzzy || dep.matches(summary) {
|
||||
f(summary.clone());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue