Support file or directory removal for Windows symlinks (#15543)

## Summary

Similar to https://github.com/rust-lang/cargo/pull/13910.

I think this should close https://github.com/astral-sh/uv/issues/15541
since we're indiscriminately calling `remove_dir` on that dangling
symlink.
This commit is contained in:
Charlie Marsh 2025-08-27 07:43:03 -04:00 committed by GitHub
parent db4dfb4cf9
commit 9108b04642
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 27 additions and 5 deletions

View File

@ -64,9 +64,22 @@ impl Removal {
// Remove the file. // Remove the file.
self.total_bytes += metadata.len(); self.total_bytes += metadata.len();
if cfg!(windows) && metadata.is_symlink() { if metadata.is_symlink() {
// Remove the junction. #[cfg(windows)]
remove_dir(path)?; {
use std::os::windows::fs::FileTypeExt;
if metadata.file_type().is_symlink_dir() {
remove_dir(path)?;
} else {
remove_file(path)?;
}
}
#[cfg(not(windows))]
{
remove_file(path)?;
}
} else { } else {
remove_file(path)?; remove_file(path)?;
} }
@ -94,8 +107,17 @@ impl Removal {
} }
let entry = entry?; let entry = entry?;
if cfg!(windows) && entry.file_type().is_symlink() { if entry.file_type().is_symlink() && {
// Remove the junction. #[cfg(windows)]
{
use std::os::windows::fs::FileTypeExt;
entry.file_type().is_symlink_dir()
}
#[cfg(not(windows))]
{
false
}
} {
self.num_files += 1; self.num_files += 1;
remove_dir(entry.path())?; remove_dir(entry.path())?;
} else if entry.file_type().is_dir() { } else if entry.file_type().is_dir() {