diff --git a/src/cargo/sources/registry/index/cache.rs b/src/cargo/sources/registry/index/cache.rs index 5d3bb28500a..f6e7d96ba6a 100644 --- a/src/cargo/sources/registry/index/cache.rs +++ b/src/cargo/sources/registry/index/cache.rs @@ -65,6 +65,7 @@ //! [`IndexSummary::parse`]: super::IndexSummary::parse //! [`RemoteRegistry`]: crate::sources::registry::remote::RemoteRegistry +use std::cell::RefCell; use std::fs; use std::io; use std::path::PathBuf; @@ -226,6 +227,9 @@ pub struct CacheManager<'gctx> { cache_root: Filesystem, /// [`GlobalContext`] reference for convenience. gctx: &'gctx GlobalContext, + /// Keeps track of if we have sent a warning message if there was an error updating the cache. + /// The motivation is to avoid warning spam if the cache is not writable. + has_warned: RefCell, } impl<'gctx> CacheManager<'gctx> { @@ -233,7 +237,11 @@ impl<'gctx> CacheManager<'gctx> { /// /// `root` --- The root path where caches are located. pub fn new(cache_root: Filesystem, gctx: &'gctx GlobalContext) -> CacheManager<'gctx> { - CacheManager { cache_root, gctx } + CacheManager { + cache_root, + gctx, + has_warned: Default::default(), + } } /// Gets the cache associated with the key. @@ -251,16 +259,28 @@ impl<'gctx> CacheManager<'gctx> { /// Associates the value with the key. pub fn put(&self, key: &str, value: &[u8]) { let cache_path = &self.cache_path(key); - if fs::create_dir_all(cache_path.parent().unwrap()).is_ok() { - let path = Filesystem::new(cache_path.clone()); - self.gctx - .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path); - if let Err(e) = fs::write(cache_path, value) { - tracing::info!(?cache_path, "failed to write cache: {e}"); + if let Err(e) = self.put_inner(cache_path, value) { + tracing::info!(?cache_path, "failed to write cache: {e}"); + + if !*self.has_warned.borrow() { + let _ = self.gctx.shell().warn(format!( + "failed to write cache, path: {}, error: {e}", + cache_path.to_str().unwrap_or_default() + )); + *self.has_warned.borrow_mut() = true; } } } + fn put_inner(&self, cache_path: &PathBuf, value: &[u8]) -> std::io::Result<()> { + fs::create_dir_all(cache_path.parent().unwrap())?; + let path = Filesystem::new(cache_path.clone()); + self.gctx + .assert_package_cache_locked(CacheLockMode::DownloadExclusive, &path); + fs::write(cache_path, value)?; + Ok(()) + } + /// Invalidates the cache associated with the key. pub fn invalidate(&self, key: &str) { let cache_path = &self.cache_path(key);