mirror of https://github.com/astral-sh/uv
Do not replace the Python dylib on macOS if `install_name_tool` fails
This commit is contained in:
parent
1ddfcee9e9
commit
6f50cd842f
|
|
@ -1,15 +1,28 @@
|
|||
use std::{io::ErrorKind, path::PathBuf};
|
||||
|
||||
use tempfile::tempdir_in;
|
||||
use uv_fs::Simplified as _;
|
||||
use uv_warnings::warn_user;
|
||||
|
||||
use crate::managed::ManagedPythonInstallation;
|
||||
|
||||
pub fn patch_dylib_install_name(dylib: PathBuf) -> Result<(), Error> {
|
||||
// If `install_name_tool` fails, it seems to be capable of rendering the dylib unusable.
|
||||
// So we'll create a copy, patch that, then, on success, replace the original
|
||||
let tmp = tempdir_in(
|
||||
dylib
|
||||
.parent()
|
||||
.expect("dylib should have a parent directory"),
|
||||
)?;
|
||||
let tmp_dylib = tmp
|
||||
.path()
|
||||
.join(dylib.file_name().expect("dylib should have a file name"));
|
||||
fs_err::copy(&dylib, &tmp_dylib)?;
|
||||
|
||||
let output = match std::process::Command::new("install_name_tool")
|
||||
.arg("-id")
|
||||
.arg(&dylib)
|
||||
.arg(&dylib)
|
||||
.arg(&tmp_dylib)
|
||||
.output()
|
||||
{
|
||||
Ok(output) => output,
|
||||
|
|
@ -28,6 +41,8 @@ pub fn patch_dylib_install_name(dylib: PathBuf) -> Result<(), Error> {
|
|||
return Err(Error::RenameError { dylib, stderr });
|
||||
}
|
||||
|
||||
fs_err::rename(tmp_dylib, dylib)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,23 +75,23 @@ fn python_install() {
|
|||
"###);
|
||||
|
||||
// Should be a no-op when already installed
|
||||
uv_snapshot!(context.filters(), context.python_install(), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install(), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Python is already installed. Use `uv python install <request>` to install another version.
|
||||
"###);
|
||||
");
|
||||
|
||||
// Similarly, when a requested version is already installed
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("3.13"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("3.13"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
");
|
||||
|
||||
// You can opt-in to a reinstall
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("3.13").arg("--reinstall"), @r"
|
||||
|
|
@ -250,14 +250,14 @@ fn python_install_automatic() {
|
|||
// Otherwise, we should fetch the latest Python version
|
||||
uv_snapshot!(context.filters(), context.run()
|
||||
.env_remove("VIRTUAL_ENV")
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###"
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
(3, 13)
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
");
|
||||
|
||||
// Subsequently, we can use the interpreter even with downloads disabled
|
||||
uv_snapshot!(context.filters(), context.run()
|
||||
|
|
@ -276,14 +276,14 @@ fn python_install_automatic() {
|
|||
uv_snapshot!(context.filters(), context.run()
|
||||
.env_remove("VIRTUAL_ENV")
|
||||
.arg("-p").arg("3.12")
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###"
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
(3, 12)
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
");
|
||||
|
||||
// But some requests cannot be mapped to a download
|
||||
uv_snapshot!(context.filters(), context.run()
|
||||
|
|
@ -322,14 +322,14 @@ fn python_install_automatic() {
|
|||
// In tests, we ignore `PATH` during Python discovery so we need to add the context `bin`
|
||||
.env("UV_TEST_PYTHON_PATH", context.bin_dir.as_os_str())
|
||||
.arg("-p").arg("3.11")
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r###"
|
||||
.arg("python").arg("-c").arg("import sys; print(sys.version_info[:2])"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
(3, 11)
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,14 +358,13 @@ fn regression_cpython() {
|
|||
uv_snapshot!(context.filters(), context.run()
|
||||
.env_remove("VIRTUAL_ENV")
|
||||
.arg("-p").arg("3.12")
|
||||
.arg("mre.py"), @r###"
|
||||
.arg("mre.py"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
|
||||
"###);
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -630,14 +629,14 @@ fn python_install_preview() {
|
|||
"###);
|
||||
|
||||
// Should be a no-op when already installed
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Python is already installed. Use `uv python install <request>` to install another version.
|
||||
"###);
|
||||
");
|
||||
|
||||
// You can opt-in to a reinstall
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("--reinstall"), @r"
|
||||
|
|
@ -931,7 +930,7 @@ fn python_install_preview_upgrade() {
|
|||
}
|
||||
|
||||
// Installing 3.12.4 should not replace the executable, but also shouldn't fail
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
|
@ -939,7 +938,7 @@ fn python_install_preview_upgrade() {
|
|||
----- stderr -----
|
||||
Installed Python 3.12.4 in [TIME]
|
||||
+ cpython-3.12.4-[PLATFORM]
|
||||
"###);
|
||||
");
|
||||
|
||||
if cfg!(unix) {
|
||||
insta::with_settings!({
|
||||
|
|
@ -960,7 +959,7 @@ fn python_install_preview_upgrade() {
|
|||
}
|
||||
|
||||
// Using `--reinstall` is not sufficient to replace it either
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4").arg("--reinstall"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4").arg("--reinstall"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
|
@ -968,7 +967,7 @@ fn python_install_preview_upgrade() {
|
|||
----- stderr -----
|
||||
Installed Python 3.12.4 in [TIME]
|
||||
~ cpython-3.12.4-[PLATFORM]
|
||||
"###);
|
||||
");
|
||||
|
||||
if cfg!(unix) {
|
||||
insta::with_settings!({
|
||||
|
|
@ -989,7 +988,7 @@ fn python_install_preview_upgrade() {
|
|||
}
|
||||
|
||||
// But `--force` is
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4").arg("--force"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.4").arg("--force"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
|
@ -997,7 +996,7 @@ fn python_install_preview_upgrade() {
|
|||
----- stderr -----
|
||||
Installed Python 3.12.4 in [TIME]
|
||||
+ cpython-3.12.4-[PLATFORM] (python3.12)
|
||||
"###);
|
||||
");
|
||||
|
||||
if cfg!(unix) {
|
||||
insta::with_settings!({
|
||||
|
|
@ -1018,7 +1017,7 @@ fn python_install_preview_upgrade() {
|
|||
}
|
||||
|
||||
// But installing 3.12.6 should upgrade automatically
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.6"), @r###"
|
||||
uv_snapshot!(context.filters(), context.python_install().arg("--preview").arg("3.12.6"), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
|
@ -1026,7 +1025,7 @@ fn python_install_preview_upgrade() {
|
|||
----- stderr -----
|
||||
Installed Python 3.12.6 in [TIME]
|
||||
+ cpython-3.12.6-[PLATFORM] (python3.12)
|
||||
"###);
|
||||
");
|
||||
|
||||
if cfg!(unix) {
|
||||
insta::with_settings!({
|
||||
|
|
@ -2029,7 +2028,7 @@ fn python_install_patch_dylib() {
|
|||
let mut cmd = std::process::Command::new("otool");
|
||||
cmd.arg("-D").arg(dylib.as_ref());
|
||||
|
||||
uv_snapshot!(context.filters(), cmd, @r###"
|
||||
uv_snapshot!(context.filters(), cmd, @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
|
@ -2037,7 +2036,7 @@ fn python_install_patch_dylib() {
|
|||
[TEMP_DIR]/managed/cpython-3.13.1-[PLATFORM]/lib/libpython3.13.dylib
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2172,14 +2171,14 @@ fn python_install_cached() {
|
|||
// Should be a no-op when already installed
|
||||
uv_snapshot!(context.filters(), context
|
||||
.python_install()
|
||||
.env(EnvVars::UV_PYTHON_CACHE_DIR, python_cache.as_ref()), @r###"
|
||||
.env(EnvVars::UV_PYTHON_CACHE_DIR, python_cache.as_ref()), @r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
Python is already installed. Use `uv python install <request>` to install another version.
|
||||
"###);
|
||||
");
|
||||
|
||||
uv_snapshot!(context.filters(), context.python_uninstall().arg("3.13"), @r"
|
||||
success: true
|
||||
|
|
|
|||
Loading…
Reference in New Issue