Skip to content

Commit dff1874

Browse files
committed
move handling precise up
1 parent df35092 commit dff1874

File tree

3 files changed

+60
-45
lines changed

3 files changed

+60
-45
lines changed

src/cargo/sources/registry/index.rs

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ use cargo_util::{paths, registry::make_dep_path};
9898
use semver::Version;
9999
use serde::Deserialize;
100100
use std::borrow::Cow;
101-
use std::cmp::Ordering;
102101
use std::collections::BTreeMap;
103102
use std::collections::{HashMap, HashSet};
104103
use std::fs;
@@ -632,11 +631,7 @@ impl<'cfg> RegistryIndex<'cfg> {
632631
f: &mut dyn FnMut(IndexSummary),
633632
online: bool,
634633
) -> Poll<CargoResult<()>> {
635-
let source_id = self.source_id;
636-
637-
let summaries = ready!(self.summaries(name, req, load))?;
638-
639-
let summaries = summaries
634+
ready!(self.summaries(name, &req, load))?
640635
// First filter summaries for `--offline`. If we're online then
641636
// everything is a candidate, otherwise if we're offline we're only
642637
// going to consider candidates which are actually present on disk.
@@ -657,35 +652,8 @@ impl<'cfg> RegistryIndex<'cfg> {
657652
// Next filter out all yanked packages. Some yanked packages may
658653
// leak through if they're in a whitelist (aka if they were
659654
// previously in `Cargo.lock`
660-
.filter(|s| !s.is_yanked() || yanked_whitelist.contains(&s.package_id()));
661-
662-
// Handle `cargo update --precise` here.
663-
let precise = source_id.precise_registry_version(name.as_str());
664-
let summaries = summaries.filter(|s| match precise {
665-
Some((current, requested)) => {
666-
if req.matches(current) {
667-
// Unfortunately crates.io allows versions to differ only
668-
// by build metadata. This shouldn't be allowed, but since
669-
// it is, this will honor it if requested. However, if not
670-
// specified, then ignore it.
671-
let s_vers = s.package_id().version();
672-
match (s_vers.build.is_empty(), requested.build.is_empty()) {
673-
(true, true) => s_vers == requested,
674-
(true, false) => false,
675-
(false, true) => {
676-
// Compare disregarding the metadata.
677-
s_vers.cmp_precedence(requested) == Ordering::Equal
678-
}
679-
(false, false) => s_vers == requested,
680-
}
681-
} else {
682-
true
683-
}
684-
}
685-
None => true,
686-
});
687-
688-
summaries.for_each(f);
655+
.filter(|s| !s.is_yanked() || yanked_whitelist.contains(&s.package_id()))
656+
.for_each(f);
689657
Poll::Ready(Ok(()))
690658
}
691659

src/cargo/sources/registry/mod.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,16 +712,27 @@ impl<'cfg> Source for RegistrySource<'cfg> {
712712
kind: QueryKind,
713713
f: &mut dyn FnMut(Summary),
714714
) -> Poll<CargoResult<()>> {
715-
// If this is a precise dependency, then it came from a lock file and in
715+
let mut req = dep.version_req().clone();
716+
717+
// Handle `cargo update --precise` here.
718+
if let Some((_, requested)) = self
719+
.source_id
720+
.precise_registry_version(dep.package_name().as_str())
721+
.filter(|(c, _)| req.matches(c))
722+
{
723+
req.update_precise(&requested);
724+
}
725+
726+
// If this is a locked dependency, then it came from a lock file and in
716727
// theory the registry is known to contain this version. If, however, we
717728
// come back with no summaries, then our registry may need to be
718729
// updated, so we fall back to performing a lazy update.
719-
if kind == QueryKind::Exact && dep.source_id().has_precise() && !self.ops.is_updated() {
730+
if kind == QueryKind::Exact && req.is_locked() && !self.ops.is_updated() {
720731
debug!("attempting query without update");
721732
let mut called = false;
722733
ready!(self.index.query_inner(
723734
dep.package_name(),
724-
dep.version_req(),
735+
&req,
725736
&mut *self.ops,
726737
&self.yanked_whitelist,
727738
&mut |s| {
@@ -742,7 +753,7 @@ impl<'cfg> Source for RegistrySource<'cfg> {
742753
let mut called = false;
743754
ready!(self.index.query_inner(
744755
dep.package_name(),
745-
dep.version_req(),
756+
&req,
746757
&mut *self.ops,
747758
&self.yanked_whitelist,
748759
&mut |s| {
@@ -779,7 +790,7 @@ impl<'cfg> Source for RegistrySource<'cfg> {
779790
.index
780791
.query_inner(
781792
name_permutation,
782-
dep.version_req(),
793+
&req,
783794
&mut *self.ops,
784795
&self.yanked_whitelist,
785796
f,

src/cargo/util/semver_ext.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub enum OptVersionReq {
88
Req(VersionReq),
99
/// The exact locked version and the original version requirement.
1010
Locked(Version, VersionReq),
11+
/// The exact requested version and the original version requirement.
12+
UpdatePrecise(Version, VersionReq),
1113
}
1214

1315
pub trait VersionExt {
@@ -53,7 +55,7 @@ impl OptVersionReq {
5355
pub fn is_exact(&self) -> bool {
5456
match self {
5557
OptVersionReq::Any => false,
56-
OptVersionReq::Req(req) => {
58+
OptVersionReq::Req(req) | OptVersionReq::UpdatePrecise(_, req) => {
5759
req.comparators.len() == 1 && {
5860
let cmp = &req.comparators[0];
5961
cmp.op == Op::Exact && cmp.minor.is_some() && cmp.patch.is_some()
@@ -69,8 +71,24 @@ impl OptVersionReq {
6971
let version = version.clone();
7072
*self = match self {
7173
Any => Locked(version, VersionReq::STAR),
72-
Req(req) => Locked(version, req.clone()),
73-
Locked(_, req) => Locked(version, req.clone()),
74+
Req(req) | Locked(_, req) | UpdatePrecise(_, req) => Locked(version, req.clone()),
75+
};
76+
}
77+
78+
pub fn update_precise(&mut self, version: &Version) {
79+
assert!(
80+
self.matches(version),
81+
"cannot update_precise {} to {}",
82+
self,
83+
version
84+
);
85+
use OptVersionReq::*;
86+
let version = version.clone();
87+
*self = match self {
88+
Any => UpdatePrecise(version, VersionReq::STAR),
89+
Req(req) | Locked(_, req) | UpdatePrecise(_, req) => {
90+
UpdatePrecise(version, req.clone())
91+
}
7492
};
7593
}
7694

@@ -100,6 +118,23 @@ impl OptVersionReq {
100118
// we should not silently use `1.0.0+foo` even though they have the same version.
101119
v == version
102120
}
121+
OptVersionReq::UpdatePrecise(v, _) => {
122+
// This is used for the `--precise` field of cargo update.
123+
//
124+
// Unfortunately crates.io allowed versions to differ only
125+
// by build metadata. This shouldn't be allowed, but since
126+
// it is, this will honor it if requested.
127+
//
128+
// In that context we treat a requirement that does not have
129+
// build metadata as allowing any metadata. But, if a requirement
130+
// has build metadata, then we only allow it to match the exact
131+
// metadata.
132+
v.major == version.major
133+
&& v.minor == version.minor
134+
&& v.patch == version.patch
135+
&& v.pre == version.pre
136+
&& (v.build == version.build || v.build.is_empty())
137+
}
103138
}
104139
}
105140
}
@@ -108,8 +143,9 @@ impl Display for OptVersionReq {
108143
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109144
match self {
110145
OptVersionReq::Any => f.write_str("*"),
111-
OptVersionReq::Req(req) => Display::fmt(req, f),
112-
OptVersionReq::Locked(_, req) => Display::fmt(req, f),
146+
OptVersionReq::Req(req)
147+
| OptVersionReq::Locked(_, req)
148+
| OptVersionReq::UpdatePrecise(_, req) => Display::fmt(req, f),
113149
}
114150
}
115151
}

0 commit comments

Comments
 (0)