"""The program catalog: the Programs/ folder (manifests, templates, icons), fetched from the SaraSuite repo itself, so adding a program or fixing an install recipe only takes a push, not a new AppImage. The latest commit of the SaraSuite repo is checked the same way programs are (Sources.py). When it changed, its Programs/ folder is downloaded into ~/.cache/SaraSuite/Catalog/. LoadPrograms() then reads that, falling back to the AppImage's bundled copy when there's no catalog yet, when it can't be loaded, or when running from source: there, the local Programs/ folder always wins, so unpushed manifest edits work while developing. """ import shutil from pathlib import Path from typing import Callable, Optional from Core import BundledManifestsDir, CacheHome, IsFrozen, LoadConfig from Sources import ClearDownloads, Download, LatestCommit, SourceError CatalogDir = CacheHome / "SaraSuite" / "Catalog" _CommitFile = CatalogDir / "Commit" _DownloadName = "SaraSuiteCatalog" def ManifestsDir() -> Path: if IsFrozen and (CatalogDir / "Programs").is_dir(): return CatalogDir / "Programs" return BundledManifestsDir def CatalogCommit() -> str: return _CommitFile.read_text().strip() if _CommitFile.is_file() else "" def UpdateCatalog(Log: Optional[Callable[[str], None]] = None) -> bool: """Fetch the SaraSuite repo's Programs/ if it has a new commit. Returns True when the catalog changed (the program list should be reloaded). Does nothing when running from source, and quietly keeps the current catalog when the git host can't be reached.""" if not IsFrozen: return False Log = Log or (lambda Line: None) Url = f"{LoadConfig().GitHost.rstrip('/')}/SaraSuite" try: Commit = LatestCommit(Url) except SourceError: return False if Commit == CatalogCommit(): return False try: Source = Download(_DownloadName, Url, Commit, Log) / "Programs" if not Source.is_dir(): return False Staging = CatalogDir.with_name("Catalog.new") shutil.rmtree(Staging, ignore_errors=True) shutil.copytree(Source, Staging / "Programs", ignore=shutil.ignore_patterns("__pycache__")) (Staging / "Commit").write_text(Commit) shutil.rmtree(CatalogDir, ignore_errors=True) Staging.rename(CatalogDir) except (SourceError, OSError) as Error: Log(f"Couldn't update the program list: {Error}") return False finally: ClearDownloads(_DownloadName) Log(f"Program list updated to SaraSuite commit {Commit[:7]}") return True