Skip to main content

hf_hub/cache/
mod.rs

1//! Inspect the local Hugging Face cache.
2//!
3//! [`HFClient::scan_cache`] walks the cache directory and produces an
4//! [`HFCacheInfo`] tree: cached repositories, their revisions, and the
5//! individual files in each revision.
6//!
7//! On disk, downloads are content-addressed — files in
8//! `<cache>/<repo_folder>/snapshots/<commit>/<filename>` are pointers (symlinks
9//! on Unix, copies on Windows) to immutable blobs in
10//! `<cache>/<repo_folder>/blobs/<etag>`. Multiple revisions of the same repo
11//! often share the same blob, which is why repo-level sizes are deduplicated
12//! while revision-level sizes are not — see [`CachedRepoInfo::size_on_disk`]
13//! and [`CachedRevisionInfo::size_on_disk`].
14
15use std::path::PathBuf;
16use std::time::SystemTime;
17
18use bon::bon;
19
20use crate::client::HFClient;
21use crate::error::HFResult;
22
23pub(crate) mod storage;
24
25/// A single file in a cached revision.
26///
27/// `file_path` is the pointer in the `snapshots/` tree (a symlink on Unix);
28/// `blob_path` is the canonical location of the underlying content under
29/// `blobs/`. Both paths refer to the same bytes.
30#[derive(Debug, Clone)]
31pub struct CachedFileInfo {
32    /// Path of the file relative to its revision's snapshot root, including
33    /// any subdirectories (e.g., `subdir/model.bin`).
34    pub file_name: String,
35    /// Absolute path of the pointer file inside the `snapshots/` tree.
36    /// Symlink on Unix, regular file (a copy of the blob) on Windows.
37    pub file_path: PathBuf,
38    /// Absolute path of the actual blob under `blobs/`, after resolving
39    /// `file_path`. Multiple revisions can point at the same blob.
40    pub blob_path: PathBuf,
41    /// Size of the blob in bytes.
42    pub size_on_disk: u64,
43    /// Last access time of the blob, from the filesystem.
44    pub blob_last_accessed: SystemTime,
45    /// Last modification time of the blob, from the filesystem.
46    pub blob_last_modified: SystemTime,
47}
48
49/// A cached revision (commit) of a repository.
50#[derive(Debug, Clone)]
51pub struct CachedRevisionInfo {
52    /// Full 40-character commit SHA.
53    pub commit_hash: String,
54    /// Directory of pointer files for this revision
55    /// (`<cache>/<repo_folder>/snapshots/<commit_hash>/`).
56    pub snapshot_path: PathBuf,
57    /// Files belonging to this revision.
58    pub files: Vec<CachedFileInfo>,
59    /// Sum of [`CachedFileInfo::size_on_disk`] for every file in this
60    /// revision. Blobs shared with other revisions of the same repo are
61    /// counted here but not in [`CachedRepoInfo::size_on_disk`].
62    pub size_on_disk: u64,
63    /// Refs (branches, tags, `refs/pr/<n>`, …) that point at this commit.
64    /// May be empty for revisions only reachable by SHA.
65    pub refs: Vec<String>,
66    /// Latest blob modification time across the files in this revision.
67    pub last_modified: SystemTime,
68}
69
70/// A cached repository, with its revisions aggregated.
71#[derive(Debug, Clone)]
72pub struct CachedRepoInfo {
73    /// Hub repo identifier (e.g., `gpt2`, `google/bert-base-uncased`).
74    pub repo_id: String,
75    /// Lowercase singular name of the repo kind (`"model"`, `"dataset"`, `"space"`, or `"kernel"`)
76    /// — see [`crate::repository::RepoType::singular`].
77    pub repo_type: &'static str,
78    /// Absolute path of the repo's cache subfolder
79    /// (`<cache>/<type>s--<owner>--<name>/`).
80    pub repo_path: PathBuf,
81    /// Cached revisions of this repo.
82    pub revisions: Vec<CachedRevisionInfo>,
83    /// Number of unique blobs stored for this repo. Two revisions sharing the
84    /// same blob count once.
85    pub nb_files: usize,
86    /// Bytes used on disk for unique blobs, with shared blobs counted once.
87    pub size_on_disk: u64,
88    /// Latest blob access time across all revisions.
89    pub last_accessed: SystemTime,
90    /// Latest blob modification time across all revisions.
91    pub last_modified: SystemTime,
92}
93
94/// Snapshot of the local Hugging Face cache directory.
95///
96/// Returned by [`HFClient::scan_cache`]; aggregates every cached repository
97/// found at `cache_dir` along with total disk usage and any warnings emitted
98/// during scanning.
99#[derive(Debug, Clone)]
100pub struct HFCacheInfo {
101    /// Cache directory that was scanned.
102    pub cache_dir: PathBuf,
103    /// Cached repositories discovered under `cache_dir`.
104    pub repos: Vec<CachedRepoInfo>,
105    /// Sum of [`CachedRepoInfo::size_on_disk`] across all repos.
106    pub size_on_disk: u64,
107    /// Human-readable warnings for entries that could not be fully scanned —
108    /// for example, snapshot pointers whose blobs are missing or unreadable.
109    pub warnings: Vec<String>,
110}
111
112#[bon]
113impl HFClient {
114    /// Scan the configured cache directory and return a summary of all cached repositories,
115    /// revisions, and files.
116    ///
117    /// If the cache directory does not exist, returns an [`HFCacheInfo`] with no repos and zero
118    /// size — not an error. Unreadable blobs and dangling snapshot pointers are reported via
119    /// [`HFCacheInfo::warnings`] rather than failing the scan.
120    #[builder(finish_fn = send, derive(Debug, Clone))]
121    pub async fn scan_cache(&self) -> HFResult<HFCacheInfo> {
122        storage::scan_cache_dir(self.cache_dir()).await
123    }
124}
125
126#[cfg(feature = "blocking")]
127#[bon]
128impl crate::blocking::HFClientSync {
129    /// Blocking counterpart of [`HFClient::scan_cache`].
130    #[builder(finish_fn = send, derive(Debug, Clone))]
131    pub fn scan_cache(&self) -> HFResult<HFCacheInfo> {
132        self.runtime.block_on(self.inner.scan_cache().send())
133    }
134}