From 66a603b6c49508b77183bf5933b2262892c1a351 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 6 Jan 2025 12:04:00 -0500 Subject: [PATCH] Use dynamic dispatch to simplify reporters (#10086) ## Summary Sort of undecided on this. These are already stored as `dyn Reporter` in each struct, so we're already using dynamic dispatch in that sense. But all the methods take `impl Reporter`. This is sometimes nice (the callsites are simpler?), but it also means that in practice, you often _can't_ pass `None` to these methods that accept `Option`, because Rust can't infer the generic type. Anyway, this adds more consistency and simplifies the setup by using `Arc` everywhere. --- .../src/distribution_database.rs | 7 ++--- crates/uv-distribution/src/reporter.rs | 17 ++++++----- crates/uv-distribution/src/source/mod.rs | 25 +++++++++++++---- crates/uv-git/src/resolver.rs | 6 ++-- crates/uv-git/src/source.rs | 11 ++++---- crates/uv-installer/src/installer.rs | 17 +++++------ crates/uv-installer/src/preparer.rs | 28 +++++++++++-------- crates/uv-requirements/src/extras.rs | 2 +- crates/uv-requirements/src/lookahead.rs | 2 +- crates/uv-requirements/src/source_tree.rs | 2 +- crates/uv-requirements/src/unnamed.rs | 2 +- crates/uv-resolver/src/resolver/mod.rs | 9 +++--- crates/uv-resolver/src/resolver/provider.rs | 10 +++---- crates/uv-resolver/src/resolver/reporter.rs | 15 ++++++++-- crates/uv/src/commands/pip/operations.rs | 19 ++++++++----- crates/uv/src/commands/project/add.rs | 12 ++++---- crates/uv/src/commands/project/lock.rs | 3 +- crates/uv/src/commands/project/mod.rs | 3 +- crates/uv/src/commands/reporters.rs | 1 + 19 files changed, 117 insertions(+), 74 deletions(-) diff --git a/crates/uv-distribution/src/distribution_database.rs b/crates/uv-distribution/src/distribution_database.rs index 06c21d007..79dc85187 100644 --- a/crates/uv-distribution/src/distribution_database.rs +++ b/crates/uv-distribution/src/distribution_database.rs @@ -82,11 +82,10 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { /// Set the [`Reporter`] to use for the [`DistributionDatabase`]. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { - let reporter = Arc::new(reporter); + pub fn with_reporter(self, reporter: Arc) -> Self { Self { - reporter: Some(reporter.clone()), - builder: self.builder.with_reporter(reporter), + builder: self.builder.with_reporter(reporter.clone()), + reporter: Some(reporter), ..self } } diff --git a/crates/uv-distribution/src/reporter.rs b/crates/uv-distribution/src/reporter.rs index e8e8b40d5..9be3a5fa4 100644 --- a/crates/uv-distribution/src/reporter.rs +++ b/crates/uv-distribution/src/reporter.rs @@ -29,15 +29,18 @@ pub trait Reporter: Send + Sync { fn on_download_complete(&self, name: &PackageName, id: usize); } -/// A facade for converting from [`Reporter`] to [`uv_git::Reporter`]. -pub(crate) struct Facade { - reporter: Arc, +impl dyn Reporter { + /// Converts this reporter to a [`uv_git::Reporter`]. + pub(crate) fn into_git_reporter(self: Arc) -> Arc { + Arc::new(Facade { + reporter: self.clone(), + }) + } } -impl From> for Facade { - fn from(reporter: Arc) -> Self { - Self { reporter } - } +/// A facade for converting from [`Reporter`] to [`uv_git::Reporter`]. +struct Facade { + reporter: Arc, } impl uv_git::Reporter for Facade { diff --git a/crates/uv-distribution/src/source/mod.rs b/crates/uv-distribution/src/source/mod.rs index 772c3d384..95d3f89d1 100644 --- a/crates/uv-distribution/src/source/mod.rs +++ b/crates/uv-distribution/src/source/mod.rs @@ -1,5 +1,13 @@ //! Fetch and build source distributions from remote sources. +// This is to squash warnings about `|r| r.into_git_reporter()`. Clippy wants +// me to eta-reduce that and write it as +// `<(dyn reporter::Reporter + 'static)>::into_git_reporter` +// instead. But that's a monster. On the other hand, applying this suppression +// instruction more granularly is annoying. So we just slap it on the module +// for now. ---AG +#![allow(clippy::redundant_closure_for_method_calls)] + use std::borrow::Cow; use std::ops::Bound; use std::path::{Path, PathBuf}; @@ -9,7 +17,6 @@ use std::sync::Arc; use crate::distribution_database::ManagedClient; use crate::error::Error; use crate::metadata::{ArchiveMetadata, GitWorkspaceMember, Metadata}; -use crate::reporter::Facade; use crate::source::built_wheel_metadata::BuiltWheelMetadata; use crate::source::revision::Revision; use crate::{Reporter, RequiresDist}; @@ -1330,7 +1337,9 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { resource.git, client.unmanaged.uncached_client(resource.url).clone(), self.build_context.cache().bucket(CacheBucket::Git), - self.reporter.clone().map(Facade::from), + self.reporter + .clone() + .map(|reporter| reporter.into_git_reporter()), ) .await?; @@ -1427,7 +1436,9 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { resource.git, client.unmanaged.uncached_client(resource.url).clone(), self.build_context.cache().bucket(CacheBucket::Git), - self.reporter.clone().map(Facade::from), + self.reporter + .clone() + .map(|reporter| reporter.into_git_reporter()), ) .await?; @@ -1603,7 +1614,9 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { &source.git, client.unmanaged.uncached_client(&source.url).clone(), self.build_context.cache().bucket(CacheBucket::Git), - self.reporter.clone().map(Facade::from), + self.reporter + .clone() + .map(|reporter| reporter.into_git_reporter()), ) .await?; } @@ -1614,7 +1627,9 @@ impl<'a, T: BuildContext> SourceDistributionBuilder<'a, T> { source.git, client.unmanaged.uncached_client(source.url).clone(), self.build_context.cache().bucket(CacheBucket::Git), - self.reporter.clone().map(Facade::from), + self.reporter + .clone() + .map(|reporter| reporter.into_git_reporter()), ) .await?; } diff --git a/crates/uv-git/src/resolver.rs b/crates/uv-git/src/resolver.rs index e0636ec24..741ee7acb 100644 --- a/crates/uv-git/src/resolver.rs +++ b/crates/uv-git/src/resolver.rs @@ -44,7 +44,7 @@ impl GitResolver { url: &GitUrl, client: ClientWithMiddleware, cache: PathBuf, - reporter: Option, + reporter: Option>, ) -> Result { debug!("Resolving source distribution from Git: {url}"); @@ -88,7 +88,7 @@ impl GitResolver { url: &GitUrl, client: ClientWithMiddleware, cache: PathBuf, - reporter: Option, + reporter: Option>, ) -> Result { debug!("Fetching source distribution from Git: {url}"); @@ -138,7 +138,7 @@ impl GitResolver { /// For example, given a Git dependency with a reference to a branch or tag, return a URL /// with a precise reference to the current commit of that branch or tag. /// - /// This method takes into account various normalizations that are independent from the Git + /// This method takes into account various normalizations that are independent of the Git /// layer. For example: removing `#subdirectory=pkg_dir`-like fragments, and removing `git+` /// prefix kinds. /// diff --git a/crates/uv-git/src/source.rs b/crates/uv-git/src/source.rs index 5b475af90..eff21786e 100644 --- a/crates/uv-git/src/source.rs +++ b/crates/uv-git/src/source.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::path::{Path, PathBuf}; +use std::sync::Arc; use anyhow::Result; use reqwest_middleware::ClientWithMiddleware; @@ -24,11 +25,11 @@ pub struct GitSource { /// The path to the Git source database. cache: PathBuf, /// The reporter to use for this source. - reporter: Option>, + reporter: Option>, } impl GitSource { - /// Initialize a new Git source. + /// Initialize a [`GitSource`] with the given Git URL, HTTP client, and cache path. pub fn new( git: GitUrl, client: impl Into, @@ -42,11 +43,11 @@ impl GitSource { } } - /// Set the [`Reporter`] to use for this `GIt` source. + /// Set the [`Reporter`] to use for the [`GitSource`]. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { - reporter: Some(Box::new(reporter)), + reporter: Some(reporter), ..self } } diff --git a/crates/uv-installer/src/installer.rs b/crates/uv-installer/src/installer.rs index f8fa0cbc0..e2db41b4c 100644 --- a/crates/uv-installer/src/installer.rs +++ b/crates/uv-installer/src/installer.rs @@ -1,21 +1,22 @@ +use std::convert; +use std::sync::{Arc, LazyLock}; + use anyhow::{Context, Error, Result}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -use std::convert; -use std::sync::LazyLock; use tokio::sync::oneshot; use tracing::instrument; -use uv_install_wheel::{linker::LinkMode, Layout}; use uv_cache::Cache; use uv_configuration::RAYON_INITIALIZE; use uv_distribution_types::CachedDist; +use uv_install_wheel::{linker::LinkMode, Layout}; use uv_python::PythonEnvironment; pub struct Installer<'a> { venv: &'a PythonEnvironment, link_mode: LinkMode, cache: Option<&'a Cache>, - reporter: Option>, + reporter: Option>, installer_name: Option, installer_metadata: bool, } @@ -50,9 +51,9 @@ impl<'a> Installer<'a> { /// Set the [`Reporter`] to use for this installer. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { - reporter: Some(Box::new(reporter)), + reporter: Some(reporter), ..self } } @@ -66,7 +67,7 @@ impl<'a> Installer<'a> { } } - /// Set the whether to link Uv specific files in dist-info + /// Set whether to install uv-specifier files in the dist-info directory. #[must_use] pub fn with_installer_metadata(self, installer_metadata: bool) -> Self { Self { @@ -151,7 +152,7 @@ fn install( layout: Layout, installer_name: Option, link_mode: LinkMode, - reporter: Option>, + reporter: Option>, relocatable: bool, installer_metadata: bool, ) -> Result> { diff --git a/crates/uv-installer/src/preparer.rs b/crates/uv-installer/src/preparer.rs index 4f3e3e46e..4b53654d0 100644 --- a/crates/uv-installer/src/preparer.rs +++ b/crates/uv-installer/src/preparer.rs @@ -48,15 +48,16 @@ impl<'a, Context: BuildContext> Preparer<'a, Context> { /// Set the [`Reporter`] to use for operations. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { - let reporter: Arc = Arc::new(reporter); + pub fn with_reporter(self, reporter: Arc) -> Self { Self { tags: self.tags, cache: self.cache, hashes: self.hashes, build_options: self.build_options, - database: self.database.with_reporter(Facade::from(reporter.clone())), - reporter: Some(reporter.clone()), + database: self + .database + .with_reporter(reporter.clone().into_distribution_reporter()), + reporter: Some(reporter), } } @@ -271,15 +272,20 @@ pub trait Reporter: Send + Sync { fn on_checkout_complete(&self, url: &Url, rev: &str, index: usize); } -/// A facade for converting from [`Reporter`] to [`uv_git::Reporter`]. -struct Facade { - reporter: Arc, +impl dyn Reporter { + /// Converts this reporter to a [`uv_distribution::Reporter`]. + pub(crate) fn into_distribution_reporter( + self: Arc, + ) -> Arc { + Arc::new(Facade { + reporter: self.clone(), + }) + } } -impl From> for Facade { - fn from(reporter: Arc) -> Self { - Self { reporter } - } +/// A facade for converting from [`Reporter`] to [`uv_distribution::Reporter`]. +struct Facade { + reporter: Arc, } impl uv_distribution::Reporter for Facade { diff --git a/crates/uv-requirements/src/extras.rs b/crates/uv-requirements/src/extras.rs index 2d72f6b1f..d8c2e6959 100644 --- a/crates/uv-requirements/src/extras.rs +++ b/crates/uv-requirements/src/extras.rs @@ -37,7 +37,7 @@ impl<'a, Context: BuildContext> ExtrasResolver<'a, Context> { /// Set the [`Reporter`] to use for this resolver. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { database: self.database.with_reporter(reporter), ..self diff --git a/crates/uv-requirements/src/lookahead.rs b/crates/uv-requirements/src/lookahead.rs index 77c18ea81..3f191ed17 100644 --- a/crates/uv-requirements/src/lookahead.rs +++ b/crates/uv-requirements/src/lookahead.rs @@ -67,7 +67,7 @@ impl<'a, Context: BuildContext> LookaheadResolver<'a, Context> { /// Set the [`Reporter`] to use for this resolver. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { database: self.database.with_reporter(reporter), ..self diff --git a/crates/uv-requirements/src/source_tree.rs b/crates/uv-requirements/src/source_tree.rs index 5c55c9dff..399120fd6 100644 --- a/crates/uv-requirements/src/source_tree.rs +++ b/crates/uv-requirements/src/source_tree.rs @@ -65,7 +65,7 @@ impl<'a, Context: BuildContext> SourceTreeResolver<'a, Context> { /// Set the [`Reporter`] to use for this resolver. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { database: self.database.with_reporter(reporter), ..self diff --git a/crates/uv-requirements/src/unnamed.rs b/crates/uv-requirements/src/unnamed.rs index 252cc368e..9356e42de 100644 --- a/crates/uv-requirements/src/unnamed.rs +++ b/crates/uv-requirements/src/unnamed.rs @@ -49,7 +49,7 @@ impl<'a, Context: BuildContext> NamedRequirementsResolver<'a, Context> { /// Set the [`Reporter`] to use for this resolver. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { + pub fn with_reporter(self, reporter: Arc) -> Self { Self { database: self.database.with_reporter(reporter), ..self diff --git a/crates/uv-resolver/src/resolver/mod.rs b/crates/uv-resolver/src/resolver/mod.rs index e6d36cbdb..270940ee1 100644 --- a/crates/uv-resolver/src/resolver/mod.rs +++ b/crates/uv-resolver/src/resolver/mod.rs @@ -73,7 +73,6 @@ pub use crate::resolver::provider::{ DefaultResolverProvider, MetadataResponse, PackageVersionsResult, ResolverProvider, VersionsResponse, WheelMetadataResult, }; -use crate::resolver::reporter::Facade; pub use crate::resolver::reporter::{BuildId, Reporter}; use crate::yanks::AllowedYanks; use crate::{marker, DependencyMode, Exclusions, FlatIndex, Options, ResolutionMode, VersionMap}; @@ -243,15 +242,15 @@ impl /// Set the [`Reporter`] to use for this installer. #[must_use] - pub fn with_reporter(self, reporter: impl Reporter + 'static) -> Self { - let reporter = Arc::new(reporter); - + pub fn with_reporter(self, reporter: Arc) -> Self { Self { state: ResolverState { reporter: Some(reporter.clone()), ..self.state }, - provider: self.provider.with_reporter(Facade { reporter }), + provider: self + .provider + .with_reporter(reporter.into_distribution_reporter()), } } diff --git a/crates/uv-resolver/src/resolver/provider.rs b/crates/uv-resolver/src/resolver/provider.rs index 03cda439d..2d6173a8c 100644 --- a/crates/uv-resolver/src/resolver/provider.rs +++ b/crates/uv-resolver/src/resolver/provider.rs @@ -2,7 +2,7 @@ use std::future::Future; use std::sync::Arc; use uv_configuration::BuildOptions; -use uv_distribution::{ArchiveMetadata, DistributionDatabase}; +use uv_distribution::{ArchiveMetadata, DistributionDatabase, Reporter}; use uv_distribution_types::{Dist, IndexCapabilities, IndexUrl, InstalledDist, RequestedDist}; use uv_normalize::PackageName; use uv_pep440::{Version, VersionSpecifiers}; @@ -97,9 +97,9 @@ pub trait ResolverProvider { dist: &'io InstalledDist, ) -> impl Future + 'io; - /// Set the [`uv_distribution::Reporter`] to use for this installer. + /// Set the [`Reporter`] to use for this installer. #[must_use] - fn with_reporter(self, reporter: impl uv_distribution::Reporter + 'static) -> Self; + fn with_reporter(self, reporter: Arc) -> Self; } /// The main IO backend for the resolver, which does cached requests network requests using the @@ -273,9 +273,9 @@ impl<'a, Context: BuildContext> ResolverProvider for DefaultResolverProvider<'a, } } - /// Set the [`uv_distribution::Reporter`] to use for this installer. + /// Set the [`Reporter`] to use for this installer. #[must_use] - fn with_reporter(self, reporter: impl uv_distribution::Reporter + 'static) -> Self { + fn with_reporter(self, reporter: Arc) -> Self { Self { fetcher: self.fetcher.with_reporter(reporter), ..self diff --git a/crates/uv-resolver/src/resolver/reporter.rs b/crates/uv-resolver/src/resolver/reporter.rs index 3010ec638..f2bf0f006 100644 --- a/crates/uv-resolver/src/resolver/reporter.rs +++ b/crates/uv-resolver/src/resolver/reporter.rs @@ -37,9 +37,20 @@ pub trait Reporter: Send + Sync { fn on_checkout_complete(&self, url: &Url, rev: &str, id: usize); } +impl dyn Reporter { + /// Converts this reporter to a [`uv_distribution::Reporter`]. + pub(crate) fn into_distribution_reporter( + self: Arc, + ) -> Arc { + Arc::new(Facade { + reporter: self.clone(), + }) + } +} + /// A facade for converting from [`Reporter`] to [`uv_distribution::Reporter`]. -pub(crate) struct Facade { - pub(crate) reporter: Arc, +struct Facade { + reporter: Arc, } impl uv_distribution::Reporter for Facade { diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index 0e854eb54..34604c350 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -6,6 +6,7 @@ use owo_colors::OwoColorize; use std::collections::{BTreeSet, HashSet}; use std::fmt::Write; use std::path::PathBuf; +use std::sync::Arc; use tracing::debug; use uv_tool::InstalledTools; @@ -138,7 +139,7 @@ pub(crate) async fn resolve( index, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) .await?, ); @@ -152,7 +153,7 @@ pub(crate) async fn resolve( index, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(source_trees.iter().map(PathBuf::as_path)) .await?; @@ -221,7 +222,7 @@ pub(crate) async fn resolve( index, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) .await?, ); @@ -251,7 +252,7 @@ pub(crate) async fn resolve( index, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(&resolver_env) .await? } @@ -297,7 +298,7 @@ pub(crate) async fn resolve( installed_packages, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), )? - .with_reporter(reporter); + .with_reporter(Arc::new(reporter)); resolver.resolve().await? }; @@ -460,7 +461,9 @@ pub(crate) async fn install( build_options, DistributionDatabase::new(client, build_dispatch, concurrency.downloads), ) - .with_reporter(PrepareReporter::from(printer).with_length(remote.len() as u64)); + .with_reporter(Arc::new( + PrepareReporter::from(printer).with_length(remote.len() as u64), + )); let wheels = preparer .prepare(remote.clone(), in_flight, resolution) @@ -519,7 +522,9 @@ pub(crate) async fn install( .with_link_mode(link_mode) .with_cache(cache) .with_installer_metadata(installer_metadata) - .with_reporter(InstallReporter::from(printer).with_length(installs.len() as u64)) + .with_reporter(Arc::new( + InstallReporter::from(printer).with_length(installs.len() as u64), + )) // This technically can block the runtime, but we are on the main thread and // have no other running tasks at this point, so this lets us avoid spawning a blocking // task. diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index 1220d532d..c721f1527 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -1,12 +1,12 @@ -use std::collections::hash_map::Entry; -use std::fmt::Write; -use std::io; -use std::path::{Path, PathBuf}; - use anyhow::{bail, Context, Result}; use itertools::Itertools; use owo_colors::OwoColorize; use rustc_hash::{FxBuildHasher, FxHashMap}; +use std::collections::hash_map::Entry; +use std::fmt::Write; +use std::io; +use std::path::{Path, PathBuf}; +use std::sync::Arc; use tracing::debug; use url::Url; @@ -350,7 +350,7 @@ pub(crate) async fn add( state.index(), DistributionDatabase::new(&client, &build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) .await?, ); diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index ec1b4c866..083aa940f 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -3,6 +3,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Write; use std::path::Path; +use std::sync::Arc; use owo_colors::OwoColorize; use rustc_hash::{FxBuildHasher, FxHashMap}; @@ -625,7 +626,7 @@ async fn do_lock( // Resolve the requirements. let resolution = pip::operations::resolve( ExtrasResolver::new(&hasher, state.index(), database) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(target.members_requirements()) .await .map_err(|err| ProjectError::Operation(err.into()))? diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index d7807c29a..0c96a5b52 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -1,6 +1,7 @@ use std::collections::BTreeSet; use std::fmt::Write; use std::path::{Path, PathBuf}; +use std::sync::Arc; use itertools::Itertools; use owo_colors::OwoColorize; @@ -1077,7 +1078,7 @@ pub(crate) async fn resolve_names( state.index(), DistributionDatabase::new(&client, &build_dispatch, concurrency.downloads), ) - .with_reporter(ResolverReporter::from(printer)) + .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) .await?, ); diff --git a/crates/uv/src/commands/reporters.rs b/crates/uv/src/commands/reporters.rs index 0ceef7f8d..1e3fdb1e5 100644 --- a/crates/uv/src/commands/reporters.rs +++ b/crates/uv/src/commands/reporters.rs @@ -6,6 +6,7 @@ use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use owo_colors::OwoColorize; use rustc_hash::FxHashMap; use url::Url; + use uv_cache::Removal; use uv_distribution_types::{ BuildableSource, CachedDist, DistributionMetadata, Name, SourceDist, VersionOrUrlRef,