commit 28af9c22720183179f5907ac421a79d3cf04b3b4
parent f050de6b7a6e2fc8b95bad571c536ea6e3165893
Author: William Casarin <jb55@jb55.com>
Date: Fri, 10 Jan 2025 07:13:29 -0800
Merge 'image-cache: use sha256 hash of url for key'
Link: https://github.com/damus-io/notedeck/pull/631
Diffstat:
5 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -2505,6 +2505,7 @@ dependencies = [
"security-framework",
"serde",
"serde_json",
+ "sha2",
"strum",
"strum_macros",
"tempfile",
diff --git a/Cargo.toml b/Cargo.toml
@@ -52,6 +52,7 @@ url = "2.5.2"
urlencoding = "2.1.3"
uuid = { version = "1.10.0", features = ["v4"] }
security-framework = "2.11.0"
+sha2 = "0.10.8"
[profile.small]
inherits = 'release'
diff --git a/crates/notedeck/Cargo.toml b/crates/notedeck/Cargo.toml
@@ -22,6 +22,7 @@ serde = { workspace = true }
hex = { workspace = true }
thiserror = { workspace = true }
puffin = { workspace = true, optional = true }
+sha2 = { workspace = true }
[dev-dependencies]
tempfile = { workspace = true }
diff --git a/crates/notedeck/src/imgcache.rs b/crates/notedeck/src/imgcache.rs
@@ -5,9 +5,13 @@ use poll_promise::Promise;
use egui::ColorImage;
use std::collections::HashMap;
-use std::fs::File;
+use std::fs::{create_dir_all, File};
+use hex::ToHex;
+use sha2::Digest;
use std::path;
+use std::path::PathBuf;
+use tracing::warn;
pub type ImageCacheValue = Promise<Result<TextureHandle>>;
pub type ImageCacheMap = HashMap<String, ImageCacheValue>;
@@ -46,6 +50,9 @@ impl ImageCache {
pub fn write(cache_dir: &path::Path, url: &str, data: ColorImage) -> Result<()> {
let file_path = cache_dir.join(Self::key(url));
+ if let Some(p) = file_path.parent() {
+ create_dir_all(p)?;
+ }
let file = File::options()
.write(true)
.create(true)
@@ -64,7 +71,51 @@ impl ImageCache {
}
pub fn key(url: &str) -> String {
- base32::encode(base32::Alphabet::Crockford, url.as_bytes())
+ let k: String = sha2::Sha256::digest(url.as_bytes()).encode_hex();
+ PathBuf::from(&k[0..2])
+ .join(&k[2..4])
+ .join(k)
+ .to_string_lossy()
+ .to_string()
+ }
+
+ /// Migrate from base32 encoded url to sha256 url + sub-dir structure
+ pub fn migrate_v0(&self) -> Result<()> {
+ for file in std::fs::read_dir(&self.cache_dir)? {
+ let file = if let Ok(f) = file {
+ f
+ } else {
+ // not sure how this could fail, skip entry
+ continue;
+ };
+ if !file.path().is_file() {
+ continue;
+ }
+ let old_filename = file.file_name().to_string_lossy().to_string();
+ let old_url = if let Some(u) =
+ base32::decode(base32::Alphabet::Crockford, &old_filename)
+ .and_then(|s| String::from_utf8(s).ok())
+ {
+ u
+ } else {
+ warn!("Invalid base32 filename: {}", &old_filename);
+ continue;
+ };
+ let new_path = self.cache_dir.join(Self::key(&old_url));
+ if let Some(p) = new_path.parent() {
+ create_dir_all(p)?;
+ }
+
+ if let Err(e) = std::fs::rename(file.path(), &new_path) {
+ warn!(
+ "Failed to migrate file from {} to {}: {:?}",
+ file.path().display(),
+ new_path.display(),
+ e
+ );
+ }
+ }
+ Ok(())
}
pub fn map(&self) -> &ImageCacheMap {
diff --git a/crates/notedeck_chrome/src/app.rs b/crates/notedeck_chrome/src/app.rs
@@ -207,6 +207,11 @@ impl Notedeck {
let tabs = Tabs::new(None);
let app_rect_handler = AppSizeHandler::new(&path);
+ // migrate
+ if let Err(e) = img_cache.migrate_v0() {
+ error!("error migrating image cache: {e}");
+ }
+
Self {
ndb,
img_cache,