mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Warn if tool binary directory is not on path (#4951)
## Summary Closes https://github.com/astral-sh/uv/issues/4671. ## Test Plan ``` ❯ XDG_BIN_HOME="/Users/crmarsh/workspace/uv/foo bar" cargo run tool install black --force Installed 2 executables: black, blackd warning: `/Users/crmarsh/workspace/uv/foo bar` is not on your PATH. To use installed tools, run: export PATH="/Users/crmarsh/workspace/uv/foo bar:$PATH" ```
This commit is contained in:
parent
3d1ab81c28
commit
1fcc3c4797
5 changed files with 189 additions and 38 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -4475,6 +4475,7 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
|
"same-file",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"textwrap",
|
"textwrap",
|
||||||
|
|
|
@ -50,14 +50,15 @@ clap = { workspace = true, features = ["derive", "string", "wrap_help"] }
|
||||||
flate2 = { workspace = true, default-features = false }
|
flate2 = { workspace = true, default-features = false }
|
||||||
fs-err = { workspace = true, features = ["tokio"] }
|
fs-err = { workspace = true, features = ["tokio"] }
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
indicatif = { workspace = true }
|
|
||||||
indexmap = { workspace = true }
|
indexmap = { workspace = true }
|
||||||
|
indicatif = { workspace = true }
|
||||||
itertools = { workspace = true }
|
itertools = { workspace = true }
|
||||||
miette = { workspace = true, features = ["fancy"] }
|
miette = { workspace = true, features = ["fancy"] }
|
||||||
owo-colors = { workspace = true }
|
owo-colors = { workspace = true }
|
||||||
rayon = { workspace = true }
|
rayon = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
|
same-file = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
textwrap = { workspace = true }
|
textwrap = { workspace = true }
|
||||||
|
|
|
@ -23,7 +23,7 @@ use uv_python::{
|
||||||
};
|
};
|
||||||
use uv_requirements::RequirementsSpecification;
|
use uv_requirements::RequirementsSpecification;
|
||||||
use uv_tool::{entrypoint_paths, find_executable_directory, InstalledTools, Tool, ToolEntrypoint};
|
use uv_tool::{entrypoint_paths, find_executable_directory, InstalledTools, Tool, ToolEntrypoint};
|
||||||
use uv_warnings::warn_user_once;
|
use uv_warnings::{warn_user, warn_user_once};
|
||||||
|
|
||||||
use crate::commands::project::{resolve_environment, sync_environment, update_environment};
|
use crate::commands::project::{resolve_environment, sync_environment, update_environment};
|
||||||
use crate::commands::reporters::PythonDownloadReporter;
|
use crate::commands::reporters::PythonDownloadReporter;
|
||||||
|
@ -31,6 +31,7 @@ use crate::commands::tool::common::resolve_requirements;
|
||||||
use crate::commands::{ExitStatus, SharedState};
|
use crate::commands::{ExitStatus, SharedState};
|
||||||
use crate::printer::Printer;
|
use crate::printer::Printer;
|
||||||
use crate::settings::ResolverInstallerSettings;
|
use crate::settings::ResolverInstallerSettings;
|
||||||
|
use crate::shell::Shell;
|
||||||
|
|
||||||
/// Install a tool.
|
/// Install a tool.
|
||||||
pub(crate) async fn install(
|
pub(crate) async fn install(
|
||||||
|
@ -373,5 +374,75 @@ pub(crate) async fn install(
|
||||||
);
|
);
|
||||||
installed_tools.add_tool_receipt(&from.name, tool)?;
|
installed_tools.add_tool_receipt(&from.name, tool)?;
|
||||||
|
|
||||||
|
// If the executable directory isn't on the user's PATH, warn.
|
||||||
|
if !std::env::var_os("PATH")
|
||||||
|
.as_ref()
|
||||||
|
.iter()
|
||||||
|
.flat_map(std::env::split_paths)
|
||||||
|
.any(|path| same_file::is_same_file(&executable_directory, path).unwrap_or(false))
|
||||||
|
{
|
||||||
|
let dir = executable_directory.simplified_display();
|
||||||
|
let export = match Shell::from_env() {
|
||||||
|
None => None,
|
||||||
|
Some(Shell::Nushell) => None,
|
||||||
|
Some(Shell::Bash | Shell::Zsh) => Some(format!(
|
||||||
|
"export PATH=\"{}:$PATH\"",
|
||||||
|
backslash_escape(&dir.to_string()),
|
||||||
|
)),
|
||||||
|
Some(Shell::Fish) => Some(format!(
|
||||||
|
"fish_add_path \"{}\"",
|
||||||
|
backslash_escape(&dir.to_string()),
|
||||||
|
)),
|
||||||
|
Some(Shell::Csh) => Some(format!(
|
||||||
|
"setenv PATH \"{}:$PATH\"",
|
||||||
|
backslash_escape(&dir.to_string()),
|
||||||
|
)),
|
||||||
|
Some(Shell::Powershell) => Some(format!(
|
||||||
|
"$env:PATH = \"{};$env:PATH\"",
|
||||||
|
backtick_escape(&dir.to_string()),
|
||||||
|
)),
|
||||||
|
Some(Shell::Cmd) => Some(format!(
|
||||||
|
"set PATH=\"{};%PATH%\"",
|
||||||
|
backslash_escape(&dir.to_string()),
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
if let Some(export) = export {
|
||||||
|
warn_user!(
|
||||||
|
"`{dir}` is not on your PATH. To use installed tools, run:\n {}",
|
||||||
|
export.green()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
warn_user!(
|
||||||
|
"`{dir}` is not on your PATH. To use installed tools, add the directory to your PATH",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ExitStatus::Success)
|
Ok(ExitStatus::Success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Escape a string for use in a shell command by inserting backslashes.
|
||||||
|
fn backslash_escape(s: &str) -> String {
|
||||||
|
let mut escaped = String::with_capacity(s.len());
|
||||||
|
for c in s.chars() {
|
||||||
|
match c {
|
||||||
|
'\\' | '"' => escaped.push('\\'),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
escaped.push(c);
|
||||||
|
}
|
||||||
|
escaped
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Escape a string for use in a `PowerShell` command by inserting backticks.
|
||||||
|
fn backtick_escape(s: &str) -> String {
|
||||||
|
let mut escaped = String::with_capacity(s.len());
|
||||||
|
for c in s.chars() {
|
||||||
|
match c {
|
||||||
|
'\\' | '"' | '$' => escaped.push('`'),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
escaped.push(c);
|
||||||
|
}
|
||||||
|
escaped
|
||||||
|
}
|
||||||
|
|
|
@ -26,7 +26,8 @@ fn tool_install() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -101,7 +102,8 @@ fn tool_install() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("flask")
|
.arg("flask")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -179,7 +181,8 @@ fn tool_install_version() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black==24.2.0")
|
.arg("black==24.2.0")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -264,7 +267,8 @@ fn tool_install_from() {
|
||||||
.arg("--from")
|
.arg("--from")
|
||||||
.arg("black==24.2.0")
|
.arg("black==24.2.0")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -289,7 +293,8 @@ fn tool_install_from() {
|
||||||
.arg("--from")
|
.arg("--from")
|
||||||
.arg("flask==24.2.0")
|
.arg("flask==24.2.0")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -305,7 +310,8 @@ fn tool_install_from() {
|
||||||
.arg("--from")
|
.arg("--from")
|
||||||
.arg("black==24.3.0")
|
.arg("black==24.3.0")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -329,7 +335,8 @@ fn tool_install_already_installed() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -394,7 +401,8 @@ fn tool_install_already_installed() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -429,7 +437,8 @@ fn tool_install_already_installed() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--reinstall")
|
.arg("--reinstall")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -461,7 +470,8 @@ fn tool_install_already_installed() {
|
||||||
.arg("--reinstall-package")
|
.arg("--reinstall-package")
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -483,7 +493,8 @@ fn tool_install_already_installed() {
|
||||||
.arg("--reinstall-package")
|
.arg("--reinstall-package")
|
||||||
.arg("click")
|
.arg("click")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -515,7 +526,8 @@ fn tool_install_entry_point_exists() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -554,7 +566,8 @@ fn tool_install_entry_point_exists() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--reinstall")
|
.arg("--reinstall")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -594,7 +607,8 @@ fn tool_install_entry_point_exists() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -617,7 +631,8 @@ fn tool_install_entry_point_exists() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--force")
|
.arg("--force")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -642,7 +657,8 @@ fn tool_install_entry_point_exists() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--force")
|
.arg("--force")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -658,7 +674,8 @@ fn tool_install_entry_point_exists() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -675,7 +692,8 @@ fn tool_install_entry_point_exists() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--reinstall")
|
.arg("--reinstall")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -776,6 +794,10 @@ fn tool_install_home() {
|
||||||
.env(
|
.env(
|
||||||
"XDG_DATA_HOME",
|
"XDG_DATA_HOME",
|
||||||
context.home_dir.child(".local").child("share").as_os_str(),
|
context.home_dir.child(".local").child("share").as_os_str(),
|
||||||
|
)
|
||||||
|
.env(
|
||||||
|
"PATH",
|
||||||
|
context.home_dir.child(".local").child("bin").as_os_str(),
|
||||||
);
|
);
|
||||||
uv_snapshot!(context.filters(), cmd, @r###"
|
uv_snapshot!(context.filters(), cmd, @r###"
|
||||||
success: true
|
success: true
|
||||||
|
@ -808,12 +830,14 @@ fn tool_install_xdg_data_home() {
|
||||||
let context = TestContext::new("3.12").with_filtered_exe_suffix();
|
let context = TestContext::new("3.12").with_filtered_exe_suffix();
|
||||||
let tool_dir = context.temp_dir.child("tools");
|
let tool_dir = context.temp_dir.child("tools");
|
||||||
let data_home = context.temp_dir.child("data/home");
|
let data_home = context.temp_dir.child("data/home");
|
||||||
|
let bin_dir = context.temp_dir.child("data/bin");
|
||||||
|
|
||||||
// Install `black`
|
// Install `black`
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_DATA_HOME", data_home.as_os_str()), @r###"
|
.env("XDG_DATA_HOME", data_home.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -849,7 +873,8 @@ fn tool_install_xdg_bin_home() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -883,7 +908,8 @@ fn tool_install_no_entrypoints() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("iniconfig")
|
.arg("iniconfig")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -909,7 +935,8 @@ fn tool_install_unnamed_package() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl")
|
.arg("https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -995,7 +1022,8 @@ fn tool_install_unnamed_conflict() {
|
||||||
.arg("--from")
|
.arg("--from")
|
||||||
.arg("https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
.arg("https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1019,7 +1047,8 @@ fn tool_install_unnamed_from() {
|
||||||
.arg("--from")
|
.arg("--from")
|
||||||
.arg("https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl")
|
.arg("https://files.pythonhosted.org/packages/0f/89/294c9a6b6c75a08da55e9d05321d0707e9418735e3062b12ef0f54c33474/black-24.4.2-py3-none-any.whl")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1104,7 +1133,8 @@ fn tool_install_unnamed_with() {
|
||||||
.arg("--with")
|
.arg("--with")
|
||||||
.arg("https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
.arg("https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1193,7 +1223,8 @@ fn tool_install_upgrade() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black==24.1.1")
|
.arg("black==24.1.1")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1231,7 +1262,8 @@ fn tool_install_upgrade() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1261,7 +1293,8 @@ fn tool_install_upgrade() {
|
||||||
.arg("--with")
|
.arg("--with")
|
||||||
.arg("iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
.arg("iniconfig @ https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1298,7 +1331,8 @@ fn tool_install_upgrade() {
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.arg("--upgrade")
|
.arg("--upgrade")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1345,7 +1379,8 @@ fn tool_install_python_request() {
|
||||||
.arg("3.12")
|
.arg("3.12")
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1370,7 +1405,8 @@ fn tool_install_python_request() {
|
||||||
.arg("3.12")
|
.arg("3.12")
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1386,7 +1422,8 @@ fn tool_install_python_request() {
|
||||||
.arg("3.11")
|
.arg("3.11")
|
||||||
.arg("black")
|
.arg("black")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1420,7 +1457,8 @@ fn tool_install_preserve_environment() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black==24.1.1")
|
.arg("black==24.1.1")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1445,7 +1483,8 @@ fn tool_install_preserve_environment() {
|
||||||
.arg("--with")
|
.arg("--with")
|
||||||
.arg("packaging==0.0.1")
|
.arg("packaging==0.0.1")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1460,7 +1499,8 @@ fn tool_install_preserve_environment() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black==24.1.1")
|
.arg("black==24.1.1")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 1
|
exit_code: 1
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
@ -1470,3 +1510,40 @@ fn tool_install_preserve_environment() {
|
||||||
`black==24.1.1` is already installed
|
`black==24.1.1` is already installed
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test warning when the binary directory is not on the user's PATH.
|
||||||
|
#[test]
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn tool_install_warn_path() {
|
||||||
|
let context = TestContext::new("3.12")
|
||||||
|
.with_filtered_counts()
|
||||||
|
.with_filtered_exe_suffix();
|
||||||
|
let tool_dir = context.temp_dir.child("tools");
|
||||||
|
let bin_dir = context.temp_dir.child("bin");
|
||||||
|
|
||||||
|
// Install `black`.
|
||||||
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
|
.arg("black==24.1.1")
|
||||||
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env_remove("PATH"), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
warning: `uv tool install` is experimental and may change without warning.
|
||||||
|
Resolved [N] packages in [TIME]
|
||||||
|
Prepared [N] packages in [TIME]
|
||||||
|
Installed [N] packages in [TIME]
|
||||||
|
+ black==24.1.1
|
||||||
|
+ click==8.1.7
|
||||||
|
+ mypy-extensions==1.0.0
|
||||||
|
+ packaging==24.0
|
||||||
|
+ pathspec==0.12.1
|
||||||
|
+ platformdirs==4.2.0
|
||||||
|
Installed 2 executables: black, blackd
|
||||||
|
warning: `[TEMP_DIR]/bin` is not on your PATH. To use installed tools, run:
|
||||||
|
export PATH="[TEMP_DIR]/bin:$PATH"
|
||||||
|
"###);
|
||||||
|
}
|
||||||
|
|
|
@ -51,7 +51,8 @@ fn tool_uninstall() {
|
||||||
uv_snapshot!(context.filters(), context.tool_install()
|
uv_snapshot!(context.filters(), context.tool_install()
|
||||||
.arg("black==24.2.0")
|
.arg("black==24.2.0")
|
||||||
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
.env("UV_TOOL_DIR", tool_dir.as_os_str())
|
||||||
.env("XDG_BIN_HOME", bin_dir.as_os_str()), @r###"
|
.env("XDG_BIN_HOME", bin_dir.as_os_str())
|
||||||
|
.env("PATH", bin_dir.as_os_str()), @r###"
|
||||||
success: true
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue