diff --git a/crates/uv/src/commands/tool/common.rs b/crates/uv/src/commands/tool/common.rs index 166b4fc6f..ffc1b5645 100644 --- a/crates/uv/src/commands/tool/common.rs +++ b/crates/uv/src/commands/tool/common.rs @@ -218,7 +218,7 @@ pub(crate) fn finalize_tool_install( if target_entry_points.is_empty() { writeln!( printer.stdout(), - "No executables are provided by `{from}`", + "No executables are provided by package `{from}`; removing tool", from = name.cyan() )?; @@ -354,7 +354,9 @@ fn hint_executable_from_dependency( let command = format!("uv tool install {}", package.name()); writeln!( printer.stdout(), - "However, an executable with the name `{}` is available via dependency `{}`.\nDid you mean `{}`?", + "{}{} An executable with the name `{}` is available via dependency `{}`.\n Did you mean `{}`?", + "hint".bold().cyan(), + ":".bold(), name.cyan(), package.name().cyan(), command.bold(), @@ -363,7 +365,9 @@ fn hint_executable_from_dependency( packages => { writeln!( printer.stdout(), - "However, an executable with the name `{}` is available via the following dependencies::", + "{}{} An executable with the name `{}` is available via the following dependencies::", + "hint".bold().cyan(), + ":".bold(), name.cyan(), )?; @@ -372,7 +376,7 @@ fn hint_executable_from_dependency( } writeln!( printer.stdout(), - "Did you mean to install one of them instead?" + " Did you mean to install one of them instead?" )?; } } diff --git a/crates/uv/tests/it/tool_install.rs b/crates/uv/tests/it/tool_install.rs index 0da627552..deb935f9b 100644 --- a/crates/uv/tests/it/tool_install.rs +++ b/crates/uv/tests/it/tool_install.rs @@ -448,13 +448,13 @@ fn tool_install_suggest_other_packages_with_executable() { uv_snapshot!(filters, context.tool_install() .arg("fastapi==0.111.0") .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: false exit_code: 1 ----- stdout ----- - No executables are provided by `fastapi` - However, an executable with the name `fastapi` is available via dependency `fastapi-cli`. - Did you mean `uv tool install fastapi-cli`? + No executables are provided by package `fastapi`; removing tool + hint: An executable with the name `fastapi` is available via dependency `fastapi-cli`. + Did you mean `uv tool install fastapi-cli`? ----- stderr ----- Resolved 35 packages in [TIME] @@ -494,7 +494,7 @@ fn tool_install_suggest_other_packages_with_executable() { + uvicorn==0.29.0 + watchfiles==0.21.0 + websockets==12.0 - "###); + "); } /// Test installing a tool at a version @@ -821,11 +821,11 @@ fn tool_install_remove_on_empty() -> Result<()> { .arg(black.path()) .env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str()) .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()) - .env(EnvVars::PATH, bin_dir.as_os_str()), @r###" + .env(EnvVars::PATH, bin_dir.as_os_str()), @r" success: false exit_code: 1 ----- stdout ----- - No executables are provided by `black` + No executables are provided by package `black`; removing tool ----- stderr ----- Resolved 1 package in [TIME] @@ -839,7 +839,7 @@ fn tool_install_remove_on_empty() -> Result<()> { - packaging==24.0 - pathspec==0.12.1 - platformdirs==4.2.0 - "###); + "); // Re-request `black`. It should reinstall, without requiring `--force`. uv_snapshot!(context.filters(), context.tool_install() @@ -1649,18 +1649,18 @@ fn tool_install_no_entrypoints() { .arg("iniconfig") .env(EnvVars::UV_TOOL_DIR, tool_dir.as_os_str()) .env(EnvVars::XDG_BIN_HOME, bin_dir.as_os_str()) - .env(EnvVars::PATH, bin_dir.as_os_str()), @r###" + .env(EnvVars::PATH, bin_dir.as_os_str()), @r" success: false exit_code: 1 ----- stdout ----- - No executables are provided by `iniconfig` + No executables are provided by package `iniconfig`; removing tool ----- stderr ----- Resolved 1 package in [TIME] Prepared 1 package in [TIME] Installed 1 package in [TIME] + iniconfig==2.0.0 - "###); + "); // Ensure the tool environment is not created. tool_dir