Fix tempdir rename (#94)

This fixes two bugs on linux:

`/tmp` and `$HOME` are technically on two different partitions on my
machine, which means that rename-as-atomic-dir-write doesn't work. The
solution is to create the temp dir in the target directory.

zip files may contain directory entries, we can't create files for them
but need to create directories. We could skip them though because iirc
they are not in the RECORD so they won't be uninstalled.
This commit is contained in:
konsti 2023-10-12 20:47:38 +02:00 committed by GitHub
parent 530edb6e39
commit de9e85978b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 6 deletions

View file

@ -4,29 +4,34 @@ static WHEEL_CACHE: &str = "wheels-v0";
#[derive(Debug)]
pub(crate) struct WheelCache {
path: PathBuf,
root: PathBuf,
}
impl WheelCache {
/// Create a handle to the wheel cache.
pub(crate) fn new(root: &Path) -> Self {
Self {
path: root.join(WHEEL_CACHE),
root: root.join(WHEEL_CACHE),
}
}
/// Return the path at which a given wheel would be stored.
pub(crate) fn entry(&self, id: &str) -> PathBuf {
self.path.join(id)
self.root.join(id)
}
/// Initialize the wheel cache.
pub(crate) async fn init(&self) -> std::io::Result<()> {
tokio::fs::create_dir_all(&self.path).await
tokio::fs::create_dir_all(&self.root).await
}
/// Returns a handle to the wheel cache directory.
pub(crate) async fn read_dir(&self) -> std::io::Result<tokio::fs::ReadDir> {
tokio::fs::read_dir(&self.path).await
tokio::fs::read_dir(&self.root).await
}
/// Returns the cache root.
pub(crate) fn root(&self) -> &Path {
&self.root
}
}

View file

@ -38,7 +38,7 @@ impl Unzipper {
let wheel_cache = WheelCache::new(target);
wheel_cache.init().await?;
let staging = tempfile::tempdir()?;
let staging = tempfile::tempdir_in(wheel_cache.root())?;
// Unpack the wheels into the cache.
let mut wheels = Vec::with_capacity(downloads.len());
@ -101,6 +101,10 @@ fn unzip_wheel(wheel: InMemoryDistribution, target: &Path) -> Result<()> {
// Create necessary parent directories.
let path = target.join(file_path);
if file.is_dir() {
std::fs::create_dir_all(path)?;
return Ok(());
}
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}