mirror of https://github.com/astral-sh/uv
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
|
|
@ -133,7 +133,7 @@ pub enum EnvironmentPreference {
|
||||||
Any,
|
Any,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum PythonVariant {
|
pub enum PythonVariant {
|
||||||
#[default]
|
#[default]
|
||||||
Default,
|
Default,
|
||||||
|
|
|
||||||
|
|
@ -405,5 +405,6 @@ impl Ord for PythonInstallationKey {
|
||||||
.then_with(|| self.os.to_string().cmp(&other.os.to_string()))
|
.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.arch.to_string().cmp(&other.arch.to_string()))
|
||||||
.then_with(|| self.libc.to_string().cmp(&other.libc.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 futures::StreamExt;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
@ -63,7 +64,7 @@ pub(crate) async fn install(
|
||||||
.inspect(|installation| debug!("Found existing installation {}", installation.key()))
|
.inspect(|installation| debug!("Found existing installation {}", installation.key()))
|
||||||
.collect();
|
.collect();
|
||||||
let mut unfilled_requests = Vec::new();
|
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) {
|
for (request, download_request) in requests.iter().zip(download_requests) {
|
||||||
if matches!(requests.as_slice(), [PythonRequest::Default]) {
|
if matches!(requests.as_slice(), [PythonRequest::Default]) {
|
||||||
writeln!(printer.stderr(), "Searching for Python installations")?;
|
writeln!(printer.stderr(), "Searching for Python installations")?;
|
||||||
|
|
@ -89,7 +90,7 @@ pub(crate) async fn install(
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
if reinstall {
|
if reinstall {
|
||||||
uninstalled.push(installation.key().clone());
|
uninstalled.insert(installation.key());
|
||||||
unfilled_requests.push(download_request);
|
unfilled_requests.push(download_request);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -155,7 +156,7 @@ pub(crate) async fn install(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut installed = vec![];
|
let mut installed = FxHashSet::default();
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
while let Some((key, result)) = tasks.next().await {
|
while let Some((key, result)) = tasks.next().await {
|
||||||
match result {
|
match result {
|
||||||
|
|
@ -166,7 +167,7 @@ pub(crate) async fn install(
|
||||||
DownloadResult::Fetched(path) => path,
|
DownloadResult::Fetched(path) => path,
|
||||||
};
|
};
|
||||||
|
|
||||||
installed.push(key.clone());
|
installed.insert(key);
|
||||||
|
|
||||||
// Ensure the installations have externally managed markers
|
// Ensure the installations have externally managed markers
|
||||||
let managed = ManagedPythonInstallation::new(path.clone())?;
|
let managed = ManagedPythonInstallation::new(path.clone())?;
|
||||||
|
|
@ -180,7 +181,8 @@ pub(crate) async fn install(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !installed.is_empty() {
|
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"
|
// Ex) "Installed Python 3.9.7 in 1.68s"
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
|
|
@ -194,29 +196,38 @@ pub(crate) async fn install(
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
// Ex) "Installed 2 versions in 1.68s"
|
// Ex) "Installed 2 versions in 1.68s"
|
||||||
let s = if installed.len() == 1 { "" } else { "s" };
|
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format!(
|
format!(
|
||||||
"Installed {} {}",
|
"Installed {} {}",
|
||||||
format!("{} version{s}", installed.len()).bold(),
|
format!("{} versions", installed.len()).bold(),
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||||
)
|
)
|
||||||
.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
|
for event in uninstalled
|
||||||
.into_iter()
|
|
||||||
.map(|key| ChangeEvent {
|
.map(|key| ChangeEvent {
|
||||||
key,
|
key: key.clone(),
|
||||||
kind: ChangeEventKind::Removed,
|
kind: ChangeEventKind::Removed,
|
||||||
})
|
})
|
||||||
.chain(installed.into_iter().map(|key| ChangeEvent {
|
.chain(installed.map(|key| ChangeEvent {
|
||||||
key,
|
key: key.clone(),
|
||||||
kind: ChangeEventKind::Added,
|
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)))
|
.sorted_unstable_by(|a, b| a.key.cmp(&b.key).then_with(|| a.kind.cmp(&b.kind)))
|
||||||
{
|
{
|
||||||
match event.kind {
|
match event.kind {
|
||||||
|
|
@ -226,6 +237,9 @@ pub(crate) async fn install(
|
||||||
ChangeEventKind::Removed => {
|
ChangeEventKind::Removed => {
|
||||||
writeln!(printer.stderr(), " {} {}", "-".red(), event.key.bold())?;
|
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,
|
Removed,
|
||||||
/// The Python version was installed.
|
/// The Python version was installed.
|
||||||
Added,
|
Added,
|
||||||
|
/// The Python version was reinstalled.
|
||||||
|
Reinstalled,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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)))
|
.sorted_unstable_by(|a, b| a.key.cmp(&b.key).then_with(|| a.kind.cmp(&b.kind)))
|
||||||
{
|
{
|
||||||
match event.kind {
|
match event.kind {
|
||||||
ChangeEventKind::Added => {
|
|
||||||
writeln!(printer.stderr(), " {} {}", "+".green(), event.key.bold())?;
|
|
||||||
}
|
|
||||||
ChangeEventKind::Removed => {
|
ChangeEventKind::Removed => {
|
||||||
writeln!(printer.stderr(), " {} {}", "-".red(), event.key.bold())?;
|
writeln!(printer.stderr(), " {} {}", "-".red(), event.key.bold())?;
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue