Skip to content

Commit

Permalink
Remove dangling archives in uv cache clean
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Sep 1, 2024
1 parent a5f1e1c commit d333eff
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 4 deletions.
52 changes: 52 additions & 0 deletions crates/uv-cache/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,62 @@ impl Cache {
///
/// Returns the number of entries removed from the cache.
pub fn remove(&self, name: &PackageName) -> Result<Removal, io::Error> {
// Collect the set of referenced archives.
let before = {
let mut references = FxHashSet::default();
for bucket in CacheBucket::iter() {
let bucket = self.bucket(bucket);
if bucket.is_dir() {
for entry in walkdir::WalkDir::new(bucket) {
let entry = entry?;
if entry.file_type().is_symlink() {
if let Ok(target) = fs_err::canonicalize(entry.path()) {
references.insert(target);
}
}
}
}
}
references
};

// Remove any entries for the package from the cache.
let mut summary = Removal::default();
for bucket in CacheBucket::iter() {
summary += bucket.remove(self, name)?;
}

// Collect the set of referenced archives after the removal.
let after = {
let mut references = FxHashSet::default();
for bucket in CacheBucket::iter() {
let bucket = self.bucket(bucket);
if bucket.is_dir() {
for entry in walkdir::WalkDir::new(bucket) {
let entry = entry?;
if entry.file_type().is_symlink() {
if let Ok(target) = fs_err::canonicalize(entry.path()) {
references.insert(target);
}
}
}
}
}
references
};

if before != after {
// Remove any archives that are no longer referenced.
for entry in fs::read_dir(self.bucket(CacheBucket::Archive))? {
let entry = entry?;
let path = fs_err::canonicalize(entry.path())?;
if !after.contains(&path) && before.contains(&path) {
debug!("Removing dangling cache entry: {}", path.display());
summary += rm_rf(path)?;
}
}
}

Ok(summary)
}

Expand Down
46 changes: 42 additions & 4 deletions crates/uv/tests/cache_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,27 @@ fn clean_package_pypi() -> Result<()> {
"Expected the `.rkyv` file to exist for `iniconfig`"
);

uv_snapshot!(context.filters(), context.clean().arg("--verbose").arg("iniconfig"), @r###"
let filters: Vec<_> = context
.filters()
.into_iter()
.chain([
// The cache entry does not have a stable key, so we filter it out
(
r"\[CACHE_DIR\](\\|\/)(.+)(\\|\/).*",
"[CACHE_DIR]/$2/[ENTRY]",
),
])
.collect();

uv_snapshot!(&filters, context.clean().arg("--verbose").arg("iniconfig"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
DEBUG uv [VERSION] ([COMMIT] DATE)
Removed 4 files for iniconfig ([SIZE])
DEBUG Removing dangling cache entry: [CACHE_DIR]/archive-v0/[ENTRY]
Removed 13 files for iniconfig ([SIZE])
"###);

// Assert that the `.rkyv` file is removed for `iniconfig`.
Expand All @@ -81,6 +94,18 @@ fn clean_package_pypi() -> Result<()> {
"Expected the `.rkyv` file to be removed for `iniconfig`"
);

// Running `uv cache prune` should have no effect.
uv_snapshot!(&filters, context.prune().arg("--verbose"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
DEBUG uv [VERSION] ([COMMIT] DATE)
Pruning cache at: [CACHE_DIR]/
No unused entries found
"###);

Ok(())
}

Expand Down Expand Up @@ -113,14 +138,27 @@ fn clean_package_index() -> Result<()> {
"Expected the `.rkyv` file to exist for `iniconfig`"
);

uv_snapshot!(context.filters(), context.clean().arg("--verbose").arg("iniconfig"), @r###"
let filters: Vec<_> = context
.filters()
.into_iter()
.chain([
// The cache entry does not have a stable key, so we filter it out
(
r"\[CACHE_DIR\](\\|\/)(.+)(\\|\/).*",
"[CACHE_DIR]/$2/[ENTRY]",
),
])
.collect();

uv_snapshot!(&filters, context.clean().arg("--verbose").arg("iniconfig"), @r###"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
DEBUG uv [VERSION] ([COMMIT] DATE)
Removed 4 files for iniconfig ([SIZE])
DEBUG Removing dangling cache entry: [CACHE_DIR]/archive-v0/[ENTRY]
Removed 13 files for iniconfig ([SIZE])
"###);

// Assert that the `.rkyv` file is removed for `iniconfig`.
Expand Down

0 comments on commit d333eff

Please sign in to comment.