mirror of https://github.com/astral-sh/uv
Remove fs2 dependency and update Rust to 1.89 (#15764)
<!-- Thank you for contributing to uv! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> This PR removes the crate fs2 and updates Rust version to 1.89. *Why?* Crate fs2 is unmaintained for a long time now and has unfixed issues. Especially it doesn't build on AIX, which is the reason I started fixing it. *How?* I removed fs2 and replaced it by std:fs:File methods. ## Test Plan <!-- How was it tested? --> - I built it on Windows and AIX only. - I did not test the artifacts. --------- Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
This commit is contained in:
parent
6da135a66a
commit
485503ee65
|
|
@ -1443,16 +1443,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fs2"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
|
|
@ -5892,7 +5882,6 @@ dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"encoding_rs_io",
|
"encoding_rs_io",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
"fs2",
|
|
||||||
"junction",
|
"junction",
|
||||||
"path-slash",
|
"path-slash",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,6 @@ encoding_rs_io = { version = "0.1.7" }
|
||||||
etcetera = { version = "0.11.0" }
|
etcetera = { version = "0.11.0" }
|
||||||
flate2 = { version = "1.0.33", default-features = false, features = ["zlib-rs"] }
|
flate2 = { version = "1.0.33", default-features = false, features = ["zlib-rs"] }
|
||||||
fs-err = { version = "3.0.0", features = ["tokio"] }
|
fs-err = { version = "3.0.0", features = ["tokio"] }
|
||||||
fs2 = { version = "0.4.3" }
|
|
||||||
futures = { version = "0.3.30" }
|
futures = { version = "0.3.30" }
|
||||||
glob = { version = "0.3.1" }
|
glob = { version = "0.3.1" }
|
||||||
globset = { version = "0.4.15" }
|
globset = { version = "0.4.15" }
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ dunce = { workspace = true }
|
||||||
either = { workspace = true }
|
either = { workspace = true }
|
||||||
encoding_rs_io = { workspace = true }
|
encoding_rs_io = { workspace = true }
|
||||||
fs-err = { workspace = true }
|
fs-err = { workspace = true }
|
||||||
fs2 = { workspace = true }
|
|
||||||
path-slash = { workspace = true }
|
path-slash = { workspace = true }
|
||||||
percent-encoding = { workspace = true }
|
percent-encoding = { workspace = true }
|
||||||
same-file = { workspace = true }
|
same-file = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::io;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use fs2::FileExt;
|
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
|
|
@ -555,10 +553,12 @@ pub fn persist_with_retry_sync(
|
||||||
/// Iterate over the subdirectories of a directory.
|
/// Iterate over the subdirectories of a directory.
|
||||||
///
|
///
|
||||||
/// If the directory does not exist, returns an empty iterator.
|
/// If the directory does not exist, returns an empty iterator.
|
||||||
pub fn directories(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>, io::Error> {
|
pub fn directories(
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<impl Iterator<Item = PathBuf>, std::io::Error> {
|
||||||
let entries = match path.as_ref().read_dir() {
|
let entries = match path.as_ref().read_dir() {
|
||||||
Ok(entries) => Some(entries),
|
Ok(entries) => Some(entries),
|
||||||
Err(err) if err.kind() == io::ErrorKind::NotFound => None,
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
Ok(entries
|
Ok(entries
|
||||||
|
|
@ -578,10 +578,10 @@ pub fn directories(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBu
|
||||||
/// Iterate over the entries in a directory.
|
/// Iterate over the entries in a directory.
|
||||||
///
|
///
|
||||||
/// If the directory does not exist, returns an empty iterator.
|
/// If the directory does not exist, returns an empty iterator.
|
||||||
pub fn entries(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>, io::Error> {
|
pub fn entries(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>, std::io::Error> {
|
||||||
let entries = match path.as_ref().read_dir() {
|
let entries = match path.as_ref().read_dir() {
|
||||||
Ok(entries) => Some(entries),
|
Ok(entries) => Some(entries),
|
||||||
Err(err) if err.kind() == io::ErrorKind::NotFound => None,
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
Ok(entries
|
Ok(entries
|
||||||
|
|
@ -600,10 +600,10 @@ pub fn entries(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>,
|
||||||
/// Iterate over the files in a directory.
|
/// Iterate over the files in a directory.
|
||||||
///
|
///
|
||||||
/// If the directory does not exist, returns an empty iterator.
|
/// If the directory does not exist, returns an empty iterator.
|
||||||
pub fn files(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>, io::Error> {
|
pub fn files(path: impl AsRef<Path>) -> Result<impl Iterator<Item = PathBuf>, std::io::Error> {
|
||||||
let entries = match path.as_ref().read_dir() {
|
let entries = match path.as_ref().read_dir() {
|
||||||
Ok(entries) => Some(entries),
|
Ok(entries) => Some(entries),
|
||||||
Err(err) if err.kind() == io::ErrorKind::NotFound => None,
|
Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
Ok(entries
|
Ok(entries
|
||||||
|
|
@ -653,18 +653,18 @@ pub fn is_virtualenv_base(path: impl AsRef<Path>) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether the error is due to a lock being held.
|
/// Whether the error is due to a lock being held.
|
||||||
fn is_known_already_locked_error(err: &std::io::Error) -> bool {
|
fn is_known_already_locked_error(err: &std::fs::TryLockError) -> bool {
|
||||||
if matches!(err.kind(), std::io::ErrorKind::WouldBlock) {
|
match err {
|
||||||
return true;
|
std::fs::TryLockError::WouldBlock => true,
|
||||||
}
|
std::fs::TryLockError::Error(err) => {
|
||||||
|
|
||||||
// On Windows, we've seen: Os { code: 33, kind: Uncategorized, message: "The process cannot access the file because another process has locked a portion of the file." }
|
// On Windows, we've seen: Os { code: 33, kind: Uncategorized, message: "The process cannot access the file because another process has locked a portion of the file." }
|
||||||
if cfg!(windows) && err.raw_os_error() == Some(33) {
|
if cfg!(windows) && err.raw_os_error() == Some(33) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A file lock that is automatically released when dropped.
|
/// A file lock that is automatically released when dropped.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -678,7 +678,7 @@ impl LockedFile {
|
||||||
"Checking lock for `{resource}` at `{}`",
|
"Checking lock for `{resource}` at `{}`",
|
||||||
file.path().user_display()
|
file.path().user_display()
|
||||||
);
|
);
|
||||||
match file.file().try_lock_exclusive() {
|
match file.file().try_lock() {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
debug!("Acquired lock for `{resource}`");
|
debug!("Acquired lock for `{resource}`");
|
||||||
Ok(Self(file))
|
Ok(Self(file))
|
||||||
|
|
@ -692,15 +692,7 @@ impl LockedFile {
|
||||||
"Waiting to acquire lock for `{resource}` at `{}`",
|
"Waiting to acquire lock for `{resource}` at `{}`",
|
||||||
file.path().user_display(),
|
file.path().user_display(),
|
||||||
);
|
);
|
||||||
file.file().lock_exclusive().map_err(|err| {
|
file.lock()?;
|
||||||
// Not an fs_err method, we need to build our own path context
|
|
||||||
std::io::Error::other(format!(
|
|
||||||
"Could not acquire lock for `{resource}` at `{}`: {}",
|
|
||||||
file.path().user_display(),
|
|
||||||
err
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
debug!("Acquired lock for `{resource}`");
|
debug!("Acquired lock for `{resource}`");
|
||||||
Ok(Self(file))
|
Ok(Self(file))
|
||||||
}
|
}
|
||||||
|
|
@ -713,7 +705,7 @@ impl LockedFile {
|
||||||
"Checking lock for `{resource}` at `{}`",
|
"Checking lock for `{resource}` at `{}`",
|
||||||
file.path().user_display()
|
file.path().user_display()
|
||||||
);
|
);
|
||||||
match file.file().try_lock_exclusive() {
|
match file.try_lock() {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
debug!("Acquired lock for `{resource}`");
|
debug!("Acquired lock for `{resource}`");
|
||||||
Some(Self(file))
|
Some(Self(file))
|
||||||
|
|
@ -739,8 +731,7 @@ impl LockedFile {
|
||||||
"Checking shared lock for `{resource}` at `{}`",
|
"Checking shared lock for `{resource}` at `{}`",
|
||||||
file.path().user_display()
|
file.path().user_display()
|
||||||
);
|
);
|
||||||
// TODO(konsti): Update fs_err to support this.
|
match file.try_lock_shared() {
|
||||||
match FileExt::try_lock_shared(file.file()) {
|
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
debug!("Acquired shared lock for `{resource}`");
|
debug!("Acquired shared lock for `{resource}`");
|
||||||
Ok(Self(file))
|
Ok(Self(file))
|
||||||
|
|
@ -754,15 +745,7 @@ impl LockedFile {
|
||||||
"Waiting to acquire shared lock for `{resource}` at `{}`",
|
"Waiting to acquire shared lock for `{resource}` at `{}`",
|
||||||
file.path().user_display(),
|
file.path().user_display(),
|
||||||
);
|
);
|
||||||
FileExt::lock_shared(file.file()).map_err(|err| {
|
file.lock_shared()?;
|
||||||
// Not an fs_err method, we need to build our own path context
|
|
||||||
std::io::Error::other(format!(
|
|
||||||
"Could not acquire shared lock for `{resource}` at `{}`: {}",
|
|
||||||
file.path().user_display(),
|
|
||||||
err
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
debug!("Acquired shared lock for `{resource}`");
|
debug!("Acquired shared lock for `{resource}`");
|
||||||
Ok(Self(file))
|
Ok(Self(file))
|
||||||
}
|
}
|
||||||
|
|
@ -884,11 +867,10 @@ impl LockedFile {
|
||||||
|
|
||||||
impl Drop for LockedFile {
|
impl Drop for LockedFile {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if let Err(err) = fs2::FileExt::unlock(self.0.file()) {
|
if let Err(err) = self.0.unlock() {
|
||||||
error!(
|
error!(
|
||||||
"Failed to unlock {}; program may be stuck: {}",
|
"Failed to unlock resource at `{}`; program may be stuck: {err}",
|
||||||
self.0.path().display(),
|
self.0.path().display()
|
||||||
err
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
debug!("Released lock at `{}`", self.0.path().display());
|
debug!("Released lock at `{}`", self.0.path().display());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue