mirror of https://github.com/astral-sh/ruff
Replace `Mutex<RefCell>` with `Mutex` in vendored file system" (#12170)
This commit is contained in:
parent
47eb6ee42b
commit
b950a6c389
|
|
@ -1,5 +1,4 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
|
|
@ -13,6 +12,7 @@ pub use path::{VendoredPath, VendoredPathBuf};
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
|
||||||
type Result<T> = io::Result<T>;
|
type Result<T> = io::Result<T>;
|
||||||
|
type LockedZipArchive<'a> = MutexGuard<'a, VendoredZipArchive>;
|
||||||
|
|
||||||
/// File system that stores all content in a static zip archive
|
/// File system that stores all content in a static zip archive
|
||||||
/// bundled as part of the Ruff binary.
|
/// bundled as part of the Ruff binary.
|
||||||
|
|
@ -20,20 +20,19 @@ type Result<T> = io::Result<T>;
|
||||||
/// "Files" in the `VendoredFileSystem` are read-only and immutable.
|
/// "Files" in the `VendoredFileSystem` are read-only and immutable.
|
||||||
/// Directories are supported, but symlinks and hardlinks cannot exist.
|
/// Directories are supported, but symlinks and hardlinks cannot exist.
|
||||||
pub struct VendoredFileSystem {
|
pub struct VendoredFileSystem {
|
||||||
inner: VendoredFileSystemInner,
|
inner: Mutex<VendoredZipArchive>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VendoredFileSystem {
|
impl VendoredFileSystem {
|
||||||
pub fn new(raw_bytes: &'static [u8]) -> Result<Self> {
|
pub fn new(raw_bytes: &'static [u8]) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: VendoredFileSystemInner::new(raw_bytes)?,
|
inner: Mutex::new(VendoredZipArchive::new(raw_bytes)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exists(&self, path: &VendoredPath) -> bool {
|
pub fn exists(&self, path: &VendoredPath) -> bool {
|
||||||
let normalized = NormalizedVendoredPath::from(path);
|
let normalized = NormalizedVendoredPath::from(path);
|
||||||
let inner_locked = self.inner.lock();
|
let mut archive = self.lock_archive();
|
||||||
let mut archive = inner_locked.borrow_mut();
|
|
||||||
|
|
||||||
// Must probe the zipfile twice, as "stdlib" and "stdlib/" are considered
|
// Must probe the zipfile twice, as "stdlib" and "stdlib/" are considered
|
||||||
// different paths in a zip file, but we want to abstract over that difference here
|
// different paths in a zip file, but we want to abstract over that difference here
|
||||||
|
|
@ -47,13 +46,12 @@ impl VendoredFileSystem {
|
||||||
|
|
||||||
pub fn metadata(&self, path: &VendoredPath) -> Option<Metadata> {
|
pub fn metadata(&self, path: &VendoredPath) -> Option<Metadata> {
|
||||||
let normalized = NormalizedVendoredPath::from(path);
|
let normalized = NormalizedVendoredPath::from(path);
|
||||||
let inner_locked = self.inner.lock();
|
let mut archive = self.lock_archive();
|
||||||
|
|
||||||
// Must probe the zipfile twice, as "stdlib" and "stdlib/" are considered
|
// Must probe the zipfile twice, as "stdlib" and "stdlib/" are considered
|
||||||
// different paths in a zip file, but we want to abstract over that difference here
|
// different paths in a zip file, but we want to abstract over that difference here
|
||||||
// so that paths relative to the `VendoredFileSystem`
|
// so that paths relative to the `VendoredFileSystem`
|
||||||
// work the same as other paths in Ruff.
|
// work the same as other paths in Ruff.
|
||||||
let mut archive = inner_locked.borrow_mut();
|
|
||||||
if let Ok(zip_file) = archive.lookup_path(&normalized) {
|
if let Ok(zip_file) = archive.lookup_path(&normalized) {
|
||||||
return Some(Metadata::from_zip_file(zip_file));
|
return Some(Metadata::from_zip_file(zip_file));
|
||||||
}
|
}
|
||||||
|
|
@ -71,46 +69,45 @@ impl VendoredFileSystem {
|
||||||
/// - The path exists in the underlying zip archive, but represents a directory
|
/// - The path exists in the underlying zip archive, but represents a directory
|
||||||
/// - The contents of the zip file at `path` contain invalid UTF-8
|
/// - The contents of the zip file at `path` contain invalid UTF-8
|
||||||
pub fn read(&self, path: &VendoredPath) -> Result<String> {
|
pub fn read(&self, path: &VendoredPath) -> Result<String> {
|
||||||
let inner_locked = self.inner.lock();
|
let mut archive = self.lock_archive();
|
||||||
let mut archive = inner_locked.borrow_mut();
|
|
||||||
let mut zip_file = archive.lookup_path(&NormalizedVendoredPath::from(path))?;
|
let mut zip_file = archive.lookup_path(&NormalizedVendoredPath::from(path))?;
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
zip_file.read_to_string(&mut buffer)?;
|
zip_file.read_to_string(&mut buffer)?;
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Acquire a lock on the underlying zip archive.
|
||||||
|
/// The call will block until it is able to acquire the lock.
|
||||||
|
///
|
||||||
|
/// ## Panics:
|
||||||
|
/// If the current thread already holds the lock.
|
||||||
|
fn lock_archive(&self) -> LockedZipArchive {
|
||||||
|
self.inner.lock().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for VendoredFileSystem {
|
impl fmt::Debug for VendoredFileSystem {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let locked_inner = self.inner.lock();
|
let mut archive = self.lock_archive();
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
let mut paths: Vec<String> = locked_inner
|
let mut paths: Vec<String> = archive.0.file_names().map(String::from).collect();
|
||||||
.borrow()
|
|
||||||
.0
|
|
||||||
.file_names()
|
|
||||||
.map(String::from)
|
|
||||||
.collect();
|
|
||||||
paths.sort();
|
paths.sort();
|
||||||
let debug_info: BTreeMap<String, ZipFileDebugInfo> = paths
|
let debug_info: BTreeMap<String, ZipFileDebugInfo> = paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|path| {
|
.map(|path| {
|
||||||
(
|
(
|
||||||
path.to_owned(),
|
path.to_owned(),
|
||||||
ZipFileDebugInfo::from(locked_inner.borrow_mut().0.by_name(path).unwrap()),
|
ZipFileDebugInfo::from(archive.0.by_name(path).unwrap()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
f.debug_struct("VendoredFileSystem")
|
f.debug_struct("VendoredFileSystem")
|
||||||
.field("inner_mutex_poisoned", &self.inner.0.is_poisoned())
|
.field("inner_mutex_poisoned", &self.inner.is_poisoned())
|
||||||
.field("paths", &paths)
|
.field("paths", &paths)
|
||||||
.field("data_by_path", &debug_info)
|
.field("data_by_path", &debug_info)
|
||||||
.finish()
|
.finish()
|
||||||
} else {
|
} else {
|
||||||
write!(
|
write!(f, "VendoredFileSystem(<{} paths>)", archive.len())
|
||||||
f,
|
|
||||||
"VendoredFileSystem(<{} paths>)",
|
|
||||||
locked_inner.borrow().len()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -196,27 +193,6 @@ impl Metadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VendoredFileSystemInner(Mutex<RefCell<VendoredZipArchive>>);
|
|
||||||
|
|
||||||
type LockedZipArchive<'a> = MutexGuard<'a, RefCell<VendoredZipArchive>>;
|
|
||||||
|
|
||||||
impl VendoredFileSystemInner {
|
|
||||||
fn new(raw_bytes: &'static [u8]) -> Result<Self> {
|
|
||||||
Ok(Self(Mutex::new(RefCell::new(VendoredZipArchive::new(
|
|
||||||
raw_bytes,
|
|
||||||
)?))))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Acquire a lock on the underlying zip archive.
|
|
||||||
/// The call will block until it is able to acquire the lock.
|
|
||||||
///
|
|
||||||
/// ## Panics:
|
|
||||||
/// If the current thread already holds the lock.
|
|
||||||
fn lock(&self) -> LockedZipArchive {
|
|
||||||
self.0.lock().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Newtype wrapper around a ZipArchive.
|
/// Newtype wrapper around a ZipArchive.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct VendoredZipArchive(ZipArchive<io::Cursor<&'static [u8]>>);
|
struct VendoredZipArchive(ZipArchive<io::Cursor<&'static [u8]>>);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue