mirror of
https://github.com/astral-sh/uv.git
synced 2025-08-04 02:48:17 +00:00
Add CACHEDIR and .gitignore tags to cache directories (#526)
## Summary Even if this will typically be in the user's application folder (rather than a local directory), it's still a good practice. Closes https://github.com/astral-sh/puffin/issues/280.
This commit is contained in:
parent
9806901a16
commit
ee2fca3a48
6 changed files with 49 additions and 18 deletions
|
@ -16,6 +16,7 @@ workspace = true
|
|||
[dependencies]
|
||||
pypi-types = { path = "../pypi-types" }
|
||||
|
||||
cachedir = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"], optional = true }
|
||||
directories = { workspace = true }
|
||||
fs-err = { workspace = true }
|
||||
|
|
|
@ -5,7 +5,6 @@ use std::path::PathBuf;
|
|||
|
||||
use clap::Parser;
|
||||
use directories::ProjectDirs;
|
||||
use fs_err as fs;
|
||||
|
||||
use crate::Cache;
|
||||
|
||||
|
@ -31,18 +30,14 @@ impl TryFrom<CacheArgs> for Cache {
|
|||
///
|
||||
/// Returns an absolute cache dir.
|
||||
fn try_from(value: CacheArgs) -> Result<Self, Self::Error> {
|
||||
let project_dirs = ProjectDirs::from("", "", "puffin");
|
||||
if value.no_cache {
|
||||
Ok(Cache::temp()?)
|
||||
Cache::temp()
|
||||
} else if let Some(cache_dir) = value.cache_dir {
|
||||
fs::create_dir_all(&cache_dir)?;
|
||||
Ok(Cache::from_path(fs::canonicalize(cache_dir)?))
|
||||
} else if let Some(project_dirs) = project_dirs {
|
||||
Ok(Cache::from_path(project_dirs.cache_dir().to_path_buf()))
|
||||
Cache::from_path(cache_dir)
|
||||
} else if let Some(project_dirs) = ProjectDirs::from("", "", "puffin") {
|
||||
Cache::from_path(project_dirs.cache_dir())
|
||||
} else {
|
||||
let cache_dir = ".puffin_cache";
|
||||
fs::create_dir_all(cache_dir)?;
|
||||
Ok(Cache::from_path(fs::canonicalize(cache_dir)?))
|
||||
Cache::from_path(".puffin_cache")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use fs_err as fs;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
|
||||
pub use canonical_url::{CanonicalUrl, RepositoryUrl};
|
||||
|
@ -47,22 +49,23 @@ pub struct Cache {
|
|||
|
||||
impl Cache {
|
||||
/// A persistent cache directory at `root`.
|
||||
pub fn from_path(root: impl Into<PathBuf>) -> Self {
|
||||
Self {
|
||||
root: root.into(),
|
||||
pub fn from_path(root: impl Into<PathBuf>) -> Result<Self, io::Error> {
|
||||
Ok(Self {
|
||||
root: Self::init(root)?,
|
||||
_temp_dir_drop: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a temporary cache directory.
|
||||
pub fn temp() -> Result<Self, io::Error> {
|
||||
let temp_dir = tempdir()?;
|
||||
Ok(Self {
|
||||
root: temp_dir.path().to_path_buf(),
|
||||
root: Self::init(temp_dir.path())?,
|
||||
_temp_dir_drop: Some(Arc::new(temp_dir)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Return the root of the cache.
|
||||
pub fn root(&self) -> &Path {
|
||||
&self.root
|
||||
}
|
||||
|
@ -72,6 +75,7 @@ impl Cache {
|
|||
self.root.join(cache_bucket.to_str())
|
||||
}
|
||||
|
||||
/// Compute an entry in the cache.
|
||||
pub fn entry(
|
||||
&self,
|
||||
cache_bucket: CacheBucket,
|
||||
|
@ -83,10 +87,30 @@ impl Cache {
|
|||
file,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize a directory for use as a cache.
|
||||
fn init(root: impl Into<PathBuf>) -> Result<PathBuf, io::Error> {
|
||||
let root = root.into();
|
||||
|
||||
// Create the cache directory, if it doesn't exist.
|
||||
fs::create_dir_all(&root)?;
|
||||
|
||||
// Add the CACHEDIR.TAG.
|
||||
cachedir::ensure_tag(&root)?;
|
||||
|
||||
// Add the .gitignore.
|
||||
let gitignore_path = root.join(".gitignore");
|
||||
if !gitignore_path.exists() {
|
||||
let mut file = fs::File::create(gitignore_path)?;
|
||||
file.write_all(b"*")?;
|
||||
}
|
||||
|
||||
fs::canonicalize(root)
|
||||
}
|
||||
}
|
||||
|
||||
/// The different kinds of data in the cache are stored in different bucket, which in our case
|
||||
/// are subfolders.
|
||||
/// are subdirectories of the cache root.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub enum CacheBucket {
|
||||
/// Wheels (excluding built wheels), their metadata and cache policy.
|
||||
|
|
|
@ -185,13 +185,13 @@ pub(crate) async fn sync_requirements(
|
|||
.await
|
||||
.context("Failed to download distributions")?;
|
||||
|
||||
let download_s = if wheels.len() == 1 { "" } else { "s" };
|
||||
let s = if wheels.len() == 1 { "" } else { "s" };
|
||||
writeln!(
|
||||
printer,
|
||||
"{}",
|
||||
format!(
|
||||
"Downloaded {} in {}",
|
||||
format!("{} package{}", wheels.len(), download_s).bold(),
|
||||
format!("{} package{}", wheels.len(), s).bold(),
|
||||
elapsed(start.elapsed())
|
||||
)
|
||||
.dimmed()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue