mirror of https://github.com/astral-sh/uv
Refactor the Changelog for use in `report_dry_run` (#17039)
## Summary Remove duplication in `report_dry_run` by making `Changelog` support both local and remote dists. This is in support of #16653 and will form a new basis for #16981. This also involved refactoring `InstallLogger` and its implementations to support dry run logging. Additionally includes some minor refactoring in `SummaryInstallLogger` and a fix to `InstalledVersion`. See https://github.com/astral-sh/uv/compare/tk/dry-run-refactor for an alternative approach (although obviously comes with some caveats). ## Test Plan There are already quite a few tests which cover the output and they pass. Manual testing was used to ensure styling stayed consistent.
This commit is contained in:
parent
38ae414682
commit
6ad80c5150
|
|
@ -159,9 +159,9 @@ pub enum InstalledVersion<'a> {
|
||||||
Url(&'a DisplaySafeUrl, &'a Version),
|
Url(&'a DisplaySafeUrl, &'a Version),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstalledVersion<'_> {
|
impl<'a> InstalledVersion<'a> {
|
||||||
/// If it is a URL, return its value.
|
/// If it is a URL, return its value.
|
||||||
pub fn url(&self) -> Option<&DisplaySafeUrl> {
|
pub fn url(&self) -> Option<&'a DisplaySafeUrl> {
|
||||||
match self {
|
match self {
|
||||||
Self::Version(_) => None,
|
Self::Version(_) => None,
|
||||||
Self::Url(url, _) => Some(url),
|
Self::Url(url, _) => Some(url),
|
||||||
|
|
@ -169,7 +169,7 @@ impl InstalledVersion<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If it is a version, return its value.
|
/// If it is a version, return its value.
|
||||||
pub fn version(&self) -> &Version {
|
pub fn version(&self) -> &'a Version {
|
||||||
match self {
|
match self {
|
||||||
Self::Version(version) => version,
|
Self::Version(version) => version,
|
||||||
Self::Url(_, version) => version,
|
Self::Url(_, version) => version,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||||
use std::io::stdout;
|
use std::io::stdout;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{fmt::Display, fmt::Write, process::ExitCode};
|
use std::{fmt::Write, process::ExitCode};
|
||||||
|
|
||||||
use anstream::AutoStream;
|
use anstream::AutoStream;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
|
@ -62,10 +62,8 @@ pub(crate) use tool::upgrade::upgrade as tool_upgrade;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_configuration::Concurrency;
|
use uv_configuration::Concurrency;
|
||||||
pub(crate) use uv_console::human_readable_bytes;
|
pub(crate) use uv_console::human_readable_bytes;
|
||||||
use uv_distribution_types::InstalledMetadata;
|
|
||||||
use uv_fs::{CWD, Simplified};
|
use uv_fs::{CWD, Simplified};
|
||||||
use uv_installer::compile_tree;
|
use uv_installer::compile_tree;
|
||||||
use uv_normalize::PackageName;
|
|
||||||
use uv_python::PythonEnvironment;
|
use uv_python::PythonEnvironment;
|
||||||
use uv_scripts::Pep723Script;
|
use uv_scripts::Pep723Script;
|
||||||
pub(crate) use venv::venv;
|
pub(crate) use venv::venv;
|
||||||
|
|
@ -73,6 +71,7 @@ pub(crate) use workspace::dir::dir;
|
||||||
pub(crate) use workspace::list::list;
|
pub(crate) use workspace::list::list;
|
||||||
pub(crate) use workspace::metadata::metadata;
|
pub(crate) use workspace::metadata::metadata;
|
||||||
|
|
||||||
|
use crate::commands::pip::operations::ChangedDist;
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
|
|
@ -148,15 +147,8 @@ pub(super) enum ChangeEventKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(super) struct ChangeEvent<'a, T: InstalledMetadata> {
|
pub(super) struct ChangeEvent<'a> {
|
||||||
dist: &'a T,
|
dist: &'a ChangedDist,
|
||||||
kind: ChangeEventKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub(super) struct DryRunEvent<T: Display> {
|
|
||||||
name: PackageName,
|
|
||||||
version: T,
|
|
||||||
kind: ChangeEventKind,
|
kind: ChangeEventKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
@ -349,10 +348,7 @@ pub(crate) async fn pip_install(
|
||||||
debug!("Requirement satisfied: {requirement}");
|
debug!("Requirement satisfied: {requirement}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultInstallLogger.on_audit(requirements.len(), start, printer)?;
|
DefaultInstallLogger.on_audit(requirements.len(), start, printer, dry_run)?;
|
||||||
if dry_run.enabled() {
|
|
||||||
writeln!(printer.stderr(), "Would make no changes")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,24 @@ use itertools::Itertools;
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
use rustc_hash::{FxBuildHasher, FxHashMap};
|
use rustc_hash::{FxBuildHasher, FxHashMap};
|
||||||
|
|
||||||
use uv_distribution_types::{InstalledMetadata, Name};
|
use uv_configuration::DryRun;
|
||||||
|
use uv_distribution_types::Name;
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_pep440::Version;
|
|
||||||
|
|
||||||
use crate::commands::pip::operations::Changelog;
|
use crate::commands::pip::operations::{Changelog, ShortSpecifier};
|
||||||
use crate::commands::{ChangeEvent, ChangeEventKind, elapsed};
|
use crate::commands::{ChangeEvent, ChangeEventKind, elapsed};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
||||||
/// A trait to handle logging during install operations.
|
/// A trait to handle logging during install operations.
|
||||||
pub(crate) trait InstallLogger {
|
pub(crate) trait InstallLogger {
|
||||||
/// Log the completion of the audit phase.
|
/// Log the completion of the audit phase.
|
||||||
fn on_audit(&self, count: usize, start: std::time::Instant, printer: Printer) -> fmt::Result;
|
fn on_audit(
|
||||||
|
&self,
|
||||||
|
count: usize,
|
||||||
|
start: std::time::Instant,
|
||||||
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
|
) -> fmt::Result;
|
||||||
|
|
||||||
/// Log the completion of the preparation phase.
|
/// Log the completion of the preparation phase.
|
||||||
fn on_prepare(
|
fn on_prepare(
|
||||||
|
|
@ -26,6 +32,7 @@ pub(crate) trait InstallLogger {
|
||||||
suffix: Option<&str>,
|
suffix: Option<&str>,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
) -> fmt::Result;
|
) -> fmt::Result;
|
||||||
|
|
||||||
/// Log the completion of the uninstallation phase.
|
/// Log the completion of the uninstallation phase.
|
||||||
|
|
@ -34,13 +41,20 @@ pub(crate) trait InstallLogger {
|
||||||
count: usize,
|
count: usize,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
) -> fmt::Result;
|
) -> fmt::Result;
|
||||||
|
|
||||||
/// Log the completion of the installation phase.
|
/// Log the completion of the installation phase.
|
||||||
fn on_install(&self, count: usize, start: std::time::Instant, printer: Printer) -> fmt::Result;
|
fn on_install(
|
||||||
|
&self,
|
||||||
|
count: usize,
|
||||||
|
start: std::time::Instant,
|
||||||
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
|
) -> fmt::Result;
|
||||||
|
|
||||||
/// Log the completion of the operation.
|
/// Log the completion of the operation.
|
||||||
fn on_complete(&self, changelog: &Changelog, printer: Printer) -> fmt::Result;
|
fn on_complete(&self, changelog: &Changelog, printer: Printer, dry_run: DryRun) -> fmt::Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default logger for install operations.
|
/// The default logger for install operations.
|
||||||
|
|
@ -48,13 +62,19 @@ pub(crate) trait InstallLogger {
|
||||||
pub(crate) struct DefaultInstallLogger;
|
pub(crate) struct DefaultInstallLogger;
|
||||||
|
|
||||||
impl InstallLogger for DefaultInstallLogger {
|
impl InstallLogger for DefaultInstallLogger {
|
||||||
fn on_audit(&self, count: usize, start: std::time::Instant, printer: Printer) -> fmt::Result {
|
fn on_audit(
|
||||||
|
&self,
|
||||||
|
count: usize,
|
||||||
|
start: std::time::Instant,
|
||||||
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
|
) -> fmt::Result {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format!("Audited in {}", elapsed(start.elapsed())).dimmed()
|
format!("Audited in {}", elapsed(start.elapsed())).dimmed()
|
||||||
)
|
)?;
|
||||||
} else {
|
} else {
|
||||||
let s = if count == 1 { "" } else { "s" };
|
let s = if count == 1 { "" } else { "s" };
|
||||||
writeln!(
|
writeln!(
|
||||||
|
|
@ -66,8 +86,12 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||||
)
|
)
|
||||||
.dimmed()
|
.dimmed()
|
||||||
)
|
)?;
|
||||||
}
|
}
|
||||||
|
if dry_run.enabled() {
|
||||||
|
writeln!(printer.stderr(), "Would make no changes")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_prepare(
|
fn on_prepare(
|
||||||
|
|
@ -76,21 +100,26 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
suffix: Option<&str>,
|
suffix: Option<&str>,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
let s = if count == 1 { "" } else { "s" };
|
let s = if count == 1 { "" } else { "s" };
|
||||||
|
let what = if let Some(suffix) = suffix {
|
||||||
|
format!("{count} package{s} {suffix}")
|
||||||
|
} else {
|
||||||
|
format!("{count} package{s}")
|
||||||
|
};
|
||||||
|
let what = what.bold();
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format!(
|
if dry_run.enabled() {
|
||||||
"Prepared {} {}",
|
format!("Would download {what}")
|
||||||
if let Some(suffix) = suffix {
|
} else {
|
||||||
format!("{count} package{s} {suffix}")
|
format!(
|
||||||
} else {
|
"Prepared {what} {}",
|
||||||
format!("{count} package{s}")
|
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||||
}
|
)
|
||||||
.bold(),
|
}
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
|
||||||
)
|
|
||||||
.dimmed()
|
.dimmed()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -100,35 +129,57 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
count: usize,
|
count: usize,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
let s = if count == 1 { "" } else { "s" };
|
let s = if count == 1 { "" } else { "s" };
|
||||||
|
let what = format!("{count} package{s}");
|
||||||
|
let what = what.bold();
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format!(
|
if dry_run.enabled() {
|
||||||
"Uninstalled {} {}",
|
format!("Would uninstall {what}")
|
||||||
format!("{count} package{s}").bold(),
|
} else {
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
format!(
|
||||||
)
|
"Uninstalled {what} {}",
|
||||||
|
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||||
|
)
|
||||||
|
}
|
||||||
.dimmed()
|
.dimmed()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_install(&self, count: usize, start: std::time::Instant, printer: Printer) -> fmt::Result {
|
fn on_install(
|
||||||
|
&self,
|
||||||
|
count: usize,
|
||||||
|
start: std::time::Instant,
|
||||||
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
|
) -> fmt::Result {
|
||||||
let s = if count == 1 { "" } else { "s" };
|
let s = if count == 1 { "" } else { "s" };
|
||||||
|
let what = format!("{count} package{s}");
|
||||||
|
let what = what.bold();
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{}",
|
"{}",
|
||||||
format!(
|
if dry_run.enabled() {
|
||||||
"Installed {} {}",
|
format!("Would install {what}")
|
||||||
format!("{count} package{s}").bold(),
|
} else {
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
format!(
|
||||||
)
|
"Installed {what} {}",
|
||||||
|
format!("in {}", elapsed(start.elapsed())).dimmed()
|
||||||
|
)
|
||||||
|
}
|
||||||
.dimmed()
|
.dimmed()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_complete(&self, changelog: &Changelog, printer: Printer) -> fmt::Result {
|
fn on_complete(
|
||||||
|
&self,
|
||||||
|
changelog: &Changelog,
|
||||||
|
printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
|
) -> fmt::Result {
|
||||||
for event in changelog
|
for event in changelog
|
||||||
.uninstalled
|
.uninstalled
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -154,7 +205,7 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
.name()
|
.name()
|
||||||
.cmp(b.dist.name())
|
.cmp(b.dist.name())
|
||||||
.then_with(|| a.kind.cmp(&b.kind))
|
.then_with(|| a.kind.cmp(&b.kind))
|
||||||
.then_with(|| a.dist.installed_version().cmp(&b.dist.installed_version()))
|
.then_with(|| a.dist.long_specifier().cmp(&b.dist.long_specifier()))
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
match event.kind {
|
match event.kind {
|
||||||
|
|
@ -164,7 +215,7 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
" {} {}{}",
|
" {} {}{}",
|
||||||
"+".green(),
|
"+".green(),
|
||||||
event.dist.name().bold(),
|
event.dist.name().bold(),
|
||||||
event.dist.installed_version().dimmed()
|
event.dist.long_specifier().dimmed()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
ChangeEventKind::Removed => {
|
ChangeEventKind::Removed => {
|
||||||
|
|
@ -173,7 +224,7 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
" {} {}{}",
|
" {} {}{}",
|
||||||
"-".red(),
|
"-".red(),
|
||||||
event.dist.name().bold(),
|
event.dist.name().bold(),
|
||||||
event.dist.installed_version().dimmed()
|
event.dist.long_specifier().dimmed()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
ChangeEventKind::Reinstalled => {
|
ChangeEventKind::Reinstalled => {
|
||||||
|
|
@ -182,7 +233,7 @@ impl InstallLogger for DefaultInstallLogger {
|
||||||
" {} {}{}",
|
" {} {}{}",
|
||||||
"~".yellow(),
|
"~".yellow(),
|
||||||
event.dist.name().bold(),
|
event.dist.name().bold(),
|
||||||
event.dist.installed_version().dimmed()
|
event.dist.long_specifier().dimmed()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,6 +253,7 @@ impl InstallLogger for SummaryInstallLogger {
|
||||||
_count: usize,
|
_count: usize,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -212,6 +264,7 @@ impl InstallLogger for SummaryInstallLogger {
|
||||||
_suffix: Option<&str>,
|
_suffix: Option<&str>,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -221,35 +274,27 @@ impl InstallLogger for SummaryInstallLogger {
|
||||||
count: usize,
|
count: usize,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
|
dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
let s = if count == 1 { "" } else { "s" };
|
DefaultInstallLogger.on_uninstall(count, start, printer, dry_run)
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format!(
|
|
||||||
"Uninstalled {} {}",
|
|
||||||
format!("{count} package{s}").bold(),
|
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
|
||||||
)
|
|
||||||
.dimmed()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_install(&self, count: usize, start: std::time::Instant, printer: Printer) -> fmt::Result {
|
fn on_install(
|
||||||
let s = if count == 1 { "" } else { "s" };
|
&self,
|
||||||
writeln!(
|
count: usize,
|
||||||
printer.stderr(),
|
start: std::time::Instant,
|
||||||
"{}",
|
printer: Printer,
|
||||||
format!(
|
dry_run: DryRun,
|
||||||
"Installed {} {}",
|
) -> fmt::Result {
|
||||||
format!("{count} package{s}").bold(),
|
DefaultInstallLogger.on_install(count, start, printer, dry_run)
|
||||||
format!("in {}", elapsed(start.elapsed())).dimmed()
|
|
||||||
)
|
|
||||||
.dimmed()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_complete(&self, _changelog: &Changelog, _printer: Printer) -> fmt::Result {
|
fn on_complete(
|
||||||
|
&self,
|
||||||
|
_changelog: &Changelog,
|
||||||
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,6 +318,7 @@ impl InstallLogger for UpgradeInstallLogger {
|
||||||
_count: usize,
|
_count: usize,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -283,6 +329,7 @@ impl InstallLogger for UpgradeInstallLogger {
|
||||||
_suffix: Option<&str>,
|
_suffix: Option<&str>,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -292,6 +339,7 @@ impl InstallLogger for UpgradeInstallLogger {
|
||||||
_count: usize,
|
_count: usize,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -301,31 +349,38 @@ impl InstallLogger for UpgradeInstallLogger {
|
||||||
_count: usize,
|
_count: usize,
|
||||||
_start: std::time::Instant,
|
_start: std::time::Instant,
|
||||||
_printer: Printer,
|
_printer: Printer,
|
||||||
|
_dry_run: DryRun,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_complete(&self, changelog: &Changelog, printer: Printer) -> fmt::Result {
|
fn on_complete(
|
||||||
|
&self,
|
||||||
|
changelog: &Changelog,
|
||||||
|
printer: Printer,
|
||||||
|
// TODO(tk): Adjust format for dry_run
|
||||||
|
_dry_run: DryRun,
|
||||||
|
) -> fmt::Result {
|
||||||
// Index the removals by package name.
|
// Index the removals by package name.
|
||||||
let removals: FxHashMap<&PackageName, BTreeSet<Version>> =
|
let removals: FxHashMap<&PackageName, BTreeSet<ShortSpecifier>> =
|
||||||
changelog.uninstalled.iter().fold(
|
changelog.uninstalled.iter().fold(
|
||||||
FxHashMap::with_capacity_and_hasher(changelog.uninstalled.len(), FxBuildHasher),
|
FxHashMap::with_capacity_and_hasher(changelog.uninstalled.len(), FxBuildHasher),
|
||||||
|mut acc, distribution| {
|
|mut acc, distribution| {
|
||||||
acc.entry(distribution.name())
|
acc.entry(distribution.name())
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(distribution.installed_version().version().clone());
|
.insert(distribution.short_specifier());
|
||||||
acc
|
acc
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Index the additions by package name.
|
// Index the additions by package name.
|
||||||
let additions: FxHashMap<&PackageName, BTreeSet<Version>> =
|
let additions: FxHashMap<&PackageName, BTreeSet<ShortSpecifier>> =
|
||||||
changelog.installed.iter().fold(
|
changelog.installed.iter().fold(
|
||||||
FxHashMap::with_capacity_and_hasher(changelog.installed.len(), FxBuildHasher),
|
FxHashMap::with_capacity_and_hasher(changelog.installed.len(), FxBuildHasher),
|
||||||
|mut acc, distribution| {
|
|mut acc, distribution| {
|
||||||
acc.entry(distribution.name())
|
acc.entry(distribution.name())
|
||||||
.or_default()
|
.or_default()
|
||||||
.insert(distribution.installed_version().version().clone());
|
.insert(distribution.short_specifier());
|
||||||
acc
|
acc
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -407,7 +462,7 @@ impl InstallLogger for UpgradeInstallLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Follow-up with a detailed summary of all changes.
|
// Follow-up with a detailed summary of all changes.
|
||||||
DefaultInstallLogger.on_complete(changelog, printer)?;
|
DefaultInstallLogger.on_complete(changelog, printer, _dry_run)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,17 @@ use uv_configuration::{
|
||||||
use uv_dispatch::BuildDispatch;
|
use uv_dispatch::BuildDispatch;
|
||||||
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
|
use uv_distribution::{DistributionDatabase, SourcedDependencyGroups};
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
CachedDist, Diagnostic, InstalledDist, LocalDist, NameRequirementSpecification, Requirement,
|
CachedDist, Diagnostic, Dist, InstalledDist, InstalledVersion, LocalDist,
|
||||||
ResolutionDiagnostic, UnresolvedRequirement, UnresolvedRequirementSpecification,
|
NameRequirementSpecification, Requirement, ResolutionDiagnostic, UnresolvedRequirement,
|
||||||
|
UnresolvedRequirementSpecification, VersionOrUrlRef,
|
||||||
};
|
};
|
||||||
use uv_distribution_types::{DistributionMetadata, InstalledMetadata, Name, Resolution};
|
use uv_distribution_types::{DistributionMetadata, InstalledMetadata, Name, Resolution};
|
||||||
use uv_fs::Simplified;
|
use uv_fs::Simplified;
|
||||||
use uv_install_wheel::LinkMode;
|
use uv_install_wheel::LinkMode;
|
||||||
use uv_installer::{InstallationStrategy, Plan, Planner, Preparer, SitePackages};
|
use uv_installer::{InstallationStrategy, Plan, Planner, Preparer, SitePackages};
|
||||||
use uv_normalize::PackageName;
|
use uv_normalize::PackageName;
|
||||||
use uv_pep508::{MarkerEnvironment, RequirementOrigin};
|
use uv_pep440::Version;
|
||||||
|
use uv_pep508::{MarkerEnvironment, RequirementOrigin, VerbatimUrl};
|
||||||
use uv_platform_tags::Tags;
|
use uv_platform_tags::Tags;
|
||||||
use uv_preview::Preview;
|
use uv_preview::Preview;
|
||||||
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
|
use uv_pypi_types::{Conflicts, ResolverMarkerEnvironment};
|
||||||
|
|
@ -44,9 +46,9 @@ use uv_tool::InstalledTools;
|
||||||
use uv_types::{BuildContext, HashStrategy, InFlight, InstalledPackagesProvider};
|
use uv_types::{BuildContext, HashStrategy, InFlight, InstalledPackagesProvider};
|
||||||
use uv_warnings::warn_user;
|
use uv_warnings::warn_user;
|
||||||
|
|
||||||
use crate::commands::pip::loggers::{DefaultInstallLogger, InstallLogger, ResolveLogger};
|
use crate::commands::compile_bytecode;
|
||||||
|
use crate::commands::pip::loggers::{InstallLogger, ResolveLogger};
|
||||||
use crate::commands::reporters::{InstallReporter, PrepareReporter, ResolverReporter};
|
use crate::commands::reporters::{InstallReporter, PrepareReporter, ResolverReporter};
|
||||||
use crate::commands::{ChangeEventKind, DryRunEvent, compile_bytecode};
|
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
|
|
||||||
/// Consolidate the requirements for an installation.
|
/// Consolidate the requirements for an installation.
|
||||||
|
|
@ -381,30 +383,104 @@ pub(crate) enum Modifications {
|
||||||
Exact,
|
Exact,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A distribution which was or would be modified
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
|
pub(crate) enum ChangedDist {
|
||||||
|
Local(LocalDist),
|
||||||
|
Remote(Arc<Dist>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Name for ChangedDist {
|
||||||
|
fn name(&self) -> &PackageName {
|
||||||
|
match self {
|
||||||
|
Self::Local(dist) => dist.name(),
|
||||||
|
Self::Remote(dist) => dist.name(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`Version`] or [`VerbatimUrl`] for a changed dist.
|
||||||
|
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
||||||
|
pub(crate) enum ShortSpecifier<'a> {
|
||||||
|
Version(&'a Version),
|
||||||
|
Url(&'a VerbatimUrl),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ShortSpecifier<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Version(version) => version.fmt(f),
|
||||||
|
Self::Url(url) => write!(f, " @ {url}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [`InstalledVersion`] or [`VerbatimUrl`] for a changed dist.
|
||||||
|
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Hash)]
|
||||||
|
pub(crate) enum LongSpecifier<'a> {
|
||||||
|
InstalledVersion(InstalledVersion<'a>),
|
||||||
|
Url(&'a VerbatimUrl),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for LongSpecifier<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::InstalledVersion(version) => version.fmt(f),
|
||||||
|
Self::Url(url) => write!(f, " @ {url}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChangedDist {
|
||||||
|
pub(crate) fn short_specifier(&self) -> ShortSpecifier<'_> {
|
||||||
|
match self {
|
||||||
|
Self::Local(dist) => ShortSpecifier::Version(dist.installed_version().version()),
|
||||||
|
Self::Remote(dist) => match dist.version_or_url() {
|
||||||
|
VersionOrUrlRef::Version(version) => ShortSpecifier::Version(version),
|
||||||
|
VersionOrUrlRef::Url(url) => ShortSpecifier::Url(url),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn long_specifier(&self) -> LongSpecifier<'_> {
|
||||||
|
match self {
|
||||||
|
Self::Local(dist) => LongSpecifier::InstalledVersion(dist.installed_version()),
|
||||||
|
Self::Remote(dist) => match dist.version_or_url() {
|
||||||
|
VersionOrUrlRef::Version(version) => {
|
||||||
|
LongSpecifier::InstalledVersion(InstalledVersion::Version(version))
|
||||||
|
}
|
||||||
|
VersionOrUrlRef::Url(url) => LongSpecifier::Url(url),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A summary of the changes made to the environment during an installation.
|
/// A summary of the changes made to the environment during an installation.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub(crate) struct Changelog {
|
pub(crate) struct Changelog {
|
||||||
/// The distributions that were installed.
|
/// The distributions that were installed.
|
||||||
pub(crate) installed: HashSet<LocalDist>,
|
pub(crate) installed: HashSet<ChangedDist>,
|
||||||
/// The distributions that were uninstalled.
|
/// The distributions that were uninstalled.
|
||||||
pub(crate) uninstalled: HashSet<LocalDist>,
|
pub(crate) uninstalled: HashSet<ChangedDist>,
|
||||||
/// The distributions that were reinstalled.
|
/// The distributions that were reinstalled.
|
||||||
pub(crate) reinstalled: HashSet<LocalDist>,
|
pub(crate) reinstalled: HashSet<ChangedDist>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Changelog {
|
impl Changelog {
|
||||||
/// Create a [`Changelog`] from a list of installed and uninstalled distributions.
|
/// Create a [`Changelog`] from two iterators of [`ChangedDist`]s.
|
||||||
pub(crate) fn new(installed: Vec<CachedDist>, uninstalled: Vec<InstalledDist>) -> Self {
|
pub(crate) fn new<I, U>(installed: I, uninstalled: U) -> Self
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = ChangedDist>,
|
||||||
|
U: IntoIterator<Item = ChangedDist>,
|
||||||
|
{
|
||||||
// SAFETY: This is allowed because `LocalDist` implements `Hash` and `Eq` based solely on
|
// SAFETY: This is allowed because `LocalDist` implements `Hash` and `Eq` based solely on
|
||||||
// the inner `kind`, and omits the types that rely on internal mutability.
|
// the inner `kind`, and omits the types that rely on internal mutability.
|
||||||
#[allow(clippy::mutable_key_type)]
|
#[allow(clippy::mutable_key_type)]
|
||||||
let mut uninstalled: HashSet<_> = uninstalled.into_iter().map(LocalDist::from).collect();
|
let mut uninstalled: HashSet<_> = uninstalled.into_iter().collect();
|
||||||
|
|
||||||
let (reinstalled, installed): (HashSet<_>, HashSet<_>) = installed
|
let (reinstalled, installed): (HashSet<_>, HashSet<_>) = installed
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(LocalDist::from)
|
|
||||||
.partition(|dist| uninstalled.contains(dist));
|
.partition(|dist| uninstalled.contains(dist));
|
||||||
|
|
||||||
uninstalled.retain(|dist| !reinstalled.contains(dist));
|
uninstalled.retain(|dist| !reinstalled.contains(dist));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -414,13 +490,21 @@ impl Changelog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a [`Changelog`] from a list of local distributions.
|
||||||
|
pub(crate) fn from_local(installed: Vec<CachedDist>, uninstalled: Vec<InstalledDist>) -> Self {
|
||||||
|
Self::new(
|
||||||
|
installed
|
||||||
|
.into_iter()
|
||||||
|
.map(|dist| ChangedDist::Local(dist.into())),
|
||||||
|
uninstalled
|
||||||
|
.into_iter()
|
||||||
|
.map(|dist| ChangedDist::Local(dist.into())),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a [`Changelog`] from a list of installed distributions.
|
/// Create a [`Changelog`] from a list of installed distributions.
|
||||||
pub(crate) fn from_installed(installed: Vec<CachedDist>) -> Self {
|
pub(crate) fn from_installed(installed: Vec<CachedDist>) -> Self {
|
||||||
Self {
|
Self::from_local(installed, Vec::new())
|
||||||
installed: installed.into_iter().map(LocalDist::from).collect(),
|
|
||||||
uninstalled: HashSet::default(),
|
|
||||||
reinstalled: HashSet::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the changelog includes a distribution with the given name, either via
|
/// Returns `true` if the changelog includes a distribution with the given name, either via
|
||||||
|
|
@ -485,8 +569,15 @@ pub(crate) async fn install(
|
||||||
.context("Failed to determine installation plan")?;
|
.context("Failed to determine installation plan")?;
|
||||||
|
|
||||||
if dry_run.enabled() {
|
if dry_run.enabled() {
|
||||||
report_dry_run(dry_run, resolution, plan, modifications, start, printer)?;
|
return report_dry_run(
|
||||||
return Ok(Changelog::default());
|
dry_run,
|
||||||
|
resolution,
|
||||||
|
plan,
|
||||||
|
modifications,
|
||||||
|
start,
|
||||||
|
logger.as_ref(),
|
||||||
|
printer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Plan {
|
let Plan {
|
||||||
|
|
@ -509,7 +600,7 @@ pub(crate) async fn install(
|
||||||
&& extraneous.is_empty()
|
&& extraneous.is_empty()
|
||||||
&& !compile
|
&& !compile
|
||||||
{
|
{
|
||||||
logger.on_audit(resolution.len(), start, printer)?;
|
logger.on_audit(resolution.len(), start, printer, dry_run)?;
|
||||||
return Ok(Changelog::default());
|
return Ok(Changelog::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -590,10 +681,10 @@ pub(crate) async fn install(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a summary of the changes made to the environment.
|
// Construct a summary of the changes made to the environment.
|
||||||
let changelog = Changelog::new(installs, uninstalls);
|
let changelog = Changelog::from_local(installs, uninstalls);
|
||||||
|
|
||||||
// Notify the user of any environment modifications.
|
// Notify the user of any environment modifications.
|
||||||
logger.on_complete(&changelog, printer)?;
|
logger.on_complete(&changelog, printer, dry_run)?;
|
||||||
|
|
||||||
Ok(changelog)
|
Ok(changelog)
|
||||||
}
|
}
|
||||||
|
|
@ -660,7 +751,13 @@ async fn execute_plan(
|
||||||
.prepare(remote.clone(), in_flight, resolution)
|
.prepare(remote.clone(), in_flight, resolution)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
logger.on_prepare(wheels.len(), phase.map(InstallPhase::label), start, printer)?;
|
logger.on_prepare(
|
||||||
|
wheels.len(),
|
||||||
|
phase.map(InstallPhase::label),
|
||||||
|
start,
|
||||||
|
printer,
|
||||||
|
DryRun::Disabled,
|
||||||
|
)?;
|
||||||
|
|
||||||
wheels
|
wheels
|
||||||
};
|
};
|
||||||
|
|
@ -702,7 +799,7 @@ async fn execute_plan(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.on_uninstall(uninstalls.len(), start, printer)?;
|
logger.on_uninstall(uninstalls.len(), start, printer, DryRun::Disabled)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the resolved distributions.
|
// Install the resolved distributions.
|
||||||
|
|
@ -721,7 +818,7 @@ async fn execute_plan(
|
||||||
// task.
|
// task.
|
||||||
.install_blocking(installs)?;
|
.install_blocking(installs)?;
|
||||||
|
|
||||||
logger.on_install(installs.len(), start, printer)?;
|
logger.on_install(installs.len(), start, printer, DryRun::Disabled)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((installs, uninstalls))
|
Ok((installs, uninstalls))
|
||||||
|
|
@ -840,8 +937,9 @@ fn report_dry_run(
|
||||||
plan: Plan,
|
plan: Plan,
|
||||||
modifications: Modifications,
|
modifications: Modifications,
|
||||||
start: std::time::Instant,
|
start: std::time::Instant,
|
||||||
|
logger: &dyn InstallLogger,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<(), Error> {
|
) -> Result<Changelog, Error> {
|
||||||
let Plan {
|
let Plan {
|
||||||
cached,
|
cached,
|
||||||
remote,
|
remote,
|
||||||
|
|
@ -857,25 +955,15 @@ fn report_dry_run(
|
||||||
|
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
if remote.is_empty() && cached.is_empty() && reinstalls.is_empty() && extraneous.is_empty() {
|
if remote.is_empty() && cached.is_empty() && reinstalls.is_empty() && extraneous.is_empty() {
|
||||||
DefaultInstallLogger.on_audit(resolution.len(), start, printer)?;
|
logger.on_audit(resolution.len(), start, printer, dry_run)?;
|
||||||
writeln!(printer.stderr(), "Would make no changes")?;
|
return Ok(Changelog::default());
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download, build, and unzip any missing distributions.
|
// Download, build, and unzip any missing distributions.
|
||||||
let wheels = if remote.is_empty() {
|
let wheels = if remote.is_empty() {
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
let s = if remote.len() == 1 { "" } else { "s" };
|
logger.on_prepare(remote.len(), None, start, printer, dry_run)?;
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format!(
|
|
||||||
"Would download {}",
|
|
||||||
format!("{} package{}", remote.len(), s).bold(),
|
|
||||||
)
|
|
||||||
.dimmed()
|
|
||||||
)?;
|
|
||||||
remote.clone()
|
remote.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -883,87 +971,35 @@ fn report_dry_run(
|
||||||
let uninstalls = extraneous.len() + reinstalls.len();
|
let uninstalls = extraneous.len() + reinstalls.len();
|
||||||
|
|
||||||
if uninstalls > 0 {
|
if uninstalls > 0 {
|
||||||
let s = if uninstalls == 1 { "" } else { "s" };
|
logger.on_uninstall(uninstalls, start, printer, dry_run)?;
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format!(
|
|
||||||
"Would uninstall {}",
|
|
||||||
format!("{uninstalls} package{s}").bold(),
|
|
||||||
)
|
|
||||||
.dimmed()
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the resolved distributions.
|
// Install the resolved distributions.
|
||||||
let installs = wheels.len() + cached.len();
|
let installs = wheels.len() + cached.len();
|
||||||
|
|
||||||
if installs > 0 {
|
if installs > 0 {
|
||||||
let s = if installs == 1 { "" } else { "s" };
|
logger.on_install(installs, start, printer, dry_run)?;
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
"{}",
|
|
||||||
format!("Would install {}", format!("{installs} package{s}").bold()).dimmed()
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(charlie): DRY this up with `report_modifications`. The types don't quite line up.
|
let uninstalled = reinstalls
|
||||||
for event in reinstalls
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(extraneous.into_iter())
|
.chain(extraneous)
|
||||||
.map(|distribution| DryRunEvent {
|
.map(|dist| ChangedDist::Local(dist.into()));
|
||||||
name: distribution.name().clone(),
|
let installed = wheels.into_iter().map(ChangedDist::Remote).chain(
|
||||||
version: distribution.installed_version().to_string(),
|
cached
|
||||||
kind: ChangeEventKind::Removed,
|
.into_iter()
|
||||||
})
|
.map(|dist| ChangedDist::Local(dist.into())),
|
||||||
.chain(wheels.into_iter().map(|distribution| DryRunEvent {
|
);
|
||||||
name: distribution.name().clone(),
|
|
||||||
version: distribution.version_or_url().to_string(),
|
let changelog = Changelog::new(installed, uninstalled);
|
||||||
kind: ChangeEventKind::Added,
|
|
||||||
}))
|
logger.on_complete(&changelog, printer, dry_run)?;
|
||||||
.chain(cached.into_iter().map(|distribution| DryRunEvent {
|
|
||||||
name: distribution.name().clone(),
|
|
||||||
version: distribution.installed_version().to_string(),
|
|
||||||
kind: ChangeEventKind::Added,
|
|
||||||
}))
|
|
||||||
.sorted_unstable_by(|a, b| a.name.cmp(&b.name).then_with(|| a.kind.cmp(&b.kind)))
|
|
||||||
{
|
|
||||||
match event.kind {
|
|
||||||
ChangeEventKind::Added => {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
" {} {}{}",
|
|
||||||
"+".green(),
|
|
||||||
event.name.bold(),
|
|
||||||
event.version.dimmed()
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
ChangeEventKind::Removed => {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
" {} {}{}",
|
|
||||||
"-".red(),
|
|
||||||
event.name.bold(),
|
|
||||||
event.version.dimmed()
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
ChangeEventKind::Reinstalled => {
|
|
||||||
writeln!(
|
|
||||||
printer.stderr(),
|
|
||||||
" {} {}{}",
|
|
||||||
"~".yellow(),
|
|
||||||
event.name.bold(),
|
|
||||||
event.version.dimmed()
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches!(dry_run, DryRun::Check) {
|
if matches!(dry_run, DryRun::Check) {
|
||||||
return Err(Error::OutdatedEnvironment);
|
return Err(Error::OutdatedEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(changelog)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Report any diagnostics on resolved distributions.
|
/// Report any diagnostics on resolved distributions.
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ use thiserror::Error;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
use uv_client::{BaseClientBuilder, FlatIndexClient, RegistryClientBuilder};
|
||||||
use uv_configuration::{
|
use uv_configuration::{
|
||||||
BuildOptions, Concurrency, Constraints, DependencyGroups, IndexStrategy, KeyringProviderType,
|
BuildOptions, Concurrency, Constraints, DependencyGroups, DryRun, IndexStrategy,
|
||||||
NoBinary, NoBuild, SourceStrategy,
|
KeyringProviderType, NoBinary, NoBuild, SourceStrategy,
|
||||||
};
|
};
|
||||||
use uv_dispatch::{BuildDispatch, SharedState};
|
use uv_dispatch::{BuildDispatch, SharedState};
|
||||||
use uv_distribution_types::{
|
use uv_distribution_types::{
|
||||||
|
|
@ -310,7 +310,7 @@ pub(crate) async fn venv(
|
||||||
.map_err(|err| VenvError::Seed(err.into()))?;
|
.map_err(|err| VenvError::Seed(err.into()))?;
|
||||||
|
|
||||||
let changelog = Changelog::from_installed(installed);
|
let changelog = Changelog::from_installed(installed);
|
||||||
DefaultInstallLogger.on_complete(&changelog, printer)?;
|
DefaultInstallLogger.on_complete(&changelog, printer, DryRun::Disabled)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the appropriate activation command.
|
// Determine the appropriate activation command.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue