This commit is contained in:
nose
2025-12-13 12:09:50 -08:00
parent 30eb628aa3
commit 52a79b0086
16 changed files with 729 additions and 655 deletions

View File

@@ -34,6 +34,8 @@ class Folder(Store):
""""""
# Track which locations have already been migrated to avoid repeated migrations
_migrated_locations = set()
# Cache scan results to avoid repeated full scans across repeated instantiations
_scan_cache: Dict[str, Tuple[bool, str, Dict[str, int]]] = {}
def __new__(cls, *args: Any, **kwargs: Any) -> "Folder":
return super().__new__(cls)
@@ -55,10 +57,16 @@ class Folder(Store):
self._location = location
self._name = name
# Scan status (set during init)
self.scan_ok: bool = True
self.scan_detail: str = ""
self.scan_stats: Dict[str, int] = {}
if self._location:
try:
from API.folder import API_folder_store
from API.folder import LocalLibraryInitializer
from pathlib import Path
location_path = Path(self._location).expanduser()
@@ -69,6 +77,29 @@ class Folder(Store):
# Call migration and discovery at startup
Folder.migrate_location(self._location)
# Local library scan/index (one-time per location per process)
location_key = str(location_path)
cached = Folder._scan_cache.get(location_key)
if cached is None:
try:
initializer = LocalLibraryInitializer(location_path)
stats = initializer.scan_and_index() or {}
files_new = int(stats.get('files_new', 0) or 0)
sidecars = int(stats.get('sidecars_imported', 0) or 0)
total_db = int(stats.get('files_total_db', 0) or 0)
if files_new > 0 or sidecars > 0:
detail = f"New: {files_new}, Sidecars: {sidecars}" + (f" (Total: {total_db})" if total_db else "")
else:
detail = ("Up to date" + (f" (Total: {total_db})" if total_db else ""))
Folder._scan_cache[location_key] = (True, detail, dict(stats))
except Exception as exc:
Folder._scan_cache[location_key] = (False, f"Scan failed: {exc}", {})
ok, detail, stats = Folder._scan_cache.get(location_key, (True, "", {}))
self.scan_ok = bool(ok)
self.scan_detail = str(detail or "")
self.scan_stats = dict(stats or {})
except Exception as exc:
debug(f"Failed to initialize database for '{name}': {exc}")
@@ -87,12 +118,11 @@ class Folder(Store):
return
cls._migrated_locations.add(location_str)
# Create a temporary instance just to call the migration
temp_instance = cls(location=location)
temp_instance._migrate_to_hash_storage(location_path)
def _migrate_to_hash_storage(self, location_path: Path) -> None:
cls._migrate_to_hash_storage(location_path)
@classmethod
def _migrate_to_hash_storage(cls, location_path: Path) -> None:
"""Migrate existing files from filename-based to hash-based storage.
Checks for sidecars (.metadata, .tag) and imports them before renaming.
@@ -158,6 +188,15 @@ class Folder(Store):
if hash_path != file_path and not hash_path.exists():
debug(f"Migrating: {file_path.name} -> {hash_filename}", file=sys.stderr)
file_path.rename(hash_path)
# Ensure DB points to the renamed path (update by hash).
try:
cursor.execute(
"UPDATE files SET file_path = ?, updated_at = CURRENT_TIMESTAMP WHERE hash = ?",
(str(hash_path.resolve()), file_hash),
)
except Exception:
pass
# Create or update database entry
db.get_or_create_file_entry(hash_path)