mirror of
https://github.com/astral-sh/uv.git
synced 2025-11-23 12:56:47 +00:00
Avoid removing local wheels when unzipping (#560)
## Summary When installing a local wheel, we need to avoid removing the zipped wheel (since it lives outside of the cache), _and_ need to ensure that we unzip the wheel into the cache (rather than replacing the zipped wheel, which may even live outside of the project). Closes https://github.com/astral-sh/puffin/issues/553.
This commit is contained in:
parent
6f055ecf3b
commit
a15da36d74
7 changed files with 97 additions and 53 deletions
|
|
@ -46,47 +46,55 @@ pub fn write_atomic_sync(path: impl AsRef<Path>, data: impl AsRef<[u8]>) -> std:
|
|||
|
||||
/// Rename `from` to `to` atomically using a temporary file and atomic rename.
|
||||
///
|
||||
/// Returns `false` if the `to` path already existed and thus was removed before performing the
|
||||
/// Returns a [`Target`] if the `to` path already existed and thus was removed before performing the
|
||||
/// rename.
|
||||
pub fn rename_atomic_sync(from: impl AsRef<Path>, to: impl AsRef<Path>) -> std::io::Result<bool> {
|
||||
// Remove the destination if it exists.
|
||||
let safe = if let Ok(metadata) = fs_err::metadata(&to) {
|
||||
if metadata.is_dir() {
|
||||
pub fn rename_atomic_sync(
|
||||
from: impl AsRef<Path>,
|
||||
to: impl AsRef<Path>,
|
||||
) -> std::io::Result<Option<Target>> {
|
||||
// Remove the destination, if it exists.
|
||||
let target = if let Ok(metadata) = fs_err::metadata(&to) {
|
||||
Some(if metadata.is_dir() {
|
||||
fs_err::remove_dir_all(&to)?;
|
||||
Target::Directory
|
||||
} else {
|
||||
fs_err::remove_file(&to)?;
|
||||
}
|
||||
false
|
||||
Target::File
|
||||
})
|
||||
} else {
|
||||
true
|
||||
None
|
||||
};
|
||||
|
||||
// Move the source file to the destination.
|
||||
fs_err::rename(from, to)?;
|
||||
|
||||
Ok(safe)
|
||||
Ok(target)
|
||||
}
|
||||
|
||||
/// Copy `from` to `to` atomically using a temporary file and atomic rename.
|
||||
///
|
||||
/// Returns `false` if the `to` path already existed and thus was removed before performing the
|
||||
/// rename.
|
||||
pub fn copy_atomic_sync(from: impl AsRef<Path>, to: impl AsRef<Path>) -> std::io::Result<bool> {
|
||||
/// Returns a [`Target`] if the `to` path already existed and thus was removed before performing the
|
||||
/// copy.
|
||||
pub fn copy_atomic_sync(
|
||||
from: impl AsRef<Path>,
|
||||
to: impl AsRef<Path>,
|
||||
) -> std::io::Result<Option<Target>> {
|
||||
// Copy to a temporary file.
|
||||
let temp_file =
|
||||
NamedTempFile::new_in(to.as_ref().parent().expect("Write path must have a parent"))?;
|
||||
fs_err::copy(from, &temp_file)?;
|
||||
|
||||
// Remove the destination if it exists.
|
||||
let safe = if let Ok(metadata) = fs_err::metadata(&to) {
|
||||
if metadata.is_dir() {
|
||||
// Remove the destination, if it exists.
|
||||
let target = if let Ok(metadata) = fs_err::metadata(&to) {
|
||||
Some(if metadata.is_dir() {
|
||||
fs_err::remove_dir_all(&to)?;
|
||||
Target::Directory
|
||||
} else {
|
||||
fs_err::remove_file(&to)?;
|
||||
}
|
||||
false
|
||||
Target::File
|
||||
})
|
||||
} else {
|
||||
true
|
||||
None
|
||||
};
|
||||
|
||||
// Move the temporary file to the destination.
|
||||
|
|
@ -101,5 +109,25 @@ pub fn copy_atomic_sync(from: impl AsRef<Path>, to: impl AsRef<Path>) -> std::io
|
|||
)
|
||||
})?;
|
||||
|
||||
Ok(safe)
|
||||
Ok(target)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Target {
|
||||
/// The target path was an existing file.
|
||||
File,
|
||||
/// The target path was an existing directory.
|
||||
Directory,
|
||||
/// The target path did not exist.
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn is_file(self) -> bool {
|
||||
matches!(self, Self::File)
|
||||
}
|
||||
|
||||
pub fn is_directory(self) -> bool {
|
||||
matches!(self, Self::Directory)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue