Add uv tool dir --bin to show executable directory (#5160)

## Summary

Closes https://github.com/astral-sh/uv/issues/5159.
This commit is contained in:
Charlie Marsh
2024-07-17 16:30:45 -04:00
committed by GitHub
parent e271d1fdde
commit eb24717a9b
5 changed files with 68 additions and 10 deletions
+12 -1
View File
@@ -2067,7 +2067,7 @@ pub enum ToolCommand {
#[command(alias = "ensurepath")]
UpdateShell,
/// Show the tools directory.
Dir,
Dir(ToolDirArgs),
}
#[derive(Args)]
@@ -2168,6 +2168,17 @@ pub struct ToolInstallArgs {
#[allow(clippy::struct_excessive_bools)]
pub struct ToolListArgs;
#[derive(Args)]
#[allow(clippy::struct_excessive_bools)]
pub struct ToolDirArgs {
/// Show the directory into which `uv tool` will install executables.
///
/// By default, `uv tool dir` shows the directory into which the tool Python environments
/// themselves are installed, rather than the directory containing the linked executables.
#[arg(long, alias = "executable")]
pub bin: bool,
}
#[derive(Args)]
#[allow(clippy::struct_excessive_bools)]
pub struct ToolUninstallArgs {
+12 -5
View File
@@ -3,16 +3,23 @@ use owo_colors::OwoColorize;
use uv_configuration::PreviewMode;
use uv_fs::Simplified;
use uv_tool::InstalledTools;
use uv_tool::{find_executable_directory, InstalledTools};
use uv_warnings::warn_user_once;
/// Show the tool directory.
pub(crate) fn dir(preview: PreviewMode) -> anyhow::Result<()> {
pub(crate) fn dir(bin: bool, preview: PreviewMode) -> anyhow::Result<()> {
if preview.is_disabled() {
warn_user_once!("`uv tool dir` is experimental and may change without warning.");
}
let installed_tools =
InstalledTools::from_settings().context("Failed to initialize tools settings")?;
anstream::println!("{}", installed_tools.root().simplified_display().cyan());
if bin {
let executable_directory = find_executable_directory()?;
anstream::println!("{}", executable_directory.simplified_display().cyan());
} else {
let installed_tools =
InstalledTools::from_settings().context("Failed to initialize tools settings")?;
anstream::println!("{}", installed_tools.root().simplified_display().cyan());
}
Ok(())
}
+6 -2
View File
@@ -689,9 +689,13 @@ async fn run(cli: Cli) -> Result<ExitStatus> {
Ok(ExitStatus::Success)
}
Commands::Tool(ToolNamespace {
command: ToolCommand::Dir,
command: ToolCommand::Dir(args),
}) => {
commands::tool_dir(globals.preview)?;
// Resolve the settings from the command-line arguments and workspace configuration.
let args = settings::ToolDirSettings::resolve(args, filesystem);
show_settings!(args);
commands::tool_dir(args.bin, globals.preview)?;
Ok(ExitStatus::Success)
}
Commands::Python(PythonNamespace {
+19 -2
View File
@@ -14,8 +14,8 @@ use uv_cli::{
AddArgs, ColorChoice, Commands, ExternalCommand, GlobalArgs, ListFormat, LockArgs, Maybe,
PipCheckArgs, PipCompileArgs, PipFreezeArgs, PipInstallArgs, PipListArgs, PipShowArgs,
PipSyncArgs, PipTreeArgs, PipUninstallArgs, PythonFindArgs, PythonInstallArgs, PythonListArgs,
PythonPinArgs, PythonUninstallArgs, RemoveArgs, RunArgs, SyncArgs, ToolInstallArgs,
ToolListArgs, ToolRunArgs, ToolUninstallArgs, TreeArgs, VenvArgs,
PythonPinArgs, PythonUninstallArgs, RemoveArgs, RunArgs, SyncArgs, ToolDirArgs,
ToolInstallArgs, ToolListArgs, ToolRunArgs, ToolUninstallArgs, TreeArgs, VenvArgs,
};
use uv_client::Connectivity;
use uv_configuration::{
@@ -316,6 +316,23 @@ impl ToolUninstallSettings {
}
}
/// The resolved settings to use for a `tool dir` invocation.
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Clone)]
pub(crate) struct ToolDirSettings {
pub(crate) bin: bool,
}
impl ToolDirSettings {
/// Resolve the [`ToolDirSettings`] from the CLI and filesystem configuration.
#[allow(clippy::needless_pass_by_value)]
pub(crate) fn resolve(args: ToolDirArgs, _filesystem: Option<FilesystemOptions>) -> Self {
let ToolDirArgs { bin } = args;
Self { bin }
}
}
#[derive(Debug, Clone, Default)]
pub(crate) enum PythonListKinds {
#[default]
+19
View File
@@ -24,3 +24,22 @@ fn tool_dir() {
warning: `uv tool dir` is experimental and may change without warning.
"###);
}
#[test]
fn tool_dir_bin() {
let context = TestContext::new("3.12");
let tool_dir = context.temp_dir.child("tools");
let bin_dir = context.temp_dir.child("bin");
uv_snapshot!(context.filters(), context.tool_dir().arg("--bin")
.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 -----
[TEMP_DIR]/bin
----- stderr -----
warning: `uv tool dir` is experimental and may change without warning.
"###);
}