mirror of
https://github.com/astral-sh/uv.git
synced 2025-07-13 08:15:00 +00:00

Some checks are pending
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / check system | conda3.11 on windows (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / mkdocs (push) Waiting to run
CI / build binary | linux (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86_64 (push) Blocked by required conditions
CI / check system | python3.10 on windows (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on linux (push) Blocked by required conditions
CI / check system | conda3.8 on linux (push) Blocked by required conditions
CI / check system | conda3.11 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on macos (push) Blocked by required conditions
CI / check system | conda3.8 on windows (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Move the shlex-like quoting utils in the uv-shell crate, so we only write `r#"'"'"'"#` once. Split out from #8984
50 lines
2 KiB
Rust
50 lines
2 KiB
Rust
use crate::{Shell, Simplified};
|
|
use std::path::Path;
|
|
|
|
/// Quote a path, if necessary, for safe use in a POSIX-compatible shell command.
|
|
pub fn shlex_posix(executable: impl AsRef<Path>) -> String {
|
|
// Convert to a display path.
|
|
let executable = executable.as_ref().portable_display().to_string();
|
|
|
|
// Like Python's `shlex.quote`:
|
|
// > Use single quotes, and put single quotes into double quotes
|
|
// > The string $'b is then quoted as '$'"'"'b'
|
|
if executable.contains(' ') {
|
|
format!("'{}'", escape_posix_for_single_quotes(&executable))
|
|
} else {
|
|
executable
|
|
}
|
|
}
|
|
|
|
/// Escape a string for being used in single quotes in a POSIX-compatible shell command.
|
|
///
|
|
/// We want our scripts to support any POSIX shell. There's two kind of quotes in POSIX:
|
|
/// Single and double quotes. In bash, single quotes must not contain another single
|
|
/// quote, you can't even escape it (<https://linux.die.net/man/1/bash> under "QUOTING").
|
|
/// Double quotes have escaping rules different from shell to shell, which we can't do.
|
|
/// Bash has `$'\''`, but that's not universal enough.
|
|
///
|
|
/// As solution, use implicit string concatenations, by putting the single quote into double
|
|
/// quotes.
|
|
pub fn escape_posix_for_single_quotes(string: &str) -> String {
|
|
string.replace('\'', r#"'"'"'"#)
|
|
}
|
|
|
|
/// Quote a path, if necessary, for safe use in `PowerShell` and `cmd`.
|
|
pub fn shlex_windows(executable: impl AsRef<Path>, shell: Shell) -> String {
|
|
// Convert to a display path.
|
|
let executable = executable.as_ref().user_display().to_string();
|
|
|
|
// Wrap the executable in quotes (and a `&` invocation on PowerShell), if it contains spaces.
|
|
if executable.contains(' ') {
|
|
if shell == Shell::Powershell {
|
|
// For PowerShell, wrap in a `&` invocation.
|
|
format!("& \"{executable}\"")
|
|
} else {
|
|
// Otherwise, assume `cmd`, which doesn't need the `&`.
|
|
format!("\"{executable}\"")
|
|
}
|
|
} else {
|
|
executable
|
|
}
|
|
}
|