Skip to content

Commit

Permalink
Indicate that uv lock --upgrade has updated the lock file (#5110)
Browse files Browse the repository at this point in the history
## Summary

Resolves #4346, I've gone with the suggested `cargo` approach here.

## Test Plan

`cargo test`

```console
❯ ../target/debug/uv lock --upgrade
warning: `uv lock` is experimental and may change without warning.
Resolved 11 packages in 41ms
Updating flask v2.3.3 -> v3.0.3
note: pass `--verbose` to see 9 unchanged dependencies
❯ ../target/debug/uv lock --upgrade -vv
    0.002478s DEBUG uv uv 0.2.24
warning: `uv lock` is experimental and may change without warning.
....
Resolved 11 packages in 50ms
    0.103703s DEBUG uv::commands::project::lock Unchanged blinker v1.8.2
    0.103719s DEBUG uv::commands::project::lock Unchanged click v8.1.7
    0.103731s DEBUG uv::commands::project::lock Unchanged colorama v0.4.6
    0.103742s DEBUG uv::commands::project::lock Unchanged flask v3.0.3
    0.103754s DEBUG uv::commands::project::lock Unchanged importlib-metadata v8.0.0
    0.103767s DEBUG uv::commands::project::lock Unchanged itsdangerous v2.2.0
    0.103778s DEBUG uv::commands::project::lock Unchanged jinja2 v3.1.4
    0.103788s DEBUG uv::commands::project::lock Unchanged markupsafe v2.1.5
    0.103798s DEBUG uv::commands::project::lock Unchanged werkzeug v3.0.3
    0.103809s DEBUG uv::commands::project::lock Unchanged zipp v3.19.2
```
  • Loading branch information
blueraft authored Jul 17, 2024
1 parent 6ac46d7 commit eb35c05
Show file tree
Hide file tree
Showing 3 changed files with 701 additions and 5 deletions.
2 changes: 1 addition & 1 deletion crates/uv-resolver/src/lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ impl Distribution {
}

/// Returns a [`VersionId`] for this package that can be used for resolution.
fn version_id(&self, workspace_root: &Path) -> Result<VersionId, LockError> {
pub fn version_id(&self, workspace_root: &Path) -> Result<VersionId, LockError> {
match &self.id.source {
Source::Registry(_) => Ok(VersionId::NameVersion(
self.name().clone(),
Expand Down
78 changes: 75 additions & 3 deletions crates/uv/src/commands/project/lock.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
#![allow(clippy::single_match_else)]

use anstream::eprint;

use distribution_types::{Diagnostic, UnresolvedRequirementSpecification};
use distribution_types::{Diagnostic, UnresolvedRequirementSpecification, VersionId};
use owo_colors::OwoColorize;
use pep440_rs::Version;
use rustc_hash::{FxBuildHasher, FxHashMap};
use std::collections::BTreeSet;
use std::{fmt::Write, path::Path};
use tracing::debug;
use uv_cache::Cache;
use uv_client::{Connectivity, FlatIndexClient, RegistryClientBuilder};
use uv_configuration::{Concurrency, ExtrasSpecification, PreviewMode, Reinstall, SetupPyStrategy};
use uv_dispatch::BuildDispatch;
use uv_distribution::{Workspace, DEV_DEPENDENCIES};
use uv_git::ResolvedRepositoryReference;
use uv_normalize::PackageName;
use uv_python::{Interpreter, PythonFetch, PythonPreference, PythonRequest};
use uv_requirements::upgrade::{read_lock_requirements, LockedRequirements};
use uv_resolver::{FlatIndex, Lock, OptionsBuilder, PythonRequirement, RequiresPython};
Expand Down Expand Up @@ -367,7 +372,16 @@ pub(super) async fn do_lock(
// Notify the user of any resolution diagnostics.
pip::operations::diagnose_resolution(resolution.diagnostics(), printer)?;

Ok(Lock::from_resolution_graph(&resolution)?)
let new_lock = Lock::from_resolution_graph(&resolution)?;

// Notify the user of any dependency updates
if !upgrade.is_none() {
if let Some(existing_lock) = existing_lock {
report_upgrades(existing_lock, &new_lock, workspace.install_path(), printer)?;
}
}

Ok(new_lock)
}

/// Write the lockfile to disk.
Expand All @@ -393,3 +407,61 @@ pub(crate) async fn read(workspace: &Workspace) -> Result<Option<Lock>, ProjectE
Err(err) => Err(err.into()),
}
}

/// Reports on the versions that were upgraded in the new lockfile.
fn report_upgrades(
existing_lock: &Lock,
new_lock: &Lock,
workspace_root: &Path,
printer: Printer,
) -> anyhow::Result<()> {
let existing_distributions: FxHashMap<PackageName, BTreeSet<Version>> =
existing_lock.distributions().iter().fold(
FxHashMap::with_capacity_and_hasher(existing_lock.distributions().len(), FxBuildHasher),
|mut acc, distribution| {
if let Ok(VersionId::NameVersion(name, version)) =
distribution.version_id(workspace_root)
{
acc.entry(name).or_default().insert(version);
}
acc
},
);

let new_distribution_names: FxHashMap<PackageName, BTreeSet<Version>> =
new_lock.distributions().iter().fold(
FxHashMap::with_capacity_and_hasher(new_lock.distributions().len(), FxBuildHasher),
|mut acc, distribution| {
if let Ok(VersionId::NameVersion(name, version)) =
distribution.version_id(workspace_root)
{
acc.entry(name).or_default().insert(version);
}
acc
},
);

for (name, new_versions) in new_distribution_names {
if let Some(existing_versions) = existing_distributions.get(&name) {
if new_versions != *existing_versions {
let existing_versions = existing_versions
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
let new_versions = new_versions
.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
writeln!(
printer.stderr(),
"{} {name} v{existing_versions} -> v{new_versions}",
"Updating".green().bold()
)?;
}
}
}

Ok(())
}
Loading

0 comments on commit eb35c05

Please sign in to comment.