aboutsummaryrefslogtreecommitdiff
path: root/app/backends/audiocpp/build.py
diff options
context:
space:
mode:
Diffstat (limited to 'app/backends/audiocpp/build.py')
-rw-r--r--app/backends/audiocpp/build.py55
1 files changed, 45 insertions, 10 deletions
diff --git a/app/backends/audiocpp/build.py b/app/backends/audiocpp/build.py
index e3536cf..36c304c 100644
--- a/app/backends/audiocpp/build.py
+++ b/app/backends/audiocpp/build.py
@@ -59,7 +59,11 @@ def update(*, emit=None, cancel=None) -> int:
(a ``prebuilt.json`` marker next to the binary, see
``backends.audiocpp.prebuilt``) take a different route: they skip the
git update and rebuild entirely and instead re-download when upstream
- published a newer release (see ``_update_prebuilt``). Source-built
+ published a newer release (see ``_update_prebuilt``) — and when that
+ re-download fails (rate limit, offline), the same source-build route a
+ source-built checkout uses runs instead, so 'Update Backends' still
+ gets current by whatever means work; the installed binary is only
+ replaced on success and keeps working meanwhile. Source-built
checkouts keep the original flow — phases: stop server / git update /
rebuild — CANCEL is honored between phases only, so a started phase
always completes. The git update is a fetch plus hard reset to origin's
@@ -78,7 +82,8 @@ def update(*, emit=None, cancel=None) -> int:
interrupted (cancelled or failed) earlier rebuild, which leaves the
previous binary in place against already-updated sources. An
up-to-date checkout with a fresh binary costs one fetch. Returns the
- exit code (130 when cancelled before a remaining phase).
+ exit code (130 when cancelled before a remaining phase, or when a
+ prebuilt re-download was cancelled).
"""
# Only stop when a pid file exists: without one this tool never
# started the server, so the "not started by this tool" notice would
@@ -92,8 +97,19 @@ def update(*, emit=None, cancel=None) -> int:
print("[INFO] No audio.cpp checkout to update.")
return 0
backend = _rebuild_backend(checkout)
+ fell_back = False
if _prebuilt.installed_release(checkout, backend) is not None:
- return _update_prebuilt(checkout, backend, emit=emit, cancel=cancel)
+ rc = _update_prebuilt(checkout, backend, emit=emit, cancel=cancel)
+ if rc == 0 or rc == 130:
+ return rc
+ # The re-download failed (the usual cause is GitHub's API rate
+ # limit): the installed binary was left in place and keeps
+ # working — recover in place like the install paths do, by
+ # building from source instead.
+ print(f"[WARNING] prebuilt update failed (exit {rc}); the installed "
+ "audiocpp_server was left in place — falling back to a "
+ "source build...")
+ fell_back = True
head_before = common.git_head(checkout)
rc = common.git_update(checkout, emit=emit, cancel=cancel)
if rc != 0:
@@ -113,6 +129,8 @@ def update(*, emit=None, cancel=None) -> int:
moved=head_after not in (None, head_before)):
print(f"[OK] {checkout} is already at origin's HEAD with an "
"up-to-date audiocpp_server.")
+ if fell_back:
+ _drop_prebuilt_marker(checkout, backend)
return 0
if head_after in (None, head_before):
print(f"[INFO] audiocpp_server on disk is older than the "
@@ -130,9 +148,29 @@ def update(*, emit=None, cancel=None) -> int:
"retry the rebuild.")
else:
print("[OK] rebuild complete.")
+ if fell_back:
+ _drop_prebuilt_marker(checkout, backend)
return build_rc
+def _drop_prebuilt_marker(checkout: Path, backend: Optional[str]) -> None:
+ """Remove the prebuilt.json marker after a fallback source build.
+
+ The fallback replaced (or matched) the downloaded binary with a
+ source build, so the marker's "this build directory holds release
+ <tag>" claim is stale — keeping it would make the next update
+ re-download over the freshly built binary. Best-effort: a marker
+ that cannot be removed only means the next update re-downloads.
+ """
+ marker = _prebuilt.marker_path(checkout, backend)
+ if marker is None:
+ return
+ try:
+ marker.unlink(missing_ok=True)
+ except OSError:
+ pass
+
+
def _update_prebuilt(checkout: Path, backend: Optional[str], *,
emit=None, cancel=None) -> int:
"""The update route for a prebuilt (release-downloaded) install.
@@ -144,8 +182,10 @@ def _update_prebuilt(checkout: Path, backend: Optional[str], *,
re-download itself, for the checksum digests. The recorded/detected
backend selects the asset, mirroring what was originally installed.
A GitHub outage is not fatal — the installed binary keeps working.
- Returns the install exit code (0 when already current or when the
- check could not run).
+ Returns 0 when already current or when the check could not run; a
+ failed re-download returns its exit code and ``update()`` falls back
+ to a source build (a cancelled download, 130, aborts without
+ falling back).
"""
marker = _prebuilt.installed_release(checkout, backend)
tag = _prebuilt.resolve_latest_tag()
@@ -166,11 +206,6 @@ def _update_prebuilt(checkout: Path, backend: Optional[str], *,
cancel=cancel)
if rc == 0:
print(f"[OK] audiocpp_server updated to {tag}.")
- else:
- print(f"[WARNING] prebuilt update failed (exit {rc}); the "
- "installed audiocpp_server was left in place. Retry "
- "'Update Backends' later, or build from source with "
- "'Build audio.cpp Server'.")
return rc