mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
feat(store): read ledmatrix_min_version, aliases and commit from the registry (#686)
The store reads three optional registry fields: ledmatrix_min_version (an incompatible install/update is refused before any download, with a "Needs LEDMatrix X+" card badge), aliases (update/uninstall/reinstall by registry id find a plugin installed under its manifest id, with registry proof only), and commit (shown and linked on the store card). An older plugins.json behaves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,14 @@ class _InstallMixin:
|
||||
return False
|
||||
|
||||
with self._get_reinstall_lock(plugin_id):
|
||||
plugin_path = self.plugins_dir / plugin_id
|
||||
# The copy to protect is wherever this plugin is installed, not
|
||||
# necessarily plugins_dir/<id>: asked for the registry id
|
||||
# `weather`, the install lives in `ledmatrix-weather/`, the
|
||||
# manifest's id. Backing up only `weather/` protected nothing,
|
||||
# and _install_plugin_impl then deleted `ledmatrix-weather/` to
|
||||
# make room for the download -- so a refusal after that point
|
||||
# (the post-download compatibility gate) left no plugin at all.
|
||||
plugin_path = self._existing_install(plugin_id) or self.plugins_dir / plugin_id
|
||||
if not plugin_path.exists():
|
||||
return self._install_plugin_impl(plugin_id, branch)
|
||||
|
||||
@@ -91,6 +98,26 @@ class _InstallMixin:
|
||||
self._restore_backup(plugin_id, plugin_path, backup_path, "Install")
|
||||
return False
|
||||
|
||||
def _existing_install(self, plugin_id: str) -> Optional[Path]:
|
||||
"""The installed copy of ``plugin_id`` in plugins_dir, by the id or an
|
||||
alias the registry proves (`_installed_id_candidates`).
|
||||
|
||||
When nothing matches but a ``ledmatrix-<id>`` folder exists and no
|
||||
registry is loaded yet, the registry is fetched first -- the install
|
||||
fetches it anyway -- because without it that folder can be neither
|
||||
protected nor trusted: the download may be renamed onto it.
|
||||
"""
|
||||
dirs = [self.plugins_dir]
|
||||
found = self._resolve_installed(plugin_id, dirs)
|
||||
if (found is None and not getattr(self, 'registry_cache', None)
|
||||
and self._unproven_prefix_folder(plugin_id, dirs) is not None):
|
||||
try:
|
||||
self.fetch_registry()
|
||||
except Exception as e: # noqa: BLE001 - proceed as before without proof
|
||||
self.logger.debug("Registry fetch before installing %s failed: %s", plugin_id, e)
|
||||
found = self._resolve_installed(plugin_id, dirs)
|
||||
return found
|
||||
|
||||
def _set_aside(self, plugin_path: Path, backup_path: Path) -> Optional[str]:
|
||||
"""Rename an installed plugin to ``backup_path`` so a failed
|
||||
(re)install can put it back.
|
||||
@@ -164,6 +191,16 @@ class _InstallMixin:
|
||||
self.logger.error(f"Plugin {plugin_id} missing repository URL")
|
||||
return False
|
||||
|
||||
# The registry's floor describes the release on the entry's branch.
|
||||
# Checked here, before anything is removed or downloaded; the gate on
|
||||
# the downloaded manifest below stays as the fallback (older
|
||||
# registries, compatible_versions ranges). A different branch asked
|
||||
# for by name is a different release, so only the fallback applies.
|
||||
registry_branch = plugin_info.get('branch') or plugin_info.get('default_branch')
|
||||
if (not branch or not registry_branch or branch == registry_branch) and \
|
||||
self._refuse_if_registry_incompatible(plugin_id, plugin_info, "install"):
|
||||
return False
|
||||
|
||||
plugin_subpath = plugin_info.get('plugin_path')
|
||||
# If branch is provided, prioritize it; otherwise use default logic
|
||||
branch_candidates = self._distinct_sequence([
|
||||
@@ -280,9 +317,11 @@ class _InstallMixin:
|
||||
return False
|
||||
|
||||
# Refuse a plugin that needs a newer core than this one. The
|
||||
# registry carries no compatibility field, so the floor is only
|
||||
# knowable once the files are down — checking here, before
|
||||
# dependency installation, is the earliest possible point.
|
||||
# registry's `ledmatrix_min_version` already refused the
|
||||
# common case before the download (above); this is the
|
||||
# fallback for a registry without it, a branch other than the
|
||||
# registry's, and `compatible_versions`, which only the
|
||||
# manifest carries. Before dependency installation, still.
|
||||
#
|
||||
# Refusing costs the user nothing: on an update this returns
|
||||
# False and _reinstall_with_rollback restores the version they
|
||||
@@ -299,6 +338,7 @@ class _InstallMixin:
|
||||
if not compatible:
|
||||
self.logger.error(
|
||||
"Refusing to install %s: %s", plugin_id, reason)
|
||||
self._note_refusal(requested_id, reason)
|
||||
self._safe_remove_directory(plugin_path)
|
||||
return False
|
||||
|
||||
|
||||
Reference in New Issue
Block a user