Skip to content

Commit 35b9c8a

Browse files
CopilotAmiga500
andcommitted
Integrate PR OnionUI#1918: Enable chunk-based OTA updates via desync
Add desync submodule for content-addressable chunking. Update Makefile with desync build targets, 7z deterministic archive flags, and chunk generation target. Update OTA update script with delta download support via --chunk flag. Update install.sh with promote_initial_seed function. Update tagged-release workflow to build desync and include .caidx artifact. Co-authored-by: Amiga500 <16525337+Amiga500@users.noreply.github.com>
1 parent a6ffff3 commit 35b9c8a

6 files changed

Lines changed: 136 additions & 13 deletions

File tree

.github/workflows/tagged-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
shell: bash
3434
run: |
3535
source /root/.bashrc
36-
VERSION_OVERRIDE=${{ env.BUILD_VERSION }} make release
36+
VERSION_OVERRIDE=${{ env.BUILD_VERSION }} make desync-bin release chunk
3737
- uses: marvinpinto/action-automatic-releases@latest
3838
with:
3939
repo_token: ${{ secrets.GITHUB_TOKEN }}
@@ -42,3 +42,4 @@ jobs:
4242
title: "Onion V${{ env.BUILD_VERSION }}"
4343
files: |
4444
release/Onion-v${{ env.BUILD_VERSION }}.zip
45+
release/Onion-v${{ env.BUILD_VERSION }}.caidx

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
[submodule "third-party/RetroArch-patch"]
1111
path = third-party/RetroArch-patch
1212
url = https://github.com/Amiga500/RetroArch-patch
13+
[submodule "third-party/desync"]
14+
path = third-party/desync
15+
url = https://github.com/folbricht/desync

Makefile

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RA_SUBVERSION=1.22.2-1
99
ifneq ($(VERSION_OVERRIDE),)
1010
VERSION = $(VERSION_OVERRIDE)
1111
endif
12-
12+
1313
RELEASE_NAME := $(TARGET)-v$(VERSION)
1414

1515
ifdef OS
@@ -43,6 +43,8 @@ PACKAGES_EMU_DEST := $(PACKAGES_DIR)/Emu
4343
PACKAGES_APP_DEST := $(PACKAGES_DIR)/App
4444
PACKAGES_RAPP_DEST := $(PACKAGES_DIR)/RApp
4545
TEMP_DIR := $(ROOT_DIR)/cache/temp
46+
DESYNC_SRC := $(THIRD_PARTY_DIR)/desync
47+
CHUNK_STORE := $(RELEASE_DIR)/chunks.castr
4648
INCLUDE_DIR := $(ROOT_DIR)/include
4749
ifeq (,$(GTEST_INCLUDE_DIR))
4850
GTEST_INCLUDE_DIR = /usr/include/
@@ -63,7 +65,7 @@ APP_COMPONENTS = batteryMonitorUI playActivityUI clock randomGamePicker
6365

6466
###########################################################
6567

66-
.PHONY: all version core apps external release clean deepclean git-clean with-toolchain patch lib test unit-test \
68+
.PHONY: all version core apps external release chunk clean deepclean git-clean with-toolchain patch lib test unit-test desync-bin desync-host \
6769
$(CORE_COMPONENTS) $(APP_COMPONENTS) installUI
6870

6971
all: dist
@@ -206,8 +208,32 @@ $(THIRD_PARTY_DIR)/RetroArch-patch/bin/retroarch_miyoo354:
206208
fi
207209
@cd $(THIRD_PARTY_DIR)/RetroArch-patch && make
208210

