mirror of
https://github.com/astral-sh/uv.git
synced 2025-10-17 13:58:29 +00:00
Colocate Python install cache with destination directory (#6043)
## Summary Closes https://github.com/astral-sh/uv/issues/6036.
This commit is contained in:
parent
e27a1fce60
commit
ae7a8d7f33
5 changed files with 27 additions and 19 deletions
|
@ -14,7 +14,6 @@ use tokio::io::{AsyncRead, ReadBuf};
|
||||||
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
use tokio_util::compat::FuturesAsyncReadCompatExt;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use uv_cache::Cache;
|
|
||||||
use uv_client::WrappedReqwestError;
|
use uv_client::WrappedReqwestError;
|
||||||
use uv_extract::hash::Hasher;
|
use uv_extract::hash::Hasher;
|
||||||
use uv_fs::{rename_with_retry, Simplified};
|
use uv_fs::{rename_with_retry, Simplified};
|
||||||
|
@ -408,16 +407,16 @@ impl ManagedPythonDownload {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download and extract
|
/// Download and extract
|
||||||
#[instrument(skip(client, parent_path, cache, reporter), fields(download = % self.key()))]
|
#[instrument(skip(client, installation_dir, cache_dir, reporter), fields(download = % self.key()))]
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
&self,
|
&self,
|
||||||
client: &uv_client::BaseClient,
|
client: &uv_client::BaseClient,
|
||||||
parent_path: &Path,
|
installation_dir: &Path,
|
||||||
cache: &Cache,
|
cache_dir: &Path,
|
||||||
reporter: Option<&dyn Reporter>,
|
reporter: Option<&dyn Reporter>,
|
||||||
) -> Result<DownloadResult, Error> {
|
) -> Result<DownloadResult, Error> {
|
||||||
let url = self.download_url()?;
|
let url = self.download_url()?;
|
||||||
let path = parent_path.join(self.key().to_string());
|
let path = installation_dir.join(self.key().to_string());
|
||||||
|
|
||||||
// If it already exists, return it
|
// If it already exists, return it
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
|
@ -438,7 +437,7 @@ impl ManagedPythonDownload {
|
||||||
.map(|reporter| (reporter, reporter.on_download_start(&self.key, size)));
|
.map(|reporter| (reporter, reporter.on_download_start(&self.key, size)));
|
||||||
|
|
||||||
// Download and extract into a temporary directory.
|
// Download and extract into a temporary directory.
|
||||||
let temp_dir = tempfile::tempdir_in(cache.root()).map_err(Error::DownloadDirError)?;
|
let temp_dir = tempfile::tempdir_in(cache_dir).map_err(Error::DownloadDirError)?;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Downloading {url} to temporary location: {}",
|
"Downloading {url} to temporary location: {}",
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use pep440_rs::Version;
|
|
||||||
use tracing::{debug, info};
|
use tracing::{debug, info};
|
||||||
use uv_client::BaseClientBuilder;
|
|
||||||
|
|
||||||
|
use pep440_rs::Version;
|
||||||
use uv_cache::Cache;
|
use uv_cache::Cache;
|
||||||
|
use uv_client::BaseClientBuilder;
|
||||||
|
|
||||||
use crate::discovery::{
|
use crate::discovery::{
|
||||||
find_best_python_installation, find_python_installation, EnvironmentPreference, PythonRequest,
|
find_best_python_installation, find_python_installation, EnvironmentPreference, PythonRequest,
|
||||||
|
@ -123,6 +123,7 @@ impl PythonInstallation {
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
||||||
let installations_dir = installations.root();
|
let installations_dir = installations.root();
|
||||||
|
let cache_dir = installations.cache();
|
||||||
let _lock = installations.acquire_lock()?;
|
let _lock = installations.acquire_lock()?;
|
||||||
|
|
||||||
let download = ManagedPythonDownload::from_request(&request)?;
|
let download = ManagedPythonDownload::from_request(&request)?;
|
||||||
|
@ -130,7 +131,7 @@ impl PythonInstallation {
|
||||||
|
|
||||||
info!("Fetching requested Python...");
|
info!("Fetching requested Python...");
|
||||||
let result = download
|
let result = download
|
||||||
.fetch(&client, installations_dir, cache, reporter)
|
.fetch(&client, installations_dir, &cache_dir, reporter)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let path = match result {
|
let path = match result {
|
||||||
|
|
|
@ -95,6 +95,11 @@ impl ManagedPythonInstallations {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the location of the cache directory for managed Python installations.
|
||||||
|
pub fn cache(&self) -> PathBuf {
|
||||||
|
self.root.join(".cache")
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the Python installation directory.
|
/// Initialize the Python installation directory.
|
||||||
///
|
///
|
||||||
/// Ensures the directory is created.
|
/// Ensures the directory is created.
|
||||||
|
@ -119,6 +124,10 @@ impl ManagedPythonInstallations {
|
||||||
// Create the directory, if it doesn't exist.
|
// Create the directory, if it doesn't exist.
|
||||||
fs::create_dir_all(root)?;
|
fs::create_dir_all(root)?;
|
||||||
|
|
||||||
|
// Create the cache directory, if it doesn't exist.
|
||||||
|
let cache = self.cache();
|
||||||
|
fs::create_dir_all(&cache)?;
|
||||||
|
|
||||||
// Add a .gitignore.
|
// Add a .gitignore.
|
||||||
match fs::OpenOptions::new()
|
match fs::OpenOptions::new()
|
||||||
.write(true)
|
.write(true)
|
||||||
|
@ -166,8 +175,10 @@ impl ManagedPythonInstallations {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let cache = self.cache();
|
||||||
Ok(dirs
|
Ok(dirs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.filter(|path| *path != cache)
|
||||||
.filter_map(|path| {
|
.filter_map(|path| {
|
||||||
ManagedPythonInstallation::new(path)
|
ManagedPythonInstallation::new(path)
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
use std::fmt::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use fs_err as fs;
|
use fs_err as fs;
|
||||||
use futures::stream::FuturesUnordered;
|
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 std::collections::BTreeSet;
|
|
||||||
use std::fmt::Write;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use uv_cache::Cache;
|
|
||||||
use uv_client::Connectivity;
|
use uv_client::Connectivity;
|
||||||
use uv_configuration::PreviewMode;
|
use uv_configuration::PreviewMode;
|
||||||
use uv_fs::CWD;
|
use uv_fs::CWD;
|
||||||
|
@ -34,7 +35,6 @@ pub(crate) async fn install(
|
||||||
connectivity: Connectivity,
|
connectivity: Connectivity,
|
||||||
preview: PreviewMode,
|
preview: PreviewMode,
|
||||||
no_config: bool,
|
no_config: bool,
|
||||||
cache: &Cache,
|
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
if preview.is_disabled() {
|
if preview.is_disabled() {
|
||||||
|
@ -45,6 +45,7 @@ pub(crate) async fn install(
|
||||||
|
|
||||||
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
let installations = ManagedPythonInstallations::from_settings()?.init()?;
|
||||||
let installations_dir = installations.root();
|
let installations_dir = installations.root();
|
||||||
|
let cache_dir = installations.cache();
|
||||||
let _lock = installations.acquire_lock()?;
|
let _lock = installations.acquire_lock()?;
|
||||||
|
|
||||||
let targets = targets.into_iter().collect::<BTreeSet<_>>();
|
let targets = targets.into_iter().collect::<BTreeSet<_>>();
|
||||||
|
@ -161,7 +162,7 @@ pub(crate) async fn install(
|
||||||
(
|
(
|
||||||
download.key(),
|
download.key(),
|
||||||
download
|
download
|
||||||
.fetch(&client, installations_dir, cache, Some(&reporter))
|
.fetch(&client, installations_dir, &cache_dir, Some(&reporter))
|
||||||
.await,
|
.await,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
|
@ -910,9 +910,6 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
||||||
let args = settings::PythonInstallSettings::resolve(args, filesystem);
|
let args = settings::PythonInstallSettings::resolve(args, filesystem);
|
||||||
show_settings!(args);
|
show_settings!(args);
|
||||||
|
|
||||||
// Initialize the cache.
|
|
||||||
let cache = cache.init()?;
|
|
||||||
|
|
||||||
commands::python_install(
|
commands::python_install(
|
||||||
args.targets,
|
args.targets,
|
||||||
args.reinstall,
|
args.reinstall,
|
||||||
|
@ -921,7 +918,6 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
|
||||||
globals.connectivity,
|
globals.connectivity,
|
||||||
globals.preview,
|
globals.preview,
|
||||||
cli.no_config,
|
cli.no_config,
|
||||||
&cache,
|
|
||||||
printer,
|
printer,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue