From 150970b56f912522c7b6adfd16113ef8d365b1e3 Mon Sep 17 00:00:00 2001 From: pax Date: Thu, 9 Apr 2026 17:32:28 -0500 Subject: [PATCH] cache: delete_from_library cleans up library_meta + matches templated names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two related fixes that the old delete flow was missing: 1. delete_from_library now accepts an optional `db` parameter which it forwards to find_library_files. Without `db`, only digit-stem files match (the old behavior — preserved as a fallback). With `db`, templated filenames stored in library_meta also match, so post-refactor saves like 12345_hatsune_miku.jpg get unlinked too. Without this fix, "Unsave from Library" on a templated save was a silent no-op. 2. Always cleans up the library_meta row when called with `db`, not just when files were unlinked. Two cases this matters for: a. Files were on disk and unlinked → meta is now stale. b. Files were already gone but the meta lingered (orphan from a previous broken delete) → user asked to "unsave," meta should reflect that. This is the missing half of the cleanup that left some libraries with pathologically more meta rows than actual files. --- booru_viewer/core/cache.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/booru_viewer/core/cache.py b/booru_viewer/core/cache.py index 516828e..02489e6 100644 --- a/booru_viewer/core/cache.py +++ b/booru_viewer/core/cache.py @@ -434,7 +434,7 @@ def is_cached(url: str, dest_dir: Path | None = None) -> bool: return cached_path_for(url, dest_dir).exists() -def delete_from_library(post_id: int, folder: str | None = None) -> bool: +def delete_from_library(post_id: int, folder: str | None = None, db=None) -> bool: """Delete every saved copy of `post_id` from the library. Returns True if at least one file was deleted. @@ -445,9 +445,16 @@ def delete_from_library(post_id: int, folder: str | None = None) -> bool: separation work: a bookmark no longer needs to know which folder its library file lives in. It also cleans up duplicates left by the old pre-fix "save to folder = copy" bug in a single Unsave action. + + Pass `db` to also match templated filenames (post-refactor saves + that aren't named {post_id}.{ext}) and to clean up the library_meta + row in the same call. Without `db`, only digit-stem files are + found and the meta row stays — that's the old broken behavior, + preserved as a fallback for callers that don't have a Database + handle. """ from .config import find_library_files - matches = find_library_files(post_id) + matches = find_library_files(post_id, db=db) deleted = False for path in matches: try: @@ -455,6 +462,22 @@ def delete_from_library(post_id: int, folder: str | None = None) -> bool: deleted = True except OSError: pass + # Always drop the meta row, even when no files were unlinked. + # Two cases this matters for: + # 1. Files were on disk and unlinked — meta row is now stale. + # 2. Files were already gone (orphan meta row from a previous + # delete that didn't clean up). The user asked to "unsave" + # this post and the meta should reflect that, even if + # there's nothing left on disk. + # Without this cleanup the post stays "saved" in the DB and + # is_post_in_library lies forever. The lookup is keyed by + # post_id so this is one cheap DELETE regardless of how many + # copies were on disk. + if db is not None: + try: + db.remove_library_meta(post_id) + except Exception: + pass return deleted