fix(venv.relocatable): script entrypoints should work if symlinked to (#8079)

Fixes: #8058

## Test Plan

Integration test (but only for Unix, because symlinks on Windows require
admin privs. Plus, they are not really all that idiomatic on Windows)
This commit is contained in:
Pavel Dikov 2024-10-10 13:00:56 +01:00 committed by GitHub
parent f2741220e5
commit bf15ca93cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 18 additions and 6 deletions

View File

@ -143,7 +143,7 @@ fn format_shebang(executable: impl AsRef<Path>, os_name: &str, relocatable: bool
// (note: the Windows trampoline binaries natively support relative paths to executable)
if shebang_length > 127 || executable.contains(' ') || relocatable {
let prefix = if relocatable {
r#""$(CDPATH= cd -- "$(dirname -- "$0")" && echo "$PWD")"/"#
r#""$(dirname -- "$(realpath -- "$0")")"/"#
} else {
""
};
@ -1019,7 +1019,7 @@ mod test {
let os_name = "posix";
assert_eq!(
format_shebang(executable, os_name, true),
"#!/bin/sh\n'''exec' \"$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && echo \"$PWD\")\"/'python3' \"$0\" \"$@\"\n' '''"
"#!/bin/sh\n'''exec' \"$(dirname -- \"$(realpath -- \"$0\")\")\"/'python3' \"$0\" \"$@\"\n' '''"
);
// Except on Windows...

View File

@ -298,9 +298,7 @@ pub(crate) fn create(
let virtual_env_dir = match (relocatable, name.to_owned()) {
(true, "activate") => {
// Extremely verbose, but should cover all major POSIX shells,
// as well as platforms where `readlink` does not implement `-f`.
r#"'"$(dirname -- "$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")" > /dev/null && echo "$PWD")")"'"#
r#"'"$(dirname -- "$(dirname -- "$(realpath -- "$SCRIPT_PATH")")")"'"#
}
(true, "activate.bat") => r"%~dp0..",
(true, "activate.fish") => {

View File

@ -6810,6 +6810,18 @@ fn install_relocatable() -> Result<()> {
.success()
.stdout(predicate::str::contains("Hello world!"));
// Relocatable entrypoint should still be usable even if symlinked.
// Only testable on POSIX since symlinks require elevated privilege on Windows
#[cfg(unix)]
{
let script_symlink_path = context.temp_dir.join("black");
std::os::unix::fs::symlink(script_path, script_symlink_path.clone())?;
Command::new(script_symlink_path.as_os_str())
.assert()
.success()
.stdout(predicate::str::contains("Hello world!"));
}
Ok(())
}

View File

@ -957,7 +957,9 @@ fn verify_pyvenv_cfg_relocatable() {
let activate_sh = scripts.child("activate");
activate_sh.assert(predicates::path::is_file());
activate_sh.assert(predicates::str::contains(r#"VIRTUAL_ENV=''"$(dirname -- "$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")" > /dev/null && echo "$PWD")")"''"#));
activate_sh.assert(predicates::str::contains(
r#"VIRTUAL_ENV=''"$(dirname -- "$(dirname -- "$(realpath -- "$SCRIPT_PATH")")")"''"#,
));
let activate_bat = scripts.child("activate.bat");
activate_bat.assert(predicates::path::is_file());