211+
$(DESYNC_SRC)/go.mod:
212+
git submodule update --init third-party/desync
213+
214+
$(BIN_DIR)/desync: $(DESYNC_SRC)/go.mod
215+
@$(ECHO) $(COLOR_BLUE)"\n-- Build desync (ARM)"$(COLOR_NORMAL)
216+
@cd $(DESYNC_SRC) && GOOS=linux GOARCH=arm GOARM=7 CGO_ENABLED=0 \
217+
PATH="$$PATH:/usr/local/go/bin" go build -ldflags="-s -w" -o $(BIN_DIR)/desync ./cmd/desync
218+
219+
desync-bin: $(BIN_DIR)/desync
220+
221+
$(CACHE)/desync: $(DESYNC_SRC)/go.mod
222+
@$(ECHO) $(COLOR_BLUE)"\n-- Build desync (host)"$(COLOR_NORMAL)
223+
@mkdir -p $(CACHE)
224+
@cd $(DESYNC_SRC) && PATH="$$PATH:/usr/local/go/bin" \
225+
go build -ldflags="-s -w" -o $(CACHE)/desync ./cmd/desync
226+
227+
desync-host: $(CACHE)/desync
228+
209229
external: $(CACHE)/.setup $(THIRD_PARTY_DIR)/RetroArch-patch/bin/retroarch_miyoo354
210230
@$(ECHO) $(PRINT_RECIPE)
231+
# Add desync to installer (must be pre-built on host with: make desync-bin)
232+
@if [ -f $(BIN_DIR)/desync ]; then \
233+
cp $(BIN_DIR)/desync $(INSTALLER_DIR)/bin/; \
234+
else \
235+
echo "WARNING: desync not found — run 'make desync-bin' on the host before building"; \
236+
fi
211237
# Add RetroArch
212238
@cp $(THIRD_PARTY_DIR)/RetroArch-patch/bin/* $(BUILD_DIR)/RetroArch/
213239
@echo $(RA_SUBVERSION) > $(BUILD_DIR)/RetroArch/onion_ra_version.txt
@@ -242,27 +268,38 @@ dist: build
242268
# Package configs
243269
@cp -R $(TEMP_DIR)/configs/Saves/CurrentProfile/ $(TEMP_DIR)/configs/Saves/GuestProfile
244270
@echo -n "Packaging configs..."
245-
@cd $(TEMP_DIR)/configs && 7z a -mtm=off $(BUILD_DIR)/.tmp_update/config/configs.pak . -bsp1 -bso0
271+
@cd $(TEMP_DIR)/configs && 7z a -ms=off -mtm=off $(BUILD_DIR)/.tmp_update/config/configs.pak . -bsp1 -bso0
246272
@echo " DONE"
247273
@rm -rf $(TEMP_DIR)/configs
248274
@rmdir $(TEMP_DIR)
249275
# Package RetroArch separately
250276
@echo -n "Packaging RetroArch..."
251-
@cd $(BUILD_DIR) && 7z a -mtm=off retroarch.pak ./RetroArch -bsp1 -bso0
277+
@cd $(BUILD_DIR) && 7z a -ms=off -mtm=off retroarch.pak ./RetroArch -bsp1 -bso0
252278
@echo " DONE"
253279
@mkdir -p $(DIST_DIR)/RetroArch
254280
@mv $(BUILD_DIR)/retroarch.pak $(DIST_DIR)/RetroArch/
255281
@echo $(RA_SUBVERSION) > $(DIST_DIR)/RetroArch/ra_package_version.txt
256282
# Package Onion core
257283
@echo -n "Packaging Onion..."
258-
@cd $(BUILD_DIR) && 7z a -mtm=off $(DIST_DIR)/miyoo/app/.tmp_update/onion.pak . -x!RetroArch -bsp1 -bso0
284+
@cd $(BUILD_DIR) && 7z a -ms=off -mtm=off $(DIST_DIR)/miyoo/app/.tmp_update/onion.pak . -x!RetroArch -bsp1 -bso0
259285
@echo " DONE"
260286
@$(ECHO) $(PRINT_DONE)
261287

262288
release: dist
263289
@$(ECHO) $(PRINT_RECIPE)
264290
@rm -f $(RELEASE_DIR)/$(RELEASE_NAME).zip
265-
@cd $(DIST_DIR) && 7z a -mtc=off $(RELEASE_DIR)/$(RELEASE_NAME).zip . -bsp1 -bso0
291+
@find $(DIST_DIR) -type f -exec touch -t 198001010000 {} +
292+
@cd $(DIST_DIR) && 7z a $(RELEASE_DIR)/$(RELEASE_NAME).zip . -bsp1 -bso0
293+
@$(ECHO) $(PRINT_DONE)
294+
295+
chunk:
296+
@$(ECHO) $(PRINT_RECIPE)
297+
@echo "Generating desync index and chunks..."
298+
@mkdir -p $(CHUNK_STORE)
299+
@$(CACHE)/desync make \
300+
-s $(CHUNK_STORE) -m 512:1024:2048 \
301+
$(RELEASE_DIR)/$(RELEASE_NAME).caidx \
302+
$(RELEASE_DIR)/$(RELEASE_NAME).zip
266303
@$(ECHO) $(PRINT_DONE)
267304

268305
clean:
@@ -283,7 +320,7 @@ dev: clean
283320

284321
asan: clean
285322
@$(MAKE_ASAN)
286-
323+
287324
git-clean:
288325
@git clean -xfd -e .vscode
289326

static/build/.tmp_update/script/ota_update.sh

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#!/bin/sh
22
# OTA updates for Onion.
33
cmd=$1
4+
chunk_download=0
5+
for arg in "$@"; do
6+
[ "$arg" = "--chunk" ] && chunk_download=1
7+
done
48
sysdir=/mnt/SDCARD/.tmp_update
59

610
# Colors
@@ -13,6 +17,9 @@ NC='\033[0m' # No Color
1317
# Repository name :
1418
GITHUB_REPOSITORY=Amiga500/Onion
1519

20+
# Chunk store for desync delta downloads (can be overridden via environment)
21+
CHUNK_STORE_URL=${CHUNK_STORE_URL:-https://onionui.github.io/Onion/chunks/}
22+
1623
# channel : stable or beta
1724
channel=$(cat "$sysdir/config/ota_channel" 2> /dev/null)
1825
if [ "$channel" = "" ]; then
@@ -60,8 +67,15 @@ check_available_space() {
6067
mount_point=$(mount | grep -m 1 '/mnt/SDCARD' | awk '{print $1}') # it could be /dev/mmcblk0p1 or /dev/mmcblk0
6168
available_space=$(df -m $mount_point | awk 'NR==2{print $4}')
6269

63-
# Check available space
64-
if [ "$available_space" -lt "1000" ]; then
70+
# Account for existing seed zip (seed + new download must coexist during update)
71+
seed_size=0
72+
seed_zip=$(ls "$sysdir/seed/Onion-v"*.zip 2>/dev/null | head -1)
73+
[ -n "$seed_zip" ] && seed_size=$(du -m "$seed_zip" | awk '{print $1}')
74+
75+
# download (~1000MB) + seed on disk + ~300MB extraction headroom
76+
required=$((seed_size + 1300))
77+
78+
if [ "$available_space" -lt "$required" ]; then
6579
echo -e "${RED}Available space is insufficient on SD card${NC}\n"
6680
echo -ne "${YELLOW}"
6781
read -n 1 -s -r -p "Press A to exit"
@@ -138,6 +152,7 @@ get_release_info() {
138152
fi
139153

140154
Release_url=$(echo "$Release_asset" | jq '.browser_download_url' | tr -d '"')
155+
Release_caidx_url=$(echo "$Release_assets_info" | jq -r '.assets[]? | select(.name | endswith(".caidx")) | .browser_download_url')
141156
Release_FullVersion=$(echo "$Release_asset" | jq '.name' | tr -d "\"" | sed 's/^Onion-v//g' | sed 's/\.zip$//g')
142157
Release_Version=$(echo "$Release_FullVersion" | sed 's/-.*$//g')
143158
Release_size=$(echo "$Release_asset" | jq -r '.size')
@@ -175,11 +190,42 @@ get_release_info() {
175190
return 0
176191
}
177192

193+
do_download() {
194+
seed_zip=$(ls "$sysdir/seed/Onion-v"*.zip 2>/dev/null | head -1)
195+
seed_idx=$(ls "$sysdir/seed/Onion-v"*.caidx 2>/dev/null | head -1)
196+
desync_bin="$sysdir/bin/desync"
197+
out_zip="$sysdir/download/$Release_Version.zip"
198+
out_idx="$sysdir/download/$Release_Version.caidx"
199+
200+
# Always fetch the index (it's small) so it can seed future updates
201+
if [ -n "$Release_caidx_url" ]; then
202+
wget --no-check-certificate "$Release_caidx_url" -O "$out_idx"
203+
fi
204+
205+
if [ "$chunk_download" -eq 1 ] && [ -f "$out_idx" ] && [ -f "$desync_bin" ] && [ -n "$seed_zip" ] && [ -n "$seed_idx" ]; then
206+
echo -ne "\n${BLUE}== Delta download via desync (seed: $(basename $seed_zip)) ==${NC}\n"
207+
"$desync_bin" extract \
208+
-s "$CHUNK_STORE_URL" \
209+
--seed "$seed_idx:$seed_zip" \
210+
"$out_idx" \
211+
"$out_zip"
212+
if [ $? -eq 0 ]; then return 0; fi
213+
echo -e "${YELLOW}desync failed — falling back to full download${NC}"
214+
rm -f "$out_zip"
215+
fi
216+
217+
echo -ne "\n${BLUE}== Downloading Onion $Release_Version ($channel channel) ==${NC}\n"
218+
wget --no-check-certificate "$Release_url" -O "$out_zip"
219+
}
220+
178221
download_update() {
179222
echo -ne "${YELLOW}"
180223
read -n 1 -s -r -p "Press A to continue"
181224
echo -ne "${NC}"
182225

226+
# Clean up any stale partial download from a previous failed attempt
227+
rm -f "$sysdir/download/"*.zip "$sysdir/download/"*.caidx
228+
183229
Mychoice=$(echo -e "No\nYes" | $sysdir/script/shellect.sh -t "Download $Release_Version ($Release_size_MB) ?" -b "Press A to validate your choice.")
184230
clear
185231
if [ "$Mychoice" = "Yes" ]; then
@@ -195,11 +241,9 @@ download_update() {
195241
fsck.fat -a $mount_point
196242

197243
mkdir -p $sysdir/download/
198-
echo -ne "\n\n" \
199-
"${BLUE}== Downloading Onion $Release_Version ($channel channel) ==${NC}\n"
200244
/mnt/SDCARD/.tmp_update/bin/freemma > /dev/null
201245
sync
202-
wget --no-check-certificate "$Release_url" -O "$sysdir/download/$Release_Version.zip"
246+
do_download
203247
if [ $? -ne 0 ]; then
204248
echo -ne "\n\n" \
205249
"${RED}Error: Download failed${NC}\n"
@@ -245,6 +289,16 @@ apply_update() {
245289
if [ $? -eq 0 ]; then
246290
echo -e "${GREEN}Decompression successful.${NC}"
247291
sync
292+
293+
# Promote downloaded zip and index to seed for next OTA delta update
294+
mkdir -p $sysdir/seed
295+
rm -f $sysdir/seed/Onion-v*.zip $sysdir/seed/Onion-v*.caidx
296+
mv "$sysdir/download/$Release_Version.zip" "$sysdir/seed/$Release_Version.zip"
297+
[ -f "$sysdir/download/$Release_Version.caidx" ] && \
298+
mv "$sysdir/download/$Release_Version.caidx" "$sysdir/seed/$Release_Version.caidx"
299+
echo "$Release_Version" > $sysdir/seed/seed_version.txt
300+
sync
301+
248302
sleep 3
249303
echo -ne "\n\n" \
250304
"Update $Release_Version applied.\n" \

static/dist/miyoo/app/.tmp_update/install.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ run_installation() {
375375
fi
376376

377377
rm -f $sysdir/config/currentSlide 2> /dev/null
378+
promote_initial_seed
378379
sync
379380
}
380381

@@ -719,6 +720,32 @@ free_mma() {
719720
/mnt/SDCARD/.tmp_update/bin/freemma
720721
}
721722

723+
promote_initial_seed() {
724+
staged_zip=$(ls "$sysdir/download/Onion-v"*.zip 2>/dev/null | head -1)
725+
[ -z "$staged_zip" ] && return 0
726+
727+
staged_idx=$(ls "$sysdir/download/Onion-v"*.caidx 2>/dev/null | head -1)
728+
729+
echo ":: Promote initial seed: $(basename $staged_zip)"
730+
mkdir -p "$sysdir/seed"
731+
rm -f "$sysdir/seed"/Onion-v*.zip "$sysdir/seed"/Onion-v*.caidx
732+
733+
seed_zip="$sysdir/seed/$(basename $staged_zip)"
734+
seed_idx="${seed_zip%.zip}.caidx"
735+
736+
mv "$staged_zip" "$seed_zip"
737+
738+
if [ -n "$staged_idx" ]; then
739+
mv "$staged_idx" "$seed_idx"
740+
elif [ -f "$sysdir/bin/desync" ]; then
741+
echo ":: Generating seed index (no .caidx found)..."
742+
"$sysdir/bin/desync" make "$seed_idx" "$seed_zip"
743+
fi
744+
745+
echo "$(basename $staged_zip .zip)" > "$sysdir/seed/seed_version.txt"
746+
sync
747+
}
748+
722749
main
723750
sync
724751
reboot

third-party/desync

Submodule desync added at e58d685

0 commit comments

Comments
 (0)