Skip to content

Commit b865526

Browse files
Coruscant11Jean-Philippe
authored andcommitted
Handle Windows AV/EDR file locks during script installations
1 parent 2aca623 commit b865526

3 files changed

Lines changed: 12 additions & 14 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-install-wheel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ serde_json = { workspace = true }
4949
sha2 = { workspace = true }
5050
tempfile = { workspace = true }
5151
thiserror = { workspace = true }
52+
tokio = { workspace = true }
5253
tracing = { workspace = true }
5354
walkdir = { workspace = true }
5455
zip = { workspace = true }

crates/uv-install-wheel/src/wheel.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use tracing::{instrument, warn};
1313
use walkdir::WalkDir;
1414

1515
use uv_cache_info::CacheInfo;
16-
use uv_fs::{relative_to, Simplified};
16+
use uv_fs::{relative_to, rename_with_retry, Simplified};
1717
use uv_normalize::PackageName;
1818
use uv_pypi_types::DirectUrl;
1919
use uv_shell::escape_posix_for_single_quotes;
@@ -393,6 +393,10 @@ fn install_script(
393393
let path = file.path();
394394
let mut script = File::open(&path)?;
395395

396+
let runtime = tokio::runtime::Builder::new_current_thread()
397+
.enable_all()
398+
.build()?;
399+
396400
// https://sphinx-locales.github.io/peps/pep-0427/#recommended-installer-features
397401
// > In wheel, scripts are packaged in {distribution}-{version}.data/scripts/.
398402
// > If the first line of a file in scripts/ starts with exactly b'#!python',
@@ -424,16 +428,8 @@ fn install_script(
424428

425429
let mut target = uv_fs::tempfile_in(&layout.scheme.scripts)?;
426430
let size_and_encoded_hash = copy_and_hash(&mut start.chain(script), &mut target)?;
427-
target.persist(&script_absolute).map_err(|err| {
428-
io::Error::new(
429-
io::ErrorKind::Other,
430-
format!(
431-
"Failed to persist temporary file to {}: {}",
432-
path.user_display(),
433-
err.error
434-
),
435-
)
436-
})?;
431+
432+
runtime.block_on(rename_with_retry(&target, &script_absolute))?;
437433
fs::remove_file(&path)?;
438434

439435
// Make the script executable. We just created the file, so we can set permissions directly.
@@ -467,7 +463,7 @@ fn install_script(
467463

468464
if permissions.mode() & 0o111 == 0o111 {
469465
// If the permissions are already executable, we don't need to change them.
470-
fs::rename(&path, &script_absolute)?;
466+
runtime.block_on(rename_with_retry(&path, &script_absolute))?;
471467
} else {
472468
// If we have to modify the permissions, copy the file, since we might not own it.
473469
warn!(
@@ -488,7 +484,7 @@ fn install_script(
488484

489485
#[cfg(not(unix))]
490486
{
491-
fs::rename(&path, &script_absolute)?;
487+
runtime.block_on(rename_with_retry(&path, &script_absolute))?;
492488
}
493489

494490
None

0 commit comments

Comments
 (0)