Files
DemonGatanjieuandClaude Opus 5.5 2e62703923 Update Anomalous_TTS from GPT-SoVITS Settings
The version manager takes an optional Checkout, so the companion node pack is
handled like the plugin itself: api/tts_version.py finds it among the
custom_nodes folders by its node class and accepts only a git clone of the
official repository; releases are fetched only on "Check for updates", an
update checks out the newest stable tag and can be undone. A checkout without
the release tags (cloned before it, then pulled) is matched by ls-remote.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 13:08:10 +08:00

97 lines
3.6 KiB
Python

"""Version and updates of the companion node pack Anomalous_TTS (GPT-SoVITS Settings).
Only a git checkout of the official repository is touched, found among the
custom_nodes folders by its node class and checked by its `origin` remote. The
rules are those of the plugin's own version panel (api/version_manager.py):
published releases are fetched only when asked, a switch checks out a
published release tag, refuses over modified tracked files and can be undone.
"""
import asyncio
import os
from aiohttp import web
import folder_paths
from . import version_manager as vm
OFFICIAL = ("demongatanjieu", "anomalous_tts")
NODE_CLASS = "AnomalousTTS_CharacterSpeech"
STATE_FILE = os.path.join(vm.PLUGIN_DIR, ".anomalous_tts_version.local.json")
READ_LIMIT = 200_000
def _node_folders():
"""custom_nodes folders whose nodes.py defines the Anomalous_TTS node (disabled ones left out)."""
for base in folder_paths.get_folder_paths("custom_nodes"):
try:
names = sorted(os.listdir(base))
except OSError:
continue
for name in names:
folder = os.path.join(base, name)
if name.endswith(".disabled") or not os.path.exists(os.path.join(folder, ".git")):
continue
try:
with open(os.path.join(folder, "nodes.py"), encoding="utf-8", errors="replace") as handle:
if NODE_CLASS in handle.read(READ_LIMIT):
yield folder
except OSError:
continue
def find_checkout():
"""The installed Anomalous_TTS as a version_manager.Checkout, or None (not installed, not a git
clone, or cloned from somewhere else)."""
for folder in _node_folders():
repo = vm.Checkout(folder, STATE_FILE)
owner_repo = vm._github_repo(vm._git_out("remote", "get-url", "origin", repo=repo))
if owner_repo and tuple(part.lower() for part in owner_repo) == OFFICIAL:
return repo
return None
def _checkout():
repo = find_checkout()
if repo is None:
raise vm.VersionError("tts_missing", "Anomalous_TTS is not installed as a git clone of its GitHub repository")
return repo
def state():
repo = find_checkout()
return {"found": False} if repo is None else {"found": True, "state": vm.current_state(repo)}
async def api_get_state(request):
"""GET /anomalous/tts_version - Installed Anomalous_TTS version (local, no network)."""
try:
return web.json_response({"success": True, **(await asyncio.to_thread(state))})
except vm.VersionError as error:
return vm.error_response(error)
async def api_get_releases(request):
"""GET /anomalous/tts_version/releases?refresh=1 - Its published releases (network, only when asked)."""
refresh = request.query.get("refresh") == "1"
return await vm.run(lambda: vm.list_releases(refresh, _checkout()))
async def api_update(request):
"""POST /anomalous/tts_version/update {tag} - Check out a published release."""
tag = str((await vm.json_body(request)).get("tag", ""))
return await vm.run(lambda: vm.switch_to(tag, _checkout()))
async def api_undo(request):
"""POST /anomalous/tts_version/undo - Back to where the last update came from."""
return await vm.run(lambda: vm.undo_last_switch(_checkout()))
def register_routes(app):
app.router.add_get('/anomalous/tts_version', api_get_state)
app.router.add_get('/anomalous/tts_version/releases', api_get_releases)
app.router.add_post('/anomalous/tts_version/update', api_update)
app.router.add_post('/anomalous/tts_version/undo', api_undo)