From 293b71a961ea89eead389ba5062af42ae38ed066 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 1/7] test(registry): Provide more room from tests conflicting with reality --- tests/testsuite/registry.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/testsuite/registry.rs b/tests/testsuite/registry.rs index 0569249e07f..2181f2ebb2b 100644 --- a/tests/testsuite/registry.rs +++ b/tests/testsuite/registry.rs @@ -2604,7 +2604,9 @@ fn ignores_unknown_index_version_git() { fn ignores_unknown_index_version() { // If the version field is not understood, it is ignored. Package::new("bar", "1.0.0").publish(); - Package::new("bar", "1.0.1").schema_version(9999).publish(); + Package::new("bar", "1.0.1") + .schema_version(u32::MAX) + .publish(); let p = project() .file( From 385dfb62985fbda98729bf3657b0ec841998cda1 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 2/7] test(registry): Show current too-new schema error This reproduces the problem in #10623. --- tests/testsuite/registry.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/testsuite/registry.rs b/tests/testsuite/registry.rs index 2181f2ebb2b..51bacc32220 100644 --- a/tests/testsuite/registry.rs +++ b/tests/testsuite/registry.rs @@ -2632,6 +2632,41 @@ fn ignores_unknown_index_version() { .run(); } +#[cargo_test] +fn unknown_index_version_error() { + // If the version field is not understood, it is ignored. + Package::new("bar", "1.0.1") + .schema_version(u32::MAX) + .publish(); + + let p = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + + [dependencies] + bar = "1.0" + "#, + ) + .file("src/lib.rs", "") + .build(); + + p.cargo("generate-lockfile") + .with_status(101) + .with_stderr( + "\ +[UPDATING] `dummy-registry` index +[ERROR] no matching package named `bar` found +location searched: registry `crates-io` +required by package `foo v0.1.0 ([CWD])` +", + ) + .run(); +} + #[cargo_test] fn protocol() { cargo_process("install bar") From 423bf0588d00fe6fa04b6eac3917c50b96a3003c Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 3/7] Make IndexSummary an enum --- src/cargo/sources/registry/index.rs | 127 ++++++++++++++++++---------- src/cargo/sources/registry/mod.rs | 5 +- 2 files changed, 85 insertions(+), 47 deletions(-) diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index ec3650b38d1..c4b753051a8 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -189,11 +189,34 @@ enum MaybeIndexSummary { /// from a line from a raw index file, or a JSON blob from on-disk index cache. /// /// In addition to a full [`Summary`], we have information on whether it is `yanked`. -pub struct IndexSummary { - pub summary: Summary, - pub yanked: bool, - /// Schema version, see [`IndexPackage::v`]. - v: u32, +#[derive(Clone, Debug)] +pub enum IndexSummary { + /// Available for consideration + Candidate(Summary), + /// Yanked within its registry + Yanked(Summary), + /// From a newer schema version and is likely incomplete or inaccurate + Unsupported(Summary, u32), +} + +impl IndexSummary { + /// Extract the summary from any variant + pub fn as_summary(&self) -> &Summary { + match self { + IndexSummary::Candidate(sum) + | IndexSummary::Yanked(sum) + | IndexSummary::Unsupported(sum, _) => sum, + } + } + + /// Extract the package id from any variant + pub fn package_id(&self) -> PackageId { + match self { + IndexSummary::Candidate(sum) + | IndexSummary::Yanked(sum) + | IndexSummary::Unsupported(sum, _) => sum.package_id(), + } + } } /// A representation of the cache on disk that Cargo maintains of summaries. @@ -387,11 +410,11 @@ impl<'cfg> RegistryIndex<'cfg> { let req = OptVersionReq::exact(pkg.version()); let summary = self.summaries(&pkg.name(), &req, load)?; let summary = ready!(summary) - .filter(|s| s.summary.version() == pkg.version()) + .filter(|s| s.package_id().version() == pkg.version()) .next(); Poll::Ready(Ok(summary .ok_or_else(|| internal(format!("no hash listed for {}", pkg)))? - .summary + .as_summary() .checksum() .ok_or_else(|| internal(format!("no hash listed for {}", pkg)))?)) } @@ -435,26 +458,24 @@ impl<'cfg> RegistryIndex<'cfg> { .versions .iter_mut() .filter_map(move |(k, v)| if req.matches(k) { Some(v) } else { None }) - .filter_map(move |maybe| match maybe.parse(raw_data, source_id) { - Ok(summary) => Some(summary), - Err(e) => { - info!("failed to parse `{}` registry package: {}", name, e); - None - } - }) - .filter(move |is| { - if is.v == 3 && bindeps { - true - } else if is.v > INDEX_V_MAX { - debug!( - "unsupported schema version {} ({} {})", - is.v, - is.summary.name(), - is.summary.version() - ); - false - } else { - true + .filter_map(move |maybe| { + match maybe.parse(raw_data, source_id, bindeps) { + Ok(sum @ IndexSummary::Candidate(_) | sum @ IndexSummary::Yanked(_)) => { + Some(sum) + } + Ok(IndexSummary::Unsupported(summary, v)) => { + debug!( + "unsupported schema version {} ({} {})", + v, + summary.name(), + summary.version() + ); + None + } + Err(e) => { + info!("failed to parse `{}` registry package: {}", name, e); + None + } } }))) } @@ -573,12 +594,14 @@ impl<'cfg> RegistryIndex<'cfg> { // does not satisfy the requirements, then resolution will // fail. Unfortunately, whether or not something is optional // is not known here. - .filter(|s| (online || load.is_crate_downloaded(s.summary.package_id()))) + .filter(|s| (online || load.is_crate_downloaded(s.package_id()))) // Next filter out all yanked packages. Some yanked packages may // leak through if they're in a whitelist (aka if they were // previously in `Cargo.lock` - .filter(|s| !s.yanked || yanked_whitelist.contains(&s.summary.package_id())) - .map(|s| s.summary.clone()); + .filter(|s| { + !matches!(s, IndexSummary::Yanked(_)) || yanked_whitelist.contains(&s.package_id()) + }) + .map(|s| s.clone()); // Handle `cargo update --precise` here. let precise = source_id.precise_registry_version(name); @@ -589,7 +612,7 @@ impl<'cfg> RegistryIndex<'cfg> { // by build metadata. This shouldn't be allowed, but since // it is, this will honor it if requested. However, if not // specified, then ignore it. - let s_vers = s.version(); + let s_vers = s.package_id().version(); match (s_vers.build.is_empty(), requested.build.is_empty()) { (true, true) => s_vers == requested, (true, false) => false, @@ -611,7 +634,7 @@ impl<'cfg> RegistryIndex<'cfg> { let mut count = 0; for summary in summaries { - f(summary); + f(summary.as_summary().clone()); count += 1; } Poll::Ready(Ok(count)) @@ -625,8 +648,8 @@ impl<'cfg> RegistryIndex<'cfg> { ) -> Poll> { let req = OptVersionReq::exact(pkg.version()); let found = ready!(self.summaries(&pkg.name(), &req, load))? - .filter(|s| s.summary.version() == pkg.version()) - .any(|summary| summary.yanked); + .filter(|s| s.package_id().version() == pkg.version()) + .any(|summary| matches!(summary, IndexSummary::Yanked(_))); Poll::Ready(Ok(found)) } } @@ -682,6 +705,8 @@ impl Summaries { let response = ready!(load.load(root, relative, index_version.as_deref())?); + let bindeps = config.cli_unstable().bindeps; + match response { LoadResponse::CacheValid => { tracing::debug!("fast path for registry cache of {:?}", relative); @@ -712,7 +737,7 @@ impl Summaries { // allow future cargo implementations to break the // interpretation of each line here and older cargo will simply // ignore the new lines. - let summary = match IndexSummary::parse(line, source_id) { + let summary = match IndexSummary::parse(line, source_id, bindeps) { Ok(summary) => summary, Err(e) => { // This should only happen when there is an index @@ -731,7 +756,7 @@ impl Summaries { continue; } }; - let version = summary.summary.package_id().version().clone(); + let version = summary.package_id().version().clone(); cache.versions.push((version.clone(), line)); ret.versions.insert(version, summary.into()); } @@ -865,12 +890,17 @@ impl MaybeIndexSummary { /// Does nothing if this is already `Parsed`, and otherwise the `raw_data` /// passed in is sliced with the bounds in `Unparsed` and then actually /// parsed. - fn parse(&mut self, raw_data: &[u8], source_id: SourceId) -> CargoResult<&IndexSummary> { + fn parse( + &mut self, + raw_data: &[u8], + source_id: SourceId, + bindeps: bool, + ) -> CargoResult<&IndexSummary> { let (start, end) = match self { MaybeIndexSummary::Unparsed { start, end } => (*start, *end), MaybeIndexSummary::Parsed(summary) => return Ok(summary), }; - let summary = IndexSummary::parse(&raw_data[start..end], source_id)?; + let summary = IndexSummary::parse(&raw_data[start..end], source_id, bindeps)?; *self = MaybeIndexSummary::Parsed(summary); match self { MaybeIndexSummary::Unparsed { .. } => unreachable!(), @@ -891,7 +921,7 @@ impl IndexSummary { /// /// The `line` provided is expected to be valid JSON. It is supposed to be /// a [`IndexPackage`]. - fn parse(line: &[u8], source_id: SourceId) -> CargoResult { + fn parse(line: &[u8], source_id: SourceId, bindeps: bool) -> CargoResult { // ****CAUTION**** Please be extremely careful with returning errors // from this function. Entries that error are not included in the // index cache, and can cause cargo to get confused when switching @@ -924,11 +954,20 @@ impl IndexSummary { } let mut summary = Summary::new(pkgid, deps, &features, links, rust_version)?; summary.set_checksum(cksum); - Ok(IndexSummary { - summary, - yanked: yanked.unwrap_or(false), - v, - }) + + let v_max = if bindeps { + INDEX_V_MAX + 1 + } else { + INDEX_V_MAX + }; + + if v_max < v { + return Ok(IndexSummary::Unsupported(summary, v)); + } + if yanked.unwrap_or(false) { + return Ok(IndexSummary::Yanked(summary)); + } + Ok(IndexSummary::Candidate(summary)) } } diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 2f3787e23dd..2a7c5959936 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -695,11 +695,10 @@ impl<'cfg> RegistrySource<'cfg> { .index .summaries(&package.name(), &req, &mut *self.ops)? .expect("a downloaded dep now pending!?") - .map(|s| s.summary.clone()) - .filter(|s| s.version() == package.version()) + .filter(|s| s.package_id().version() == package.version()) .next() .expect("summary not found"); - if let Some(cksum) = summary_with_cksum.checksum() { + if let Some(cksum) = summary_with_cksum.as_summary().checksum() { pkg.manifest_mut() .summary_mut() .set_checksum(cksum.to_string()); From 366e871778a5efdbf74e4b0a5413558b0cac13da Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 4/7] use the `hash` method not a copy paste of its code --- src/cargo/sources/registry/index.rs | 2 +- src/cargo/sources/registry/mod.rs | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index c4b753051a8..f4a7c17a8a6 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -430,7 +430,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// /// Internally there's quite a few layer of caching to amortize this cost /// though since this method is called quite a lot on null builds in Cargo. - pub fn summaries<'a, 'b>( + fn summaries<'a, 'b>( &'a mut self, name: &str, req: &'b OptVersionReq, diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index 2a7c5959936..d8fc47ba975 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -208,9 +208,7 @@ use crate::sources::source::Source; use crate::sources::PathSource; use crate::util::hex; use crate::util::network::PollExt; -use crate::util::{ - restricted_names, CargoResult, Config, Filesystem, LimitErrorReader, OptVersionReq, -}; +use crate::util::{restricted_names, CargoResult, Config, Filesystem, LimitErrorReader}; /// The `.cargo-ok` file is used to track if the source is already unpacked. /// See [`RegistrySource::unpack_package`] for more. @@ -690,19 +688,14 @@ impl<'cfg> RegistrySource<'cfg> { // After we've loaded the package configure its summary's `checksum` // field with the checksum we know for this `PackageId`. - let req = OptVersionReq::exact(package.version()); - let summary_with_cksum = self + let cksum = self .index - .summaries(&package.name(), &req, &mut *self.ops)? + .hash(package, &mut *self.ops) .expect("a downloaded dep now pending!?") - .filter(|s| s.package_id().version() == package.version()) - .next() .expect("summary not found"); - if let Some(cksum) = summary_with_cksum.as_summary().checksum() { - pkg.manifest_mut() - .summary_mut() - .set_checksum(cksum.to_string()); - } + pkg.manifest_mut() + .summary_mut() + .set_checksum(cksum.to_string()); Ok(pkg) } From 231e4f315b861abf3744d471cf1cd0beb1f6ef18 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 5/7] Even fewer temporary needless strings --- src/cargo/sources/registry/index.rs | 13 ++++++------- src/cargo/sources/registry/mod.rs | 10 ++++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index f4a7c17a8a6..bd6d73898b7 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -408,7 +408,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// the index file, aka [`IndexSummary`]. pub fn hash(&mut self, pkg: PackageId, load: &mut dyn RegistryData) -> Poll> { let req = OptVersionReq::exact(pkg.version()); - let summary = self.summaries(&pkg.name(), &req, load)?; + let summary = self.summaries(pkg.name(), &req, load)?; let summary = ready!(summary) .filter(|s| s.package_id().version() == pkg.version()) .next(); @@ -432,7 +432,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// though since this method is called quite a lot on null builds in Cargo. fn summaries<'a, 'b>( &'a mut self, - name: &str, + name: InternedString, req: &'b OptVersionReq, load: &mut dyn RegistryData, ) -> Poll + 'b>> @@ -444,7 +444,6 @@ impl<'cfg> RegistryIndex<'cfg> { let source_id = self.source_id; // First up parse what summaries we have available. - let name = InternedString::new(name); let summaries = ready!(self.load_summaries(name, load)?); // Iterate over our summaries, extract all relevant ones which match our @@ -539,7 +538,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// This is primarily used by [`Source::query`](super::Source). pub fn query_inner( &mut self, - name: &str, + name: InternedString, req: &OptVersionReq, load: &mut dyn RegistryData, yanked_whitelist: &HashSet, @@ -572,7 +571,7 @@ impl<'cfg> RegistryIndex<'cfg> { /// The `online` controls whether Cargo can access the network when needed. fn query_inner_with_online( &mut self, - name: &str, + name: InternedString, req: &OptVersionReq, load: &mut dyn RegistryData, yanked_whitelist: &HashSet, @@ -604,7 +603,7 @@ impl<'cfg> RegistryIndex<'cfg> { .map(|s| s.clone()); // Handle `cargo update --precise` here. - let precise = source_id.precise_registry_version(name); + let precise = source_id.precise_registry_version(name.as_str()); let summaries = summaries.filter(|s| match &precise { Some((current, requested)) => { if req.matches(current) { @@ -647,7 +646,7 @@ impl<'cfg> RegistryIndex<'cfg> { load: &mut dyn RegistryData, ) -> Poll> { let req = OptVersionReq::exact(pkg.version()); - let found = ready!(self.summaries(&pkg.name(), &req, load))? + let found = ready!(self.summaries(pkg.name(), &req, load))? .filter(|s| s.package_id().version() == pkg.version()) .any(|summary| matches!(summary, IndexSummary::Yanked(_))); Poll::Ready(Ok(found)) diff --git a/src/cargo/sources/registry/mod.rs b/src/cargo/sources/registry/mod.rs index d8fc47ba975..fb8f7981788 100644 --- a/src/cargo/sources/registry/mod.rs +++ b/src/cargo/sources/registry/mod.rs @@ -207,6 +207,7 @@ use crate::sources::source::QueryKind; use crate::sources::source::Source; use crate::sources::PathSource; use crate::util::hex; +use crate::util::interning::InternedString; use crate::util::network::PollExt; use crate::util::{restricted_names, CargoResult, Config, Filesystem, LimitErrorReader}; @@ -717,7 +718,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { debug!("attempting query without update"); let mut called = false; ready!(self.index.query_inner( - &dep.package_name(), + dep.package_name(), dep.version_req(), &mut *self.ops, &self.yanked_whitelist, @@ -738,7 +739,7 @@ impl<'cfg> Source for RegistrySource<'cfg> { } else { let mut called = false; ready!(self.index.query_inner( - &dep.package_name(), + dep.package_name(), dep.version_req(), &mut *self.ops, &self.yanked_whitelist, @@ -768,13 +769,14 @@ impl<'cfg> Source for RegistrySource<'cfg> { dep.package_name().replace('-', "_"), dep.package_name().replace('_', "-"), ] { - if name_permutation.as_str() == dep.package_name().as_str() { + let name_permutation = InternedString::new(&name_permutation); + if name_permutation == dep.package_name() { continue; } any_pending |= self .index .query_inner( - &name_permutation, + name_permutation, dep.version_req(), &mut *self.ops, &self.yanked_whitelist, From 7f6bef522efe12bfc6e5542acdd6a71d04732909 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Mon, 11 Sep 2023 16:19:15 +0000 Subject: [PATCH 6/7] handle offline one layer higher --- src/cargo/sources/registry/index.rs | 61 +++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index bd6d73898b7..e487bc0a16c 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -195,6 +195,8 @@ pub enum IndexSummary { Candidate(Summary), /// Yanked within its registry Yanked(Summary), + /// Not available as we are offline and create is not downloaded yet + Offline(Summary), /// From a newer schema version and is likely incomplete or inaccurate Unsupported(Summary, u32), } @@ -205,6 +207,7 @@ impl IndexSummary { match self { IndexSummary::Candidate(sum) | IndexSummary::Yanked(sum) + | IndexSummary::Offline(sum) | IndexSummary::Unsupported(sum, _) => sum, } } @@ -214,6 +217,7 @@ impl IndexSummary { match self { IndexSummary::Candidate(sum) | IndexSummary::Yanked(sum) + | IndexSummary::Offline(sum) | IndexSummary::Unsupported(sum, _) => sum.package_id(), } } @@ -471,6 +475,9 @@ impl<'cfg> RegistryIndex<'cfg> { ); None } + Ok(IndexSummary::Offline(_)) => { + unreachable!("We do not check for off-line until later") + } Err(e) => { info!("failed to parse `{}` registry package: {}", name, e); None @@ -555,14 +562,35 @@ impl<'cfg> RegistryIndex<'cfg> { // then cargo will fail to download and an error message // indicating that the required dependency is unavailable while // offline will be displayed. - if ready!(self.query_inner_with_online(name, req, load, yanked_whitelist, f, false)?) - > 0 - { + let mut called = false; + let callback = &mut |s: IndexSummary| { + if !matches!(&s, &IndexSummary::Offline(_)) { + called = true; + f(s.as_summary().clone()); + } + }; + ready!(self.query_inner_with_online( + name, + req, + load, + yanked_whitelist, + callback, + false + )?); + if called { return Poll::Ready(Ok(())); } } - self.query_inner_with_online(name, req, load, yanked_whitelist, f, true) - .map_ok(|_| ()) + self.query_inner_with_online( + name, + req, + load, + yanked_whitelist, + &mut |s| { + f(s.as_summary().clone()); + }, + true, + ) } /// Inner implementation of [`Self::query_inner`]. Returns the number of @@ -575,9 +603,9 @@ impl<'cfg> RegistryIndex<'cfg> { req: &OptVersionReq, load: &mut dyn RegistryData, yanked_whitelist: &HashSet, - f: &mut dyn FnMut(Summary), + f: &mut dyn FnMut(IndexSummary), online: bool, - ) -> Poll> { + ) -> Poll> { let source_id = self.source_id; let summaries = ready!(self.summaries(name, req, load))?; @@ -593,14 +621,19 @@ impl<'cfg> RegistryIndex<'cfg> { // does not satisfy the requirements, then resolution will // fail. Unfortunately, whether or not something is optional // is not known here. - .filter(|s| (online || load.is_crate_downloaded(s.package_id()))) + .map(|s| { + if online || load.is_crate_downloaded(s.package_id()) { + s.clone() + } else { + IndexSummary::Offline(s.as_summary().clone()) + } + }) // Next filter out all yanked packages. Some yanked packages may // leak through if they're in a whitelist (aka if they were // previously in `Cargo.lock` .filter(|s| { !matches!(s, IndexSummary::Yanked(_)) || yanked_whitelist.contains(&s.package_id()) - }) - .map(|s| s.clone()); + }); // Handle `cargo update --precise` here. let precise = source_id.precise_registry_version(name.as_str()); @@ -631,12 +664,8 @@ impl<'cfg> RegistryIndex<'cfg> { None => true, }); - let mut count = 0; - for summary in summaries { - f(summary.as_summary().clone()); - count += 1; - } - Poll::Ready(Ok(count)) + summaries.for_each(f); + Poll::Ready(Ok(())) } /// Looks into the summaries to check if a package has been yanked. From 5c8cf8dc163c261e920f9e989e500a03ab600f08 Mon Sep 17 00:00:00 2001 From: Jacob Finkelman Date: Mon, 11 Sep 2023 16:29:04 +0000 Subject: [PATCH 7/7] Small clarifications --- src/cargo/sources/registry/index.rs | 48 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/cargo/sources/registry/index.rs b/src/cargo/sources/registry/index.rs index e487bc0a16c..4b6d5048be6 100644 --- a/src/cargo/sources/registry/index.rs +++ b/src/cargo/sources/registry/index.rs @@ -212,6 +212,16 @@ impl IndexSummary { } } + /// Extract the summary from any variant + pub fn into_summary(self) -> Summary { + match self { + IndexSummary::Candidate(sum) + | IndexSummary::Yanked(sum) + | IndexSummary::Offline(sum) + | IndexSummary::Unsupported(sum, _) => sum, + } + } + /// Extract the package id from any variant pub fn package_id(&self) -> PackageId { match self { @@ -221,6 +231,22 @@ impl IndexSummary { | IndexSummary::Unsupported(sum, _) => sum.package_id(), } } + + /// Returns `true` if the index summary is [`Yanked`]. + /// + /// [`Yanked`]: IndexSummary::Yanked + #[must_use] + pub fn is_yanked(&self) -> bool { + matches!(self, Self::Yanked(..)) + } + + /// Returns `true` if the index summary is [`Offline`]. + /// + /// [`Offline`]: IndexSummary::Offline + #[must_use] + pub fn is_offline(&self) -> bool { + matches!(self, Self::Offline(..)) + } } /// A representation of the cache on disk that Cargo maintains of summaries. @@ -564,9 +590,9 @@ impl<'cfg> RegistryIndex<'cfg> { // offline will be displayed. let mut called = false; let callback = &mut |s: IndexSummary| { - if !matches!(&s, &IndexSummary::Offline(_)) { + if !s.is_offline() { called = true; - f(s.as_summary().clone()); + f(s.into_summary()); } }; ready!(self.query_inner_with_online( @@ -587,7 +613,7 @@ impl<'cfg> RegistryIndex<'cfg> { load, yanked_whitelist, &mut |s| { - f(s.as_summary().clone()); + f(s.into_summary()); }, true, ) @@ -631,9 +657,7 @@ impl<'cfg> RegistryIndex<'cfg> { // Next filter out all yanked packages. Some yanked packages may // leak through if they're in a whitelist (aka if they were // previously in `Cargo.lock` - .filter(|s| { - !matches!(s, IndexSummary::Yanked(_)) || yanked_whitelist.contains(&s.package_id()) - }); + .filter(|s| !s.is_yanked() || yanked_whitelist.contains(&s.package_id())); // Handle `cargo update --precise` here. let precise = source_id.precise_registry_version(name.as_str()); @@ -677,7 +701,7 @@ impl<'cfg> RegistryIndex<'cfg> { let req = OptVersionReq::exact(pkg.version()); let found = ready!(self.summaries(pkg.name(), &req, load))? .filter(|s| s.package_id().version() == pkg.version()) - .any(|summary| matches!(summary, IndexSummary::Yanked(_))); + .any(|s| s.is_yanked()); Poll::Ready(Ok(found)) } } @@ -990,12 +1014,12 @@ impl IndexSummary { }; if v_max < v { - return Ok(IndexSummary::Unsupported(summary, v)); - } - if yanked.unwrap_or(false) { - return Ok(IndexSummary::Yanked(summary)); + Ok(IndexSummary::Unsupported(summary, v)) + } else if yanked.unwrap_or(false) { + Ok(IndexSummary::Yanked(summary)) + } else { + Ok(IndexSummary::Candidate(summary)) } - Ok(IndexSummary::Candidate(summary)) } }