Skip to content

Commit 4d63fbc

Browse files
committed
Read/write the encoded cargo update --precise in the same place
1 parent d9a4cf1 commit 4d63fbc

File tree

3 files changed

+61
-34
lines changed

3 files changed

+61
-34
lines changed

src/cargo/core/source/source_id.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use crate::core::PackageId;
22
use crate::sources::registry::CRATES_IO_HTTP_INDEX;
33
use crate::sources::{DirectorySource, CRATES_IO_DOMAIN, CRATES_IO_INDEX, CRATES_IO_REGISTRY};
44
use crate::sources::{GitSource, PathSource, RegistrySource};
5-
use crate::util::{config, CanonicalUrl, CargoResult, Config, IntoUrl};
5+
use crate::util::{config, CanonicalUrl, CargoResult, Config, IntoUrl, ToSemver};
6+
use anyhow::Context;
67
use serde::de;
78
use serde::ser;
89
use std::cmp::{self, Ordering};
@@ -430,11 +431,6 @@ impl SourceId {
430431
}
431432
}
432433

433-
/// Gets the value of the precise field.
434-
pub fn precise(self) -> Option<&'static str> {
435-
self.inner.precise.as_deref()
436-
}
437-
438434
/// Gets the Git reference if this is a git source, otherwise `None`.
439435
pub fn git_reference(self) -> Option<&'static GitReference> {
440436
match self.inner.kind {
@@ -443,6 +439,33 @@ impl SourceId {
443439
}
444440
}
445441

442+
/// Gets the value of the precise field.
443+
pub fn precise(self) -> Option<&'static str> {
444+
self.inner.precise.as_deref()
445+
}
446+
447+
/// Check if the precise data field stores information for this `name`
448+
/// from a call to [SourceId::with_precise_registry_version].
449+
///
450+
/// If so return the version currently in the lock file and the version to be updated to.
451+
/// If specified, our own source will have a precise version listed of the form
452+
// `<pkg>=<p_req>-><f_req>` where `<pkg>` is the name of a crate on
453+
// this source, `<p_req>` is the version installed and `<f_req>` is the
454+
// version requested (argument to `--precise`).
455+
pub fn precise_registry_version(
456+
self,
457+
name: &str,
458+
) -> Option<(semver::Version, semver::Version)> {
459+
self.inner
460+
.precise
461+
.as_deref()
462+
.and_then(|p| p.strip_prefix(name)?.strip_prefix('='))
463+
.map(|p| {
464+
let (current, requested) = p.split_once("->").unwrap();
465+
(current.to_semver().unwrap(), requested.to_semver().unwrap())
466+
})
467+
}
468+
446469
/// Creates a new `SourceId` from this source with the given `precise`.
447470
pub fn with_precise(self, v: Option<String>) -> SourceId {
448471
SourceId::wrap(SourceIdInner {
@@ -451,6 +474,23 @@ impl SourceId {
451474
})
452475
}
453476

477+
/// When updating a lock file on a version using `cargo update --precise`
478+
/// the requested version is stored in the precise field.
479+
/// On a registry dependency we also need to keep track of the package that
480+
/// should be updated and even which of the versions should be updated.
481+
/// All of this gets encoded in the precise field using this method.
482+
/// The data can be read with [SourceId::precise_registry_version]
483+
pub fn with_precise_registry_version(
484+
self,
485+
name: impl fmt::Display,
486+
version: &semver::Version,
487+
precise: &str,
488+
) -> CargoResult<SourceId> {
489+
semver::Version::parse(precise)
490+
.with_context(|| format!("invalid version format for precise version `{precise}`"))?;
491+
Ok(self.with_precise(Some(format!("{}={}->{}", name, version, precise))))
492+
}
493+
454494
/// Returns `true` if the remote registry is the standard <https://crates.io>.
455495
pub fn is_crates_io(self) -> bool {
456496
match self.inner.kind {

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use crate::core::{Resolve, SourceId, Workspace};
55
use crate::ops;
66
use crate::util::config::Config;
77
use crate::util::CargoResult;
8-
use anyhow::Context;
98
use std::collections::{BTreeMap, HashSet};
109
use termcolor::Color::{self, Cyan, Green, Red, Yellow};
1110
use tracing::debug;
@@ -88,27 +87,27 @@ pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoRes
8887
} else {
8988
let mut sources = Vec::new();
9089
for name in opts.to_update.iter() {
91-
let dep = previous_resolve.query(name)?;
90+
let pid = previous_resolve.query(name)?;
9291
if opts.recursive {
93-
fill_with_deps(&previous_resolve, dep, &mut to_avoid, &mut HashSet::new());
92+
fill_with_deps(&previous_resolve, pid, &mut to_avoid, &mut HashSet::new());
9493
} else {
95-
to_avoid.insert(dep);
94+
to_avoid.insert(pid);
9695
sources.push(match opts.precise {
9796
Some(precise) => {
9897
// TODO: see comment in `resolve.rs` as well, but this
9998
// seems like a pretty hokey reason to single out
10099
// the registry as well.
101-
let precise = if dep.source_id().is_registry() {
102-
semver::Version::parse(precise).with_context(|| {
103-
format!("invalid version format for precise version `{}`", precise)
104-
})?;
105-
format!("{}={}->{}", dep.name(), dep.version(), precise)
100+
if pid.source_id().is_registry() {
101+
pid.source_id().with_precise_registry_version(
102+
pid.name(),
103+
pid.version(),
104+
precise,
105+
)?
106106
} else {
107-
precise.to_string()
108-
};
109-
dep.source_id().with_precise(Some(precise))
107+
pid.source_id().with_precise(Some(precise.to_string()))
108+
}
110109
}
111-
None => dep.source_id().with_precise(None),
110+
None => pid.source_id().with_precise(None),
112111
});
113112
}
114113
if let Ok(unused_id) =

src/cargo/sources/registry/index.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ use crate::core::{PackageId, SourceId, Summary};
9191
use crate::sources::registry::{LoadResponse, RegistryData};
9292
use crate::util::interning::InternedString;
9393
use crate::util::IntoUrl;
94-
use crate::util::{
95-
internal, CargoResult, Config, Filesystem, OptVersionReq, PartialVersion, ToSemver,
96-
};
94+
use crate::util::{internal, CargoResult, Config, Filesystem, OptVersionReq, PartialVersion};
9795
use anyhow::bail;
9896
use cargo_util::{paths, registry::make_dep_path};
9997
use semver::Version;
@@ -582,18 +580,8 @@ impl<'cfg> RegistryIndex<'cfg> {
582580
.filter(|s| !s.yanked || yanked_whitelist.contains(&s.summary.package_id()))
583581
.map(|s| s.summary.clone());
584582

585-
// Handle `cargo update --precise` here. If specified, our own source
586-
// will have a precise version listed of the form
587-
// `<pkg>=<p_req>o-><f_req>` where `<pkg>` is the name of a crate on
588-
// this source, `<p_req>` is the version installed and `<f_req> is the
589-
// version requested (argument to `--precise`).
590-
let precise = source_id
591-
.precise()
592-
.filter(|p| p.starts_with(name) && p[name.len()..].starts_with('='))
593-
.map(|p| {
594-
let (current, requested) = p[name.len() + 1..].split_once("->").unwrap();
595-
(current.to_semver().unwrap(), requested.to_semver().unwrap())
596-
});
583+
// Handle `cargo update --precise` here.
584+
let precise = source_id.precise_registry_version(name);
597585
let summaries = summaries.filter(|s| match &precise {
598586
Some((current, requested)) => {
599587
if req.matches(current) {

0 commit comments

Comments
 (0)