diff --git a/crates/resolver-tests/src/lib.rs b/crates/resolver-tests/src/lib.rs index a86b67905733..fd190fe6b3b5 100644 --- a/crates/resolver-tests/src/lib.rs +++ b/crates/resolver-tests/src/lib.rs @@ -12,7 +12,7 @@ use std::time::Instant; use cargo::core::dependency::DepKind; use cargo::core::resolver::{self, ResolveOpts, VersionPreferences}; -use cargo::core::source::{GitReference, SourceId}; +use cargo::core::source::{GitReference, QueryKind, SourceId}; use cargo::core::Resolve; use cargo::core::{Dependency, PackageId, Registry, Summary}; use cargo::util::{CargoResult, Config, Graph, IntoUrl}; @@ -128,11 +128,15 @@ pub fn resolve_with_config_raw( fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { for summary in self.list.iter() { - if fuzzy || dep.matches(summary) { + let matched = match kind { + QueryKind::Exact => dep.matches(summary), + QueryKind::Fuzzy => true, + }; + if matched { self.used.insert(summary.package_id()); f(summary.clone()); } diff --git a/src/cargo/core/compiler/future_incompat.rs b/src/cargo/core/compiler/future_incompat.rs index 4ff99079009a..61b2c47fd87a 100644 --- a/src/cargo/core/compiler/future_incompat.rs +++ b/src/cargo/core/compiler/future_incompat.rs @@ -1,7 +1,7 @@ //! Support for future-incompatible warning reporting. use crate::core::compiler::BuildContext; -use crate::core::{Dependency, PackageId, Workspace}; +use crate::core::{Dependency, PackageId, QueryKind, Workspace}; use crate::sources::SourceConfigMap; use crate::util::{iter_join, CargoResult, Config}; use anyhow::{bail, format_err, Context}; @@ -293,7 +293,7 @@ fn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet) -> Option< Ok(dep) => dep, Err(_) => return false, }; - match source.query_vec(&dep, false) { + match source.query_vec(&dep, QueryKind::Exact) { Poll::Ready(Ok(sum)) => { summaries.push((pkg_id, sum)); false diff --git a/src/cargo/core/mod.rs b/src/cargo/core/mod.rs index df91808ccafa..e36c678c4cb3 100644 --- a/src/cargo/core/mod.rs +++ b/src/cargo/core/mod.rs @@ -8,7 +8,7 @@ pub use self::package_id_spec::PackageIdSpec; pub use self::registry::Registry; pub use self::resolver::{Resolve, ResolveVersion}; pub use self::shell::{Shell, Verbosity}; -pub use self::source::{GitReference, Source, SourceId, SourceMap}; +pub use self::source::{GitReference, QueryKind, Source, SourceId, SourceMap}; pub use self::summary::{FeatureMap, FeatureValue, Summary}; pub use self::workspace::{ find_workspace_root, resolve_relative_path, MaybePackage, Workspace, WorkspaceConfig, diff --git a/src/cargo/core/registry.rs b/src/cargo/core/registry.rs index 4bb8e8aec3d8..0d788a05c43f 100644 --- a/src/cargo/core/registry.rs +++ b/src/cargo/core/registry.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::task::Poll; use crate::core::PackageSet; -use crate::core::{Dependency, PackageId, Source, SourceId, SourceMap, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Source, SourceId, SourceMap, Summary}; use crate::sources::config::SourceConfigMap; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -19,14 +19,13 @@ pub trait Registry { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency, fuzzy: bool) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, fuzzy, &mut |s| ret.push(s)) - .map_ok(|()| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|()| ret) } fn describe_source(&self, source: SourceId) -> String; @@ -327,7 +326,7 @@ impl<'cfg> PackageRegistry<'cfg> { .get_mut(dep.source_id()) .expect("loaded source not present"); - let summaries = match source.query_vec(dep, false)? { + let summaries = match source.query_vec(dep, QueryKind::Exact)? { Poll::Ready(deps) => deps, Poll::Pending => { deps_pending.push(dep_remaining); @@ -483,7 +482,7 @@ impl<'cfg> PackageRegistry<'cfg> { for &s in self.overrides.iter() { let src = self.sources.get_mut(s).unwrap(); let dep = Dependency::new_override(dep.package_name(), s); - let mut results = match src.query_vec(&dep, false) { + let mut results = match src.query_vec(&dep, QueryKind::Exact) { Poll::Ready(results) => results?, Poll::Pending => return Poll::Pending, }; @@ -575,7 +574,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { assert!(self.patches_locked); @@ -671,7 +670,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { } f(lock(locked, all_patches, summary)) }; - return source.query(dep, fuzzy, callback); + return source.query(dep, kind, callback); } // If we have an override summary then we query the source @@ -690,7 +689,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> { n += 1; to_warn = Some(summary); }; - let pend = source.query(dep, fuzzy, callback); + let pend = source.query(dep, kind, callback); if pend.is_pending() { return Poll::Pending; } @@ -881,7 +880,7 @@ fn summary_for_patch( // No summaries found, try to help the user figure out what is wrong. if let Some(locked) = locked { // Since the locked patch did not match anything, try the unlocked one. - let orig_matches = match source.query_vec(orig_patch, false) { + let orig_matches = match source.query_vec(orig_patch, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } @@ -906,7 +905,7 @@ fn summary_for_patch( // Try checking if there are *any* packages that match this by name. let name_only_dep = Dependency::new_override(orig_patch.package_name(), orig_patch.source_id()); - let name_summaries = match source.query_vec(&name_only_dep, false) { + let name_summaries = match source.query_vec(&name_only_dep, QueryKind::Exact) { Poll::Pending => return Poll::Pending, Poll::Ready(deps) => deps, } diff --git a/src/cargo/core/resolver/dep_cache.rs b/src/cargo/core/resolver/dep_cache.rs index c07dadc31e8e..79e44f6eba2c 100644 --- a/src/cargo/core/resolver/dep_cache.rs +++ b/src/cargo/core/resolver/dep_cache.rs @@ -16,7 +16,9 @@ use crate::core::resolver::{ ActivateError, ActivateResult, CliFeatures, RequestedFeatures, ResolveOpts, VersionOrdering, VersionPreferences, }; -use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec, Registry, Summary}; +use crate::core::{ + Dependency, FeatureValue, PackageId, PackageIdSpec, QueryKind, Registry, Summary, +}; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; @@ -100,7 +102,7 @@ impl<'a> RegistryQueryer<'a> { } let mut ret = Vec::new(); - let ready = self.registry.query(dep, false, &mut |s| { + let ready = self.registry.query(dep, QueryKind::Exact, &mut |s| { ret.push(s); })?; if ready.is_pending() { @@ -123,7 +125,7 @@ impl<'a> RegistryQueryer<'a> { dep.version_req() ); - let mut summaries = match self.registry.query_vec(dep, false)? { + let mut summaries = match self.registry.query_vec(dep, QueryKind::Exact)? { Poll::Ready(s) => s.into_iter(), Poll::Pending => { self.registry_cache.insert(dep.clone(), Poll::Pending); diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 306da17ef6cd..d75240df6250 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -1,7 +1,7 @@ use std::fmt; use std::task::Poll; -use crate::core::{Dependency, PackageId, Registry, Summary}; +use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary}; use crate::util::lev_distance::lev_distance; use crate::util::{Config, VersionExt}; use anyhow::Error; @@ -228,7 +228,7 @@ pub(super) fn activation_error( new_dep.set_version_req(all_req); let mut candidates = loop { - match registry.query_vec(&new_dep, false) { + match registry.query_vec(&new_dep, QueryKind::Exact) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { @@ -294,7 +294,7 @@ pub(super) fn activation_error( // 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 = loop { - match registry.query_vec(&new_dep, true) { + match registry.query_vec(&new_dep, QueryKind::Fuzzy) { Poll::Ready(Ok(candidates)) => break candidates, Poll::Ready(Err(e)) => return to_resolve_err(e), Poll::Pending => match registry.block_until_ready() { diff --git a/src/cargo/core/source/mod.rs b/src/cargo/core/source/mod.rs index 9e6f161aec5d..15ab929d766a 100644 --- a/src/cargo/core/source/mod.rs +++ b/src/cargo/core/source/mod.rs @@ -29,20 +29,16 @@ pub trait Source { fn requires_precise(&self) -> bool; /// Attempts to find the packages that match a dependency request. - /// - /// When fuzzy, each source gets to define what `close` means for it. - /// Path/Git sources may return all dependencies that are at that URI, - /// whereas an `Index` source may return dependencies that have the same canonicalization. fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll>; - fn query_vec(&mut self, dep: &Dependency, fuzzy: bool) -> Poll>> { + fn query_vec(&mut self, dep: &Dependency, kind: QueryKind) -> Poll>> { let mut ret = Vec::new(); - self.query(dep, fuzzy, &mut |s| ret.push(s)).map_ok(|_| ret) + self.query(dep, kind, &mut |s| ret.push(s)).map_ok(|_| ret) } /// Ensure that the source is fully up-to-date for the current session on the next query. @@ -114,6 +110,14 @@ pub trait Source { fn block_until_ready(&mut self) -> CargoResult<()>; } +pub enum QueryKind { + Exact, + /// Each source gets to define what `close` means for it. + /// Path/Git sources may return all dependencies that are at that URI, + /// whereas an `Index` source may return dependencies that have the same canonicalization. + Fuzzy, +} + pub enum MaybePackage { Ready(Package), Download { url: String, descriptor: String }, @@ -144,10 +148,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for Box { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).query(dep, fuzzy, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { @@ -214,10 +218,10 @@ impl<'a, T: Source + ?Sized + 'a> Source for &'a mut T { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - (**self).query(dep, fuzzy, f) + (**self).query(dep, kind, f) } fn invalidate_cache(&mut self) { diff --git a/src/cargo/ops/cargo_add/mod.rs b/src/cargo/ops/cargo_add/mod.rs index dff93e91b023..a1cc0d272aae 100644 --- a/src/cargo/ops/cargo_add/mod.rs +++ b/src/cargo/ops/cargo_add/mod.rs @@ -19,6 +19,7 @@ use toml_edit::Item as TomlItem; use crate::core::dependency::DepKind; use crate::core::registry::PackageRegistry; use crate::core::Package; +use crate::core::QueryKind; use crate::core::Registry; use crate::core::Shell; use crate::core::Workspace; @@ -443,8 +444,7 @@ fn get_latest_dependency( } MaybeWorkspace::Other(query) => { let possibilities = loop { - let fuzzy = true; - match registry.query_vec(&query, fuzzy) { + match registry.query_vec(&query, QueryKind::Fuzzy) { std::task::Poll::Ready(res) => { break res?; } @@ -485,8 +485,8 @@ fn select_package( } MaybeWorkspace::Other(query) => { let possibilities = loop { - let fuzzy = false; // Returns all for path/git - match registry.query_vec(&query, fuzzy) { + // Exact to avoid returning all for path/git + match registry.query_vec(&query, QueryKind::Exact) { std::task::Poll::Ready(res) => { break res?; } @@ -600,7 +600,7 @@ fn populate_available_features( MaybeWorkspace::Other(query) => query, }; let possibilities = loop { - match registry.query_vec(&query, true) { + match registry.query_vec(&query, QueryKind::Fuzzy) { std::task::Poll::Ready(res) => { break res?; } diff --git a/src/cargo/ops/common_for_install_and_uninstall.rs b/src/cargo/ops/common_for_install_and_uninstall.rs index 5e9282d716c9..08d5c908979e 100644 --- a/src/cargo/ops/common_for_install_and_uninstall.rs +++ b/src/cargo/ops/common_for_install_and_uninstall.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; use toml_edit::easy as toml; use crate::core::compiler::Freshness; -use crate::core::{Dependency, FeatureValue, Package, PackageId, Source, SourceId}; +use crate::core::{Dependency, FeatureValue, Package, PackageId, QueryKind, Source, SourceId}; use crate::ops::{self, CompileFilter, CompileOptions}; use crate::sources::PathSource; use crate::util::errors::CargoResult; @@ -540,7 +540,7 @@ where } let deps = loop { - match source.query_vec(&dep, false)? { + match source.query_vec(&dep, QueryKind::Exact)? { Poll::Ready(deps) => break deps, Poll::Pending => source.block_until_ready()?, } diff --git a/src/cargo/sources/directory.rs b/src/cargo/sources/directory.rs index 0ed14b0a4f7c..e30755643a78 100644 --- a/src/cargo/sources/directory.rs +++ b/src/cargo/sources/directory.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::errors::CargoResult; use crate::util::Config; @@ -49,14 +49,17 @@ impl<'cfg> Source for DirectorySource<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if !self.updated { return Poll::Pending; } let packages = self.packages.values().map(|p| &p.0); - let matches = packages.filter(|pkg| fuzzy || dep.matches(pkg.summary())); + let matches = packages.filter(|pkg| match kind { + QueryKind::Exact => dep.matches(pkg.summary()), + QueryKind::Fuzzy => true, + }); for summary in matches.map(|pkg| pkg.summary().clone()) { f(summary); } diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index 538d94fa38f6..4644a3ac7102 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -1,4 +1,4 @@ -use crate::core::source::{MaybePackage, Source, SourceId}; +use crate::core::source::{MaybePackage, QueryKind, Source, SourceId}; use crate::core::GitReference; use crate::core::{Dependency, Package, PackageId, Summary}; use crate::sources::git::utils::GitRemote; @@ -89,11 +89,11 @@ impl<'cfg> Source for GitSource<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { if let Some(src) = self.path_source.as_mut() { - src.query(dep, fuzzy, f) + src.query(dep, kind, f) } else { Poll::Pending } diff --git a/src/cargo/sources/path.rs b/src/cargo/sources/path.rs index 95519cd7ca90..78a66e098ec7 100644 --- a/src/cargo/sources/path.rs +++ b/src/cargo/sources/path.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use std::task::Poll; use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::ops; use crate::util::{internal, CargoResult, Config}; use anyhow::Context as _; @@ -500,12 +500,16 @@ impl<'cfg> Source for PathSource<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { self.update()?; for s in self.packages.iter().map(|p| p.summary()) { - if fuzzy || dep.matches(s) { + let matched = match kind { + QueryKind::Exact => dep.matches(s), + QueryKind::Fuzzy => true, + }; + if matched { f(s.clone()) } } diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 46eeb67565c1..c9a3a9de4841 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -176,7 +176,7 @@ use tar::Archive; use crate::core::dependency::{DepKind, Dependency}; use crate::core::source::MaybePackage; -use crate::core::{Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::sources::PathSource; use crate::util::hex; use crate::util::interning::InternedString; @@ -704,44 +704,51 @@ impl<'cfg> Source for RegistrySource<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { - if !fuzzy { - // If this is a precise dependency, then it came from a lock file and in - // theory the registry is known to contain this version. If, however, we - // come back with no summaries, then our registry may need to be - // updated, so we fall back to performing a lazy update. - if dep.source_id().precise().is_some() && !self.ops.is_updated() { - debug!("attempting query without update"); - let mut called = false; - let pend = self.index.query_inner( - dep, - &mut *self.ops, - &self.yanked_whitelist, - &mut |s| { - if dep.matches(&s) { - called = true; - f(s); - } - }, - )?; - if pend.is_pending() { - return Poll::Pending; - } - if called { - return Poll::Ready(Ok(())); - } else { - debug!("falling back to an update"); - self.invalidate_cache(); - return Poll::Pending; + match kind { + QueryKind::Exact => { + // If this is a precise dependency, then it came from a lock file and in + // theory the registry is known to contain this version. If, however, we + // come back with no summaries, then our registry may need to be + // updated, so we fall back to performing a lazy update. + if dep.source_id().precise().is_some() && !self.ops.is_updated() { + debug!("attempting query without update"); + let mut called = false; + let pend = self.index.query_inner( + dep, + &mut *self.ops, + &self.yanked_whitelist, + &mut |s| { + if dep.matches(&s) { + called = true; + f(s); + } + }, + )?; + if pend.is_pending() { + return Poll::Pending; + } + if called { + return Poll::Ready(Ok(())); + } else { + debug!("falling back to an update"); + self.invalidate_cache(); + return Poll::Pending; + } } } + QueryKind::Fuzzy => {} } self.index .query_inner(dep, &mut *self.ops, &self.yanked_whitelist, &mut |s| { - if fuzzy || dep.matches(&s) { + let matched = match kind { + QueryKind::Exact => dep.matches(&s), + QueryKind::Fuzzy => true, + }; + if matched { f(s); } }) diff --git a/src/cargo/sources/replaced.rs b/src/cargo/sources/replaced.rs index 61408559efb3..2d8a2903d763 100644 --- a/src/cargo/sources/replaced.rs +++ b/src/cargo/sources/replaced.rs @@ -1,5 +1,5 @@ use crate::core::source::MaybePackage; -use crate::core::{Dependency, Package, PackageId, Source, SourceId, Summary}; +use crate::core::{Dependency, Package, PackageId, QueryKind, Source, SourceId, Summary}; use crate::util::errors::CargoResult; use std::task::Poll; @@ -45,14 +45,14 @@ impl<'cfg> Source for ReplacedSource<'cfg> { fn query( &mut self, dep: &Dependency, - fuzzy: bool, + kind: QueryKind, f: &mut dyn FnMut(Summary), ) -> Poll> { 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, fuzzy, &mut |summary| { + .query(&dep, kind, &mut |summary| { f(summary.map_source(replace_with, to_replace)) }) .map_err(|e| {