Skip to content

Commit 5a8e35d

Browse files
committed
[PHAROS] Hotfix for update path
1 parent 74b42f2 commit 5a8e35d

3 files changed

Lines changed: 35 additions & 3 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version = "1.0.0"
1+
version = "1.0.1"

buildtools/pharos/app/main.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,48 @@
1414
def apply_pending_update() -> None:
1515
update_zip = os.path.join(DATA_DIR, ".pending_update.zip")
1616
if not os.path.exists(update_zip):
17+
print(f"[Update] No pending update at {update_zip}; skipping.")
1718
return
19+
print(f"[Update] Applying pending update from {update_zip} "
20+
f"(size {os.path.getsize(update_zip)} bytes)...")
1821

1922
# The update zip mirrors the install layout. Extract one level above
2023
# the install dir so the launchscript and binary both get replaced.
24+
# Linux refuses to overwrite a running binary with O_TRUNC (ETXTBSY on
25+
# overlay-style filesystems used by ROCKNIX/Knulli/MuOS), so write each
26+
# entry to a sibling .tmp and os.replace() it onto the target. The
27+
# inode swap leaves the currently-running process undisturbed and the
28+
# new file is in place for the next launch.
2129
target = os.path.abspath(os.path.join(INSTALL_DIR, ".."))
2230
try:
2331
with zipfile.ZipFile(update_zip, "r") as zf:
24-
zf.extractall(target)
32+
for entry in zf.infolist():
33+
dest = os.path.join(target, entry.filename)
34+
if entry.is_dir():
35+
os.makedirs(dest, exist_ok=True)
36+
continue
37+
os.makedirs(os.path.dirname(dest), exist_ok=True)
38+
tmp = dest + ".tmp"
39+
with zf.open(entry, "r") as src, open(tmp, "wb") as dst:
40+
while True:
41+
chunk = src.read(64 * 1024)
42+
if not chunk:
43+
break
44+
dst.write(chunk)
45+
# Preserve original mode bits (e.g. 0o755 on the binary).
46+
mode = (entry.external_attr >> 16) & 0o777
47+
if mode:
48+
os.chmod(tmp, mode)
49+
os.replace(tmp, dest)
2550
os.remove(update_zip)
2651
print(f"[Update] Applied pending update to {target}.")
2752
except (zipfile.BadZipFile, OSError) as e:
2853
print(f"[Update] Failed to apply pending update: {e}", file=sys.stderr)
54+
# Drop the zip so we don't keep retrying a broken/partial download.
55+
try:
56+
os.remove(update_zip)
57+
except OSError:
58+
pass
2959

3060

3161
apply_pending_update()

buildtools/pharos/app/update.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
PHAROS_PORTS_JSON_RAW = (
3535
f"https://raw.githubusercontent.com/{PHAROS_REPO}/main/docs/ports.json"
3636
)
37-
PHAROS_PORT_NAME = "pharos.zip" # matches port.json "name"
37+
PHAROS_PORT_NAME = "pharos.zip"
3838

3939
PENDING_ZIP = os.path.join(DATA_DIR, ".pending_update.zip")
4040
VERSION_RE = re.compile(r"version\s*=\s*['\"]([^'\"]+)['\"]")
@@ -138,6 +138,8 @@ def download(self) -> bool:
138138
self.ui.render_to_screen()
139139
sdl2.SDL_Delay(16)
140140

141+
print(f"[Update] Saved pending update to {PENDING_ZIP} "
142+
f"({downloaded} bytes).")
141143
return True
142144
except (HTTPError, URLError, OSError) as e:
143145
# OSError covers disk-full / permission failures mid-write — without

0 commit comments

Comments
 (0)