From ecc872a1fd43c0863e3171a1faf533adc3e3a4c5 Mon Sep 17 00:00:00 2001 From: Ken D'Ambrosio Date: Mon, 8 Jun 2026 17:37:06 +0000 Subject: Add progress counter and faces-pending sentinel bypass to update.rb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - process_dir() takes idx/total args and prints [N/total] prefix on every Scanning/Skipping line so long runs are easy to monitor via tail -f - faces_pending?() checks album.json for any image with faces: null when faces.enabled is true; if found, the sentinel skip is bypassed so those images get processed even though the directory mtime hasn't changed - This handles the case where face detection is newly enabled on a library that was previously indexed without it — no --force needed on subsequent runs after the initial catch-up Resume after abort: sentinel is only touched after atomic_write_json, so an aborted directory reruns cleanly. Already-completed directories skip normally; partially-detected batches rerun from scratch (safe/idempotent). Co-Authored-By: Claude Sonnet 4.6 --- scripts/update.rb | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/update.rb b/scripts/update.rb index 1a00ddf..5671330 100644 --- a/scripts/update.rb +++ b/scripts/update.rb @@ -51,15 +51,20 @@ def process_dir(dir, idx, total) label = rel.empty? ? '(root)' : rel prefix = "[#{idx}/#{total}]" + pending_faces = false unless FORCE_UPDATE sentinel = File.join(dir, SENTINEL_FILE) if File.exist?(sentinel) && File.mtime(sentinel) >= File.mtime(dir) - puts "#{prefix} Skipping #{label} (unchanged)" - return + if faces_pending?(dir) + pending_faces = true # fall through, but only to run face detection + else + puts "#{prefix} Skipping #{label} (unchanged)" + return + end end end - puts "#{prefix} Scanning #{label}" + puts "#{prefix} Scanning #{label}#{' (face detection pending)' if pending_faces}" json_path = File.join(dir, 'album.json') data = load_json(json_path) @@ -290,6 +295,16 @@ rescue JSON::ParserError => e {} end +def faces_pending?(dir) + return false unless FACES_ENABLED + json_path = File.join(dir, 'album.json') + return false unless File.exist?(json_path) + (load_json(json_path)['files'] || {}).any? do |name, meta| + IMAGE_EXTS.include?(File.extname(name).downcase.delete_prefix('.')) && + meta['faces'].nil? + end +end + # Fields the admin controls — never overwrite with stale values from our earlier read. ADMIN_ALBUM_KEYS = %w[title description cover cover_dynamic sort_reverse visible].freeze ADMIN_FILE_KEYS = %w[title caption visible].freeze -- cgit v1.2.3