mirror of https://github.com/astral-sh/uv
Remove dangling archives in `uv cache clean ${package}` (#6915)
## Summary Closes https://github.com/astral-sh/uv/issues/6909.
This commit is contained in:
parent
a5f1e1c765
commit
049c73d09e
|
|
@ -322,10 +322,62 @@ impl Cache {
|
||||||
///
|
///
|
||||||
/// Returns the number of entries removed from the cache.
|
/// Returns the number of entries removed from the cache.
|
||||||
pub fn remove(&self, name: &PackageName) -> Result<Removal, io::Error> {
|
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();
|
let mut summary = Removal::default();
|
||||||
for bucket in CacheBucket::iter() {
|
for bucket in CacheBucket::iter() {
|
||||||
summary += bucket.remove(self, name)?;
|
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)
|
Ok(summary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,14 +65,27 @@ fn clean_package_pypi() -> Result<()> {
|
||||||
"Expected the `.rkyv` file to exist for `iniconfig`"
|
"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
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
DEBUG uv [VERSION] ([COMMIT] DATE)
|
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`.
|
// Assert that the `.rkyv` file is removed for `iniconfig`.
|
||||||
|
|
@ -81,6 +94,18 @@ fn clean_package_pypi() -> Result<()> {
|
||||||
"Expected the `.rkyv` file to be removed for `iniconfig`"
|
"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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,14 +138,27 @@ fn clean_package_index() -> Result<()> {
|
||||||
"Expected the `.rkyv` file to exist for `iniconfig`"
|
"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
|
success: true
|
||||||
exit_code: 0
|
exit_code: 0
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
DEBUG uv [VERSION] ([COMMIT] DATE)
|
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`.
|
// Assert that the `.rkyv` file is removed for `iniconfig`.
|
||||||
|
|
|
||||||
|
|
@ -1396,7 +1396,7 @@ fn install_url_source_dist_cached() -> Result<()> {
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Removed 13 files for source-distribution ([SIZE])
|
Removed 19 files for source-distribution ([SIZE])
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1591,7 +1591,7 @@ fn install_registry_source_dist_cached() -> Result<()> {
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Removed 14 files for source-distribution ([SIZE])
|
Removed 20 files for source-distribution ([SIZE])
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1687,7 +1687,7 @@ fn install_path_source_dist_cached() -> Result<()> {
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Removed 13 files for source-distribution ([SIZE])
|
Removed 19 files for source-distribution ([SIZE])
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1788,7 +1788,7 @@ fn install_path_built_dist_cached() -> Result<()> {
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Removed 2 files for tomli ([SIZE])
|
Removed 11 files for tomli ([SIZE])
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1876,7 +1876,7 @@ fn install_url_built_dist_cached() -> Result<()> {
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
Removed 3 files for tqdm ([SIZE])
|
Removed 43 files for tqdm ([SIZE])
|
||||||
"###
|
"###
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue