List installed tools when no command is provided to uv tool run (#5553)

## Summary

Part of #4024 

## Test Plan

Test cases included.
This commit is contained in:
eth3lbert 2024-07-30 06:12:31 +08:00 committed by GitHub
parent ecb85c9894
commit 3e329029bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 56 additions and 4 deletions

View file

@ -2264,8 +2264,10 @@ pub struct ToolRunArgs {
/// ///
/// If more complex version specification is desired or if the command is provided by a different /// If more complex version specification is desired or if the command is provided by a different
/// package, use `--from`. /// package, use `--from`.
///
/// If omitted, lists the available tools.
#[command(subcommand)] #[command(subcommand)]
pub command: ExternalCommand, pub command: Option<ExternalCommand>,
/// Use the given package to provide the command. /// Use the given package to provide the command.
/// ///

View file

@ -31,7 +31,7 @@ use crate::commands::reporters::PythonDownloadReporter;
use crate::commands::project::resolve_names; use crate::commands::project::resolve_names;
use crate::commands::{ use crate::commands::{
project, project::environment::CachedEnvironment, tool::common::matching_packages, project, project::environment::CachedEnvironment, tool::common::matching_packages, tool_list,
}; };
use crate::commands::{ExitStatus, SharedState}; use crate::commands::{ExitStatus, SharedState};
use crate::printer::Printer; use crate::printer::Printer;
@ -56,7 +56,7 @@ impl Display for ToolRunCommand {
/// Run a command. /// Run a command.
pub(crate) async fn run( pub(crate) async fn run(
command: ExternalCommand, command: Option<ExternalCommand>,
from: Option<String>, from: Option<String>,
with: &[RequirementsSource], with: &[RequirementsSource],
python: Option<String>, python: Option<String>,
@ -76,6 +76,11 @@ pub(crate) async fn run(
warn_user_once!("`{invocation_source}` is experimental and may change without warning"); warn_user_once!("`{invocation_source}` is experimental and may change without warning");
} }
// treat empty command as `uv tool list`
let Some(command) = command else {
return tool_list(false, PreviewMode::Enabled, cache, printer).await;
};
let (target, args) = command.split(); let (target, args) = command.split();
let Some(target) = target else { let Some(target) = target else {
return Err(anyhow::anyhow!("No tool command provided")); return Err(anyhow::anyhow!("No tool command provided"));

View file

@ -251,7 +251,7 @@ impl RunSettings {
#[allow(clippy::struct_excessive_bools)] #[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct ToolRunSettings { pub(crate) struct ToolRunSettings {
pub(crate) command: ExternalCommand, pub(crate) command: Option<ExternalCommand>,
pub(crate) from: Option<String>, pub(crate) from: Option<String>,
pub(crate) with: Vec<String>, pub(crate) with: Vec<String>,
pub(crate) with_requirements: Vec<PathBuf>, pub(crate) with_requirements: Vec<PathBuf>,

View file

@ -766,3 +766,48 @@ fn tool_run_requirements_txt_arguments() {
+ werkzeug==3.0.1 + werkzeug==3.0.1
"###); "###);
} }
/// List installed tools when no command arg is given (e.g. `uv tool run`).
#[test]
fn tool_run_list_installed() {
let context = TestContext::new("3.12").with_filtered_exe_suffix();
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");
// No tools installed.
uv_snapshot!(context.filters(), context.tool_run()
.env("UV_TOOL_DIR", tool_dir.as_os_str())
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
warning: `uv tool run` is experimental and may change without warning
No tools installed
"###);
// Install `black`.
context
.tool_install()
.arg("black==24.2.0")
.env("UV_TOOL_DIR", tool_dir.as_os_str())
.env("XDG_BIN_HOME", bin_dir.as_os_str())
.assert()
.success();
// List installed tools.
uv_snapshot!(context.filters(), context.tool_run()
.env("UV_TOOL_DIR", tool_dir.as_os_str())
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
success: true
exit_code: 0
----- stdout -----
black v24.2.0
- black
- blackd
----- stderr -----
warning: `uv tool run` is experimental and may change without warning
"###);
}