mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 19:08:04 +00:00
Store IDs rather than paths in the cache (#2985)
## Summary Similar to `Revision`, we now store IDs in the `Archive` entires rather than absolute paths. This makes the cache robust to moves, etc. Closes https://github.com/astral-sh/uv/issues/2908.
This commit is contained in:
parent
c294c7098f
commit
32f129c245
8 changed files with 107 additions and 64 deletions
24
crates/uv-cache/src/archive.rs
Normal file
24
crates/uv-cache/src/archive.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use std::path::Path;
|
||||
|
||||
/// A unique identifier for an archive (unzipped wheel) in the cache.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ArchiveId(String);
|
||||
|
||||
impl Default for ArchiveId {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ArchiveId {
|
||||
/// Generate a new unique identifier for an archive.
|
||||
pub fn new() -> Self {
|
||||
Self(nanoid::nanoid!())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for ArchiveId {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
|
@ -23,7 +23,9 @@ use crate::removal::{rm_rf, Removal};
|
|||
pub use crate::timestamp::Timestamp;
|
||||
pub use crate::wheel::WheelCache;
|
||||
use crate::wheel::WheelCacheKind;
|
||||
pub use archive::ArchiveId;
|
||||
|
||||
mod archive;
|
||||
mod by_timestamp;
|
||||
#[cfg(feature = "clap")]
|
||||
mod cli;
|
||||
|
@ -173,6 +175,11 @@ impl Cache {
|
|||
CacheEntry::new(self.bucket(cache_bucket).join(dir), file)
|
||||
}
|
||||
|
||||
/// Return the path to an archive in the cache.
|
||||
pub fn archive(&self, id: &ArchiveId) -> PathBuf {
|
||||
self.bucket(CacheBucket::Archive).join(id)
|
||||
}
|
||||
|
||||
/// Returns `true` if a cache entry must be revalidated given the [`Refresh`] policy.
|
||||
pub fn must_revalidate(&self, package: &PackageName) -> bool {
|
||||
match &self.refresh {
|
||||
|
@ -214,18 +221,18 @@ impl Cache {
|
|||
}
|
||||
}
|
||||
|
||||
/// Persist a temporary directory to the artifact store.
|
||||
/// Persist a temporary directory to the artifact store, returning its unique ID.
|
||||
pub async fn persist(
|
||||
&self,
|
||||
temp_dir: impl AsRef<Path>,
|
||||
path: impl AsRef<Path>,
|
||||
) -> io::Result<PathBuf> {
|
||||
) -> io::Result<ArchiveId> {
|
||||
// Create a unique ID for the artifact.
|
||||
// TODO(charlie): Support content-addressed persistence via SHAs.
|
||||
let id = nanoid::nanoid!();
|
||||
let id = ArchiveId::new();
|
||||
|
||||
// Move the temporary directory into the directory store.
|
||||
let archive_entry = self.entry(CacheBucket::Archive, "", id);
|
||||
let archive_entry = self.entry(CacheBucket::Archive, "", &id);
|
||||
fs_err::create_dir_all(archive_entry.dir())?;
|
||||
uv_fs::rename_with_retry(temp_dir.as_ref(), archive_entry.path()).await?;
|
||||
|
||||
|
@ -233,7 +240,7 @@ impl Cache {
|
|||
fs_err::create_dir_all(path.as_ref().parent().expect("Cache entry to have parent"))?;
|
||||
uv_fs::replace_symlink(archive_entry.path(), path.as_ref())?;
|
||||
|
||||
Ok(archive_entry.into_path_buf())
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Initialize a directory for use as a cache.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue