From 312084f2ddfe44168f84902444e28c833b38af96 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 14 Sep 2025 09:10:46 -0400 Subject: [PATCH] Allow cached environment reuse with `@latest` (#15827) ## Summary I think this is leftover from a prior refactor whereby we used to avoid reusing the cached environment if `--reinstall` was passed; but then we stopped allowing `--reinstall` in `uv tool run` anyway, and this got changed to `--refresh`. It seems wrong to skip cache reuse with `--refresh`, though. Closes https://github.com/astral-sh/uv/issues/15824. --- crates/uv/src/commands/project/environment.rs | 8 ++---- crates/uv/src/settings.rs | 4 +-- crates/uv/tests/it/tool_run.rs | 28 ++++--------------- 3 files changed, 11 insertions(+), 29 deletions(-) diff --git a/crates/uv/src/commands/project/environment.rs b/crates/uv/src/commands/project/environment.rs index 97da0f730..cfef02018 100644 --- a/crates/uv/src/commands/project/environment.rs +++ b/crates/uv/src/commands/project/environment.rs @@ -174,11 +174,9 @@ impl CachedEnvironment { // Search in the content-addressed cache. let cache_entry = cache.entry(CacheBucket::Environments, interpreter_hash, resolution_hash); - if cache.refresh().is_none() { - if let Ok(root) = cache.resolve_link(cache_entry.path()) { - if let Ok(environment) = PythonEnvironment::from_root(root, cache) { - return Ok(Self(environment)); - } + if let Ok(root) = cache.resolve_link(cache_entry.path()) { + if let Ok(environment) = PythonEnvironment::from_root(root, cache) { + return Ok(Self(environment)); } } diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index 9c1ab8f07..607c3ccb2 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -536,11 +536,11 @@ impl ToolRunSettings { if installer.reinstall || !installer.reinstall_package.is_empty() { if with.is_empty() && with_requirements.is_empty() { warn_user_once!( - "Tools cannot be reinstalled via `{invocation_source}`; use `uv tool upgrade --all --reinstall` to reinstall all installed tools, or `{invocation_source} package@latest` to run the latest version of a tool." + "Tools cannot be reinstalled via `{invocation_source}`; use `uv tool upgrade --all --reinstall` to reinstall all installed tools, `{invocation_source} package@latest` to run the latest version of a tool, or `uv cache prune` to clear any cached tool environments." ); } else { warn_user_once!( - "Tools cannot be reinstalled via `{invocation_source}`; use `uv tool upgrade --all --reinstall` to reinstall all installed tools, `{invocation_source} package@latest` to run the latest version of a tool, or `{invocation_source} --refresh package` to reinstall any `--with` dependencies." + "Tools cannot be reinstalled via `{invocation_source}`; use `uv tool upgrade --all --reinstall` to reinstall all installed tools, `{invocation_source} package@latest` to run the latest version of a tool, `{invocation_source} --refresh package` to reinstall any `--with` dependencies, or `uv cache prune` to clear any cached tool environments." ); } } diff --git a/crates/uv/tests/it/tool_run.rs b/crates/uv/tests/it/tool_run.rs index 1dd90e633..07396b596 100644 --- a/crates/uv/tests/it/tool_run.rs +++ b/crates/uv/tests/it/tool_run.rs @@ -734,7 +734,7 @@ fn tool_run_cache() { Resolved [N] packages in [TIME] "###); - // Verify that `--refresh` recreates everything. + // Verify that `--refresh` allows cache reuse. uv_snapshot!(context.filters(), context.tool_run() .arg("-p") .arg("3.12") @@ -742,7 +742,7 @@ fn tool_run_cache() { .arg("black") .arg("--version") .env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str()) - .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r###" + .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r" success: true exit_code: 0 ----- stdout ----- @@ -751,17 +751,9 @@ fn tool_run_cache() { ----- stderr ----- Resolved [N] packages in [TIME] - Prepared [N] packages in [TIME] - Installed [N] packages in [TIME] - + black==24.3.0 - + click==8.1.7 - + mypy-extensions==1.0.0 - + packaging==24.0 - + pathspec==0.12.1 - + platformdirs==4.2.0 - "###); + "); - // Verify that `--refresh-package` recreates everything. We may want to change this. + // Verify that `--refresh-package` allows cache reuse. uv_snapshot!(context.filters(), context.tool_run() .arg("-p") .arg("3.12") @@ -770,7 +762,7 @@ fn tool_run_cache() { .arg("black") .arg("--version") .env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str()) - .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r###" + .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()), @r" success: true exit_code: 0 ----- stdout ----- @@ -779,15 +771,7 @@ fn tool_run_cache() { ----- stderr ----- Resolved [N] packages in [TIME] - Prepared [N] packages in [TIME] - Installed [N] packages in [TIME] - + black==24.3.0 - + click==8.1.7 - + mypy-extensions==1.0.0 - + packaging==24.0 - + pathspec==0.12.1 - + platformdirs==4.2.0 - "###); + "); // Verify that varying the interpreter leads to a fresh environment. uv_snapshot!(context.filters(), context.tool_run()