mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Try installing exact versions before updating
When an exact version is being installed, if we already have that version from the index, we don't need to update the index before installing it. Don't do this if it's not an exact version, because the update may find us a newer version. This is particularly useful for scripts which unconditionally run `cargo install some-crate --version=1.2.3`. Before install-update, I wrote a crate to do this (https://crates.io/crates/cargo-ensure-installed) which I'm trying to replace with just `cargo install`, but the extra latency of updating the index for a no-op is noticeable. This introduces an interesting edge-case around yanked crates; the yanked-ness of crates will no longer change on install for exact version matches which were already downloaded. This feels niche enough to hopefully not matter...
This commit is contained in:
parent
e8b03443d6
commit
a721e62781
@ -151,7 +151,7 @@ fn install_one(
|
||||
krate,
|
||||
vers,
|
||||
config,
|
||||
true,
|
||||
NeedsUpdate::True,
|
||||
&mut |git| git.read_packages(),
|
||||
)?
|
||||
} else if source_id.is_path() {
|
||||
@ -180,7 +180,7 @@ fn install_one(
|
||||
}
|
||||
}
|
||||
src.update()?;
|
||||
select_pkg(src, krate, vers, config, false, &mut |path| {
|
||||
select_pkg(src, krate, vers, config, NeedsUpdate::False, &mut |path| {
|
||||
path.read_packages()
|
||||
})?
|
||||
} else {
|
||||
@ -189,7 +189,11 @@ fn install_one(
|
||||
krate,
|
||||
vers,
|
||||
config,
|
||||
is_first_install,
|
||||
if is_first_install {
|
||||
NeedsUpdate::TryWithoutFirst
|
||||
} else {
|
||||
NeedsUpdate::False
|
||||
},
|
||||
&mut |_| {
|
||||
bail!(
|
||||
"must specify a crate to install from \
|
||||
|
@ -85,7 +85,7 @@ fn uninstall_cwd(root: &Filesystem, bins: &[String], config: &Config) -> CargoRe
|
||||
let tracker = InstallTracker::load(config, root)?;
|
||||
let source_id = SourceId::for_path(config.cwd())?;
|
||||
let src = path_source(source_id, config)?;
|
||||
let pkg = select_pkg(src, None, None, config, true, &mut |path| {
|
||||
let pkg = select_pkg(src, None, None, config, NeedsUpdate::True, &mut |path| {
|
||||
path.read_packages()
|
||||
})?;
|
||||
let pkgid = pkg.package_id();
|
||||
|
@ -525,13 +525,20 @@ pub fn path_source(source_id: SourceId, config: &Config) -> CargoResult<PathSour
|
||||
Ok(PathSource::new(&path, source_id, config))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum NeedsUpdate {
|
||||
True,
|
||||
False,
|
||||
TryWithoutFirst,
|
||||
}
|
||||
|
||||
/// Gets a Package based on command-line requirements.
|
||||
pub fn select_pkg<'a, T>(
|
||||
mut source: T,
|
||||
name: Option<&str>,
|
||||
vers: Option<&str>,
|
||||
config: &Config,
|
||||
needs_update: bool,
|
||||
needs_update: NeedsUpdate,
|
||||
list_all: &mut dyn FnMut(&mut T) -> CargoResult<Vec<Package>>,
|
||||
) -> CargoResult<Package>
|
||||
where
|
||||
@ -542,7 +549,7 @@ where
|
||||
// with other global Cargos
|
||||
let _lock = config.acquire_package_cache_lock()?;
|
||||
|
||||
if needs_update {
|
||||
if let NeedsUpdate::True = needs_update {
|
||||
source.update()?;
|
||||
}
|
||||
|
||||
@ -603,8 +610,21 @@ where
|
||||
vers
|
||||
};
|
||||
let dep = Dependency::parse_no_deprecated(name, vers_spec, source.source_id())?;
|
||||
let deps = source.query_vec(&dep)?;
|
||||
match deps.iter().map(|p| p.package_id()).max() {
|
||||
let deps = (|| {
|
||||
if let Some(vers_spec) = vers_spec {
|
||||
if semver::VersionReq::parse(vers_spec).unwrap().is_exact() {
|
||||
let deps = source.query_vec(&dep)?;
|
||||
if deps.len() == 1 {
|
||||
return Ok(deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
if needs_update != NeedsUpdate::False {
|
||||
source.update()?;
|
||||
}
|
||||
source.query_vec(&dep)
|
||||
})();
|
||||
match deps?.iter().map(|p| p.package_id()).max() {
|
||||
Some(pkgid) => {
|
||||
let pkg = Box::new(&mut source).download_now(pkgid, config)?;
|
||||
Ok(pkg)
|
||||
|
@ -225,8 +225,7 @@ fn ambiguous_version_no_longer_allowed() {
|
||||
cargo_process("install foo --version=1.0")
|
||||
.with_stderr(
|
||||
"\
|
||||
[UPDATING] `[..]` index
|
||||
[ERROR] the `--vers` provided, `1.0`, is not a valid semver version: cannot parse '1.0' as a semver
|
||||
error: the `--vers` provided, `1.0`, is not a valid semver version: cannot parse '1.0' as a semver
|
||||
|
||||
if you want to specify semver range, add an explicit qualifier, like ^1.0
|
||||
",
|
||||
|
Loading…
x
Reference in New Issue
Block a user