mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-02 18:12:17 +00:00
Use reinstall report formatting for uv python install --reinstall
(#8487)
## Summary Resolves #8456 ## Test Plan ```console $ cargo run -- python install 3.13 $ cargo run -- python install --reinstall 3.13 Searching for Python versions matching: Python 3.13 Found existing installation for Python 3.13: cpython-3.13.0-macos-aarch64-none Installed Python 3.13.0 in 7.39s ~ cpython-3.13.0-macos-aarch64-none ``` --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
parent
e9c08b1639
commit
9540d6ad24
5 changed files with 30 additions and 15 deletions
|
@ -133,7 +133,7 @@ pub enum EnvironmentPreference {
|
|||
Any,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum PythonVariant {
|
||||
#[default]
|
||||
Default,
|
||||
|
|
|
@ -405,5 +405,6 @@ impl Ord for PythonInstallationKey {
|
|||
.then_with(|| self.os.to_string().cmp(&other.os.to_string()))
|
||||
.then_with(|| self.arch.to_string().cmp(&other.arch.to_string()))
|
||||
.then_with(|| self.libc.to_string().cmp(&other.libc.to_string()))
|
||||
.then_with(|| self.variant.cmp(&other.variant))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use futures::stream::FuturesUnordered;
|
|||
use futures::StreamExt;
|
||||
use itertools::Itertools;
|
||||
use owo_colors::OwoColorize;
|
||||
use rustc_hash::FxHashSet;
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt::Write;
|
||||
use std::path::Path;
|
||||
|
@ -63,7 +64,7 @@ pub(crate) async fn install(
|
|||
.inspect(|installation| debug!("Found existing installation {}", installation.key()))
|
||||
.collect();
|
||||
let mut unfilled_requests = Vec::new();
|
||||
let mut uninstalled = Vec::new();
|
||||
let mut uninstalled = FxHashSet::default();
|
||||
for (request, download_request) in requests.iter().zip(download_requests) {
|
||||
if matches!(requests.as_slice(), [PythonRequest::Default]) {
|
||||
writeln!(printer.stderr(), "Searching for Python installations")?;
|
||||
|
@ -89,7 +90,7 @@ pub(crate) async fn install(
|
|||
)?;
|
||||
}
|
||||
if reinstall {
|
||||
uninstalled.push(installation.key().clone());
|
||||
uninstalled.insert(installation.key());
|
||||
unfilled_requests.push(download_request);
|
||||
}
|
||||
} else {
|
||||
|
@ -155,7 +156,7 @@ pub(crate) async fn install(
|
|||
});
|
||||
}
|
||||
|
||||
let mut installed = vec![];
|
||||
let mut installed = FxHashSet::default();
|
||||
let mut errors = vec![];
|
||||
while let Some((key, result)) = tasks.next().await {
|
||||
match result {
|
||||
|
@ -166,7 +167,7 @@ pub(crate) async fn install(
|
|||
DownloadResult::Fetched(path) => path,
|
||||
};
|
||||
|
||||
installed.push(key.clone());
|
||||
installed.insert(key);
|
||||
|
||||
// Ensure the installations have externally managed markers
|
||||
let managed = ManagedPythonInstallation::new(path.clone())?;
|
||||
|
@ -180,7 +181,8 @@ pub(crate) async fn install(
|
|||
}
|
||||
|
||||
if !installed.is_empty() {
|
||||
if let [installed] = installed.as_slice() {
|
||||
if installed.len() == 1 {
|
||||
let installed = installed.iter().next().unwrap();
|
||||
// Ex) "Installed Python 3.9.7 in 1.68s"
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
|
@ -194,29 +196,38 @@ pub(crate) async fn install(
|
|||
)?;
|
||||
} else {
|
||||
// Ex) "Installed 2 versions in 1.68s"
|
||||
let s = if installed.len() == 1 { "" } else { "s" };
|
||||
writeln!(
|
||||
printer.stderr(),
|
||||
"{}",
|
||||
format!(
|
||||
"Installed {} {}",
|
||||
format!("{} version{s}", installed.len()).bold(),
|
||||
format!("{} versions", installed.len()).bold(),
|
||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||
)
|
||||
.dimmed()
|
||||
)?;
|
||||
}
|
||||
|
||||
let reinstalled = uninstalled
|
||||
.intersection(&installed)
|
||||
.copied()
|
||||
.collect::<FxHashSet<_>>();
|
||||
let uninstalled = uninstalled.difference(&reinstalled).copied();
|
||||
let installed = installed.difference(&reinstalled).copied();
|
||||
|
||||
for event in uninstalled
|
||||
.into_iter()
|
||||
.map(|key| ChangeEvent {
|
||||
key,
|
||||
key: key.clone(),
|
||||
kind: ChangeEventKind::Removed,
|
||||
})
|
||||
.chain(installed.into_iter().map(|key| ChangeEvent {
|
||||
key,
|
||||
.chain(installed.map(|key| ChangeEvent {
|
||||
key: key.clone(),
|
||||
kind: ChangeEventKind::Added,
|
||||
}))
|
||||
.chain(reinstalled.iter().map(|&key| ChangeEvent {
|
||||
key: key.clone(),
|
||||
kind: ChangeEventKind::Reinstalled,
|
||||
}))
|
||||
.sorted_unstable_by(|a, b| a.key.cmp(&b.key).then_with(|| a.kind.cmp(&b.kind)))
|
||||
{
|
||||
match event.kind {
|
||||
|
@ -226,6 +237,9 @@ pub(crate) async fn install(
|
|||
ChangeEventKind::Removed => {
|
||||
writeln!(printer.stderr(), " {} {}", "-".red(), event.key.bold())?;
|
||||
}
|
||||
ChangeEventKind::Reinstalled => {
|
||||
writeln!(printer.stderr(), " {} {}", "~".yellow(), event.key.bold(),)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ pub(super) enum ChangeEventKind {
|
|||
Removed,
|
||||
/// The Python version was installed.
|
||||
Added,
|
||||
/// The Python version was reinstalled.
|
||||
Reinstalled,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -179,12 +179,10 @@ async fn do_uninstall(
|
|||
.sorted_unstable_by(|a, b| a.key.cmp(&b.key).then_with(|| a.kind.cmp(&b.kind)))
|
||||
{
|
||||
match event.kind {
|
||||
ChangeEventKind::Added => {
|
||||
writeln!(printer.stderr(), " {} {}", "+".green(), event.key.bold())?;
|
||||
}
|
||||
ChangeEventKind::Removed => {
|
||||
writeln!(printer.stderr(), " {} {}", "-".red(), event.key.bold())?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue