From 08d05656c06a7fcd21aaaa5d3787294fae29b2e2 Mon Sep 17 00:00:00 2001 From: argszero Date: Tue, 4 Aug 2026 23:15:42 +0800 Subject: [PATCH 1/4] =?UTF-8?q?emrg:=20Phase=204=20=E8=A1=A5=20packaging/a?= =?UTF-8?q?ssets=20=E5=9B=BE=E6=A0=87=E8=B5=84=E4=BA=A7=20+=20gen-assets.s?= =?UTF-8?q?h=20=E7=94=9F=E6=88=90=E8=84=9A=E6=9C=AC=EF=BC=88rant=20#12=20?= =?UTF-8?q?=C2=A713=20=E9=AA=8C=E6=94=B6=E9=81=97=E6=BC=8F=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packaging/assets/icon-256.png | Bin 0 -> 2120 bytes packaging/assets/icon-512.png | Bin 0 -> 5397 bytes packaging/assets/icon.icns | Bin 0 -> 42070 bytes packaging/assets/icon.ico | Bin 0 -> 4596 bytes packaging/assets/icon.png | Bin 0 -> 14810 bytes packaging/gen-assets.sh | 247 ++++++++++++++++++++++++++++++++++ 6 files changed, 247 insertions(+) create mode 100644 packaging/assets/icon-256.png create mode 100644 packaging/assets/icon-512.png create mode 100644 packaging/assets/icon.icns create mode 100644 packaging/assets/icon.ico create mode 100644 packaging/assets/icon.png create mode 100644 packaging/gen-assets.sh diff --git a/packaging/assets/icon-256.png b/packaging/assets/icon-256.png new file mode 100644 index 0000000000000000000000000000000000000000..55902400241690faef5741215868bf756d08ddc9 GIT binary patch literal 2120 zcmZuy3s6+o8UF8McQ3HG7kscjU@zhXlOk+_4x|Em!389#gi$IXQP_@JO=7_Z;r%$g zWL1hzlWAq5WMyc5V1(9`hc@oTEUq*fWKxSpkOf3Apzg{Lud?j+EF?1>+kfVqd(MBp z`~Uwr|Lb5{r*w^hMK!^3o3i= zm4<$EeR8`;+KE4noLGE-kVIZnuW!}^S$ zQdbs31qG$e;wA^39cxculGky?HVVigpD6f)KWh{TAZ&+?@pcvoZDPMHQ`St7pjSZ$ zqffU3LSm-^7~t)X>1r)+zarzqX<&`%RQ}FVvGYkDu#8mbdT@|G!{`SR9@HZC8ZC6~ zh&H?qL#^j@v?()nC#xrfgzeEfm}7x16-(IR8>3qViHkhQa@S50z!m3^@2z3ZVQkN{ z-x!L2anpwY{a2k&^RV{l4(gWDI-pp_~Jx7X!8Fl>{uII7grLotUH50E?~~U$t*y!LS&Hd>kJz-d=#L z(Ja}a1XGCpLuMljNc3kb_yX86Q#l|htJn%~Xvq0|y!F+(U z?~G#)pxLW58yaRlOV7Fhw+~_TW$XO@2x##KbR}~-Hf%oHzOim#HOdgIjL zj9~bTT`A+H;#561q(I`}#e_yPCKvV>LJP+^$_nhUtrYg2i}>ZxbbNLF_}|lJ7W!ku zG*h3X^-NKgh4ciuWrkqo2wNF7#VdNIXfDr(bF8ybhA?13P(lQGu6J7}G%rJqbtAH$ z1ulXi8PH{3v*M8w9OEWZ$e^KFjvCYN6L1NIV?BhL+>f zoq38`X+_XB#6|2^lVEzngi6xnGO$bdaxe8#^Olt*1!Jg-2l&KE5a4?gL;e z2;*G5|E7ij%%4Thaf4*s!vb`K15_=}Ob-MDoOjHfpsErn2tTU8b_t;Eg&BJVAjN4B zACX}BL4m5USFo>KV9s+k-#g|63jw}3!&I|Uo&o|esg{+z0nX)?4N;K;uO-g}M?u8| zscrQ@o}-g@A12(B=+CQMdczN(vHUOY;{t=p;z`Q9*#3E7QlL{T>k820*b+=hp-%=b zzp|XWc*mtC#Gkv^4!eJu{yrRS^I(19Y;Qphtc>BaLW$d1b)KpLsB)P}JI)hR!Q*sqd6 zu*sF5FVFzb*^xEgwLk8zSyK!_ak`~+j^C+@$=xe(3Uu_FUwN|_Xn(a^`6l!7k-jCK zK)<05pK%5k12V7`XPxFR_kSP(_Vm{I>wKK8ilV4(uwH9eN^eRT%A4%@3+^vAN+*Rb z2JvEwS>uheXsommXAo1Nng@7OXzRvx`3@`oBmIa9)NCX?AfZ&w6xKX58A)I!Ov32L zCH9X1359H--{`Om{kp7dSdP9S5bvw3`TDxpi;MZ&c8Wk~hs0d62H0kkOLmZr68;8i z+~MBcyvLq13mODo@OENv>ry*x1Nb_9ZpZve3V>5PTgjSF#P@O62-SG+>&x%dNU`$g zm4@L!M+@+l>)qwP<`<$F*J6SN-F`7(ScCt6TokS!PW5rV3mgtgnOT9uMib$1$6MrS zYa$HpMAM3A>YHZ!F&tZyG} zn>PCYYrOZs@m|Mc(g3LL~A9cf+l`y}|m01{#o KwdZ4WW&Z&qlIv;! literal 0 HcmV?d00001 diff --git a/packaging/assets/icon-512.png b/packaging/assets/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..bc6179cfc97159e1d0320cdbc446b368dd4a6311 GIT binary patch literal 5397 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 literal 0 HcmV?d00001 diff --git a/packaging/assets/icon.png b/packaging/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..794c9bcad0bae4f294d022d8dca0ac59c0f8a01f GIT binary patch literal 14810 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 literal 0 HcmV?d00001 diff --git a/packaging/gen-assets.sh b/packaging/gen-assets.sh new file mode 100644 index 00000000..3f489548 --- /dev/null +++ b/packaging/gen-assets.sh @@ -0,0 +1,247 @@ +#!/usr/bin/env bash +# EMRG Phase 4 — generate packaging assets (icons). +# +# Pure-stdlib approach (no PIL/ImageMagick dependency): +# 1. Python stdlib draws a 1024x1024 PNG (EMRG glyph: dark bg + green "E" + circuit node) +# 2. iconutil (macOS) → .icns +# 3. Python stdlib → multi-size .ico (win) +# 4. 512/256 PNG copies (linux) +# +# Output in packaging/assets/: +# icon.png (1024) icon-512.png icon-256.png icon.icns icon.ico +# +# Run from repo root: bash packaging/gen-assets.sh + +set -euo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +OUT="$ROOT/packaging/assets" +mkdir -p "$OUT" + +echo "==> generating 1024x1024 icon.png (pure stdlib)" +python3 - "$OUT/icon.png" <<'PYEOF' +import sys, struct, zlib, math + +path = sys.argv[1] +S = 1024 +# RGBA buffer (transparent bg) +buf = bytearray([0, 0, 0, 0]) * (S * S) + +def put(x, y, r, g, b, a=255): + if 0 <= x < S and 0 <= y < S: + i = (y * S + x) * 4 + buf[i] = r; buf[i+1] = g; buf[i+2] = b; buf[i+3] = a + +def fill_circle(cx, cy, rad, r, g, b, a=255): + # bounding box fill + x0, x1 = max(0, int(cx-rad)), min(S, int(cx+rad)+1) + y0, y1 = max(0, int(cy-rad)), min(S, int(cy+rad)+1) + r2 = rad*rad + for yy in range(y0, y1): + for xx in range(x0, x1): + dx, dy = xx-cx, yy-cy + if dx*dx + dy*dy <= r2: + put(xx, yy, r, g, b, a) + +def fill_rect(x0, y0, x1, y1, r, g, b, a=255): + for yy in range(max(0,y0), min(S,y1)): + for xx in range(max(0,x0), min(S,x1)): + put(xx, yy, r, g, b, a) + +def fill_round_rect(x0, y0, x1, y1, rad, r, g, b, a=255): + fill_rect(x0+rad, y0, x1-rad, y1, r, g, b, a) + fill_rect(x0, y0+rad, x1, y1-rad, r, g, b, a) + fill_circle(x0+rad, y0+rad, rad, r, g, b, a) + fill_circle(x1-rad, y0+rad, rad, r, g, b, a) + fill_circle(x0+rad, y1-rad, rad, r, g, b, a) + fill_circle(x1-rad, y1-rad, rad, r, g, b, a) + +# background: rounded square (EMRG brand: dark navy #0f172a) +fill_round_rect(64, 64, S-64, S-64, 180, 0x0f, 0x17, 0x2a) +# subtle outer ring +for rad in range(460, 480): + fill_circle(S//2, S//2, rad, 0x1e, 0x29, 0x3b, 255) + +# circuit: ring + node (self-evolving motif) +fill_circle(S//2, S//2, 300, 0x10, 0xb9, 0x81, 255) # green ring body +fill_circle(S//2, S//2, 250, 0x0f, 0x17, 0x2a, 255) # punch hole → ring +# 4 orbit nodes +for ang in (0, 90, 180, 270): + ox = S//2 + int(380 * math.cos(math.radians(ang))) + oy = S//2 + int(380 * math.sin(math.radians(ang))) + fill_circle(ox, oy, 40, 0x10, 0xb9, 0x81, 255) + +# "E" glyph (three bars + spine) — simple block letter +bar = 70 +spine_x0, spine_x1 = S//2 - 200, S//2 - 130 +top_y, mid_y, bot_y = S//2 - 200, S//2 - 30, S//2 + 140 +fill_rect(spine_x0, top_y, spine_x1, bot_y+bar, 0xf8, 0xfa, 0xfc) # vertical spine +fill_rect(spine_x0, top_y, S//2 + 200, top_y+bar, 0xf8, 0xfa, 0xfc) # top bar +fill_rect(spine_x0, mid_y, S//2 + 140, mid_y+bar, 0xf8, 0xfa, 0xfc) # middle bar +fill_rect(spine_x0, bot_y, S//2 + 200, bot_y+bar, 0xf8, 0xfa, 0xfc) # bottom bar + +def write_png(path, w, h, rgba): + def chunk(tag, data): + c = struct.pack(">I", len(data)) + tag + data + c += struct.pack(">I", zlib.crc32(tag + data) & 0xffffffff) + return c + raw = b"".join(b"\x00" + bytes(rgba[y*w*4:(y+1)*w*4]) for y in range(h)) + png = b"\x89PNG\r\n\x1a\n" + png += chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 6, 0, 0, 0)) + png += chunk(b"IDAT", zlib.compress(raw, 9)) + png += chunk(b"IEND", b"") + with open(path, "wb") as f: + f.write(png) + +write_png(path, S, S, buf) +print(" wrote", path) +PYEOF + +echo "==> resizing to 512/256 (stdlib scale-down)" +python3 - "$OUT/icon.png" "$OUT" <<'PYEOF' +import sys, zlib, struct + +src, outdir = sys.argv[1], sys.argv[2] + +def read_png(path): + data = open(path, "rb").read() + assert data[:8] == b"\x89PNG\r\n\x1a\n" + pos, w, h, idat = 8, 0, 0, b"" + while pos < len(data): + ln = struct.unpack(">I", data[pos:pos+4])[0] + tag = data[pos+4:pos+8] + chunk = data[pos+8:pos+8+ln] + if tag == b"IHDR": + w, h = struct.unpack(">II", chunk[:8]) + elif tag == b"IDAT": + idat += chunk + pos += 12 + ln + raw = zlib.decompress(idat) + # PNG scanlines each have a leading filter byte (0 for None); strip them + stride0 = w * 4 + 1 + raw = b"".join(raw[y*stride0+1:(y+1)*stride0] for y in range(h)) + return w, h, raw + +w, h, raw = read_png(src) +stride = w * 4 + +def sample(x, y): + i = y * stride + x * 4 + return raw[i], raw[i+1], raw[i+2], raw[i+3] + +def resize(nw, nh): + out = bytearray([0, 0, 0, 0]) * (nw * nh) + for yy in range(nh): + sy = min(int(yy * h / nh), h-1) + for xx in range(nw): + sx = min(int(xx * w / nw), w-1) + i = sy * stride + sx * 4 + r, g, b, a = raw[i], raw[i+1], raw[i+2], raw[i+3] + o = (yy * nw + xx) * 4 + out[o] = r; out[o+1] = g; out[o+2] = b; out[o+3] = a + return bytes(out) + +def write_png(path, nw, nh, rgba): + def chunk(tag, data): + c = struct.pack(">I", len(data)) + tag + data + c += struct.pack(">I", zlib.crc32(tag + data) & 0xffffffff) + return c + raw = b"".join(b"\x00" + rgba[y*nw*4:(y+1)*nw*4] for y in range(nh)) + png = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", nw, nh, 8, 6, 0, 0, 0)) + chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b"") + open(path, "wb").write(png) + +for size in (512, 256): + p = f"{outdir}/icon-{size}.png" + write_png(p, size, size, resize(size, size)) + print(" wrote", p) +PYEOF + +echo "==> iconutil → icon.icns (macOS)" +ICONSET="$OUT/icon.iconset" +mkdir -p "$ICONSET" +# iconutil wants specific sizes +for s in 16 32 128 256 512; do + d=$((s*2)) + python3 - "$OUT/icon.png" "$ICONSET/icon_${s}x${s}.png" "$s" <<'PYEOF' +import sys, zlib, struct +src, dst, size = sys.argv[1], sys.argv[2], int(sys.argv[3]) +# reuse resize from above by re-reading +data = open(src, "rb").read(); pos, w, h, idat = 8, 0, 0, b"" +while pos < len(data): + ln = struct.unpack(">I", data[pos:pos+4])[0]; tag = data[pos+4:pos+8]; chunk = data[pos+8:pos+8+ln] + if tag == b"IHDR": w, h = struct.unpack(">II", chunk[:8]) + elif tag == b"IDAT": idat += chunk + pos += 12 + ln +raw = zlib.decompress(idat) +stride0 = w*4 + 1 +raw = b"".join(raw[y*stride0+1:(y+1)*stride0] for y in range(h)) +stride = w*4 +out = bytearray([0,0,0,0])*(size*size) +for yy in range(size): + sy = yy*h//size + for xx in range(size): + sx = min(xx*w//size, w-1) + i = sy*stride + sx*4 + o = (yy*size+xx)*4 + out[o]=raw[i]; out[o+1]=raw[i+1]; out[o+2]=raw[i+2]; out[o+3]=raw[i+3] +def chunk(tag, data): + c = struct.pack(">I", len(data))+tag+data; c += struct.pack(">I", zlib.crc32(tag+data)&0xffffffff); return c +rgba = bytes(out) +raw2 = b"".join(b"\x00"+rgba[y*size*4:(y+1)*size*4] for y in range(size)) +png = b"\x89PNG\r\n\x1a\n"+chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0))+chunk(b"IDAT", zlib.compress(raw2,9))+chunk(b"IEND", b"") +open(dst, "wb").write(png) +PYEOF + cp "$ICONSET/icon_${s}x${s}.png" "$ICONSET/icon_${s}x${s}@2x.png" 2>/dev/null || true +done +# icns needs exact 16/32/128/256/512 + @2x +iconutil -c icns "$ICONSET" -o "$OUT/icon.icns" +rm -rf "$ICONSET" +echo " wrote $OUT/icon.icns" + +echo "==> icon.ico (multi-size, win)" +python3 - "$OUT/icon.png" "$OUT/icon.ico" <<'PYEOF' +import sys, zlib, struct +src, dst = sys.argv[1], sys.argv[2] +data = open(src, "rb").read(); pos, w, h, idat = 8, 0, 0, b"" +while pos < len(data): + ln = struct.unpack(">I", data[pos:pos+4])[0]; tag = data[pos+4:pos+8]; chunk = data[pos+8:pos+8+ln] + if tag == b"IHDR": w, h = struct.unpack(">II", chunk[:8]) + elif tag == b"IDAT": idat += chunk + pos += 12 + ln +raw = zlib.decompress(idat) +stride0 = w*4 + 1 +raw = b"".join(raw[y*stride0+1:(y+1)*stride0] for y in range(h)) +stride = w*4 + +def resize(nw, nh): + out = bytearray([0,0,0,0])*(nw*nh) + for yy in range(nh): + sy = min(yy*h//nh, h-1) + for xx in range(nw): + sx = min(xx*w//nw, w-1) + i = sy*stride + sx*4 + o = (yy*nw+xx)*4 + out[o]=raw[i]; out[o+1]=raw[i+1]; out[o+2]=raw[i+2]; out[o+3]=raw[i+3] + return bytes(out) + +def png_bytes(nw, nh, rgba): + def chunk(tag, data): + c = struct.pack(">I", len(data))+tag+data; c += struct.pack(">I", zlib.crc32(tag+data)&0xffffffff); return c + raw2 = b"".join(b"\x00"+rgba[y*nw*4:(y+1)*nw*4] for y in range(nh)) + return b"\x89PNG\r\n\x1a\n"+chunk(b"IHDR", struct.pack(">IIBBBBB", nw, nh, 8, 6, 0, 0, 0))+chunk(b"IDAT", zlib.compress(raw2,9))+chunk(b"IEND", b"") + +# ICO: header + directory + PNG-embedded entries +sizes = [16, 24, 32, 48, 64, 128, 256] +imgs = [(s, png_bytes(s, s, resize(s, s))) for s in sizes] +header = struct.pack(" assets:" +ls -la "$OUT" From 499f00f4008c2fd5fc12bf1ddc9a77279ddd2106 Mon Sep 17 00:00:00 2001 From: argszero Date: Tue, 4 Aug 2026 23:18:32 +0800 Subject: [PATCH 2/4] =?UTF-8?q?emrg:=20Phase=204=20=E6=89=93=E5=8C=85?= =?UTF-8?q?=E9=93=BE=E8=B7=AF=E6=94=B6=E5=B0=BE=20=E2=80=94=20GUI=20target?= =?UTF-8?q?=20=E6=94=B9=20dir=20+=20make-installer=20=E7=BB=84=E8=A3=85=20?= =?UTF-8?q?GUI/=E5=8D=B8=E8=BD=BD=E5=99=A8=EF=BC=88R97=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- emrg/gui/package.json | 6 +- packaging/make-installer.sh | 127 ++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 8 deletions(-) diff --git a/emrg/gui/package.json b/emrg/gui/package.json index ef7f356b..95cb8af5 100644 --- a/emrg/gui/package.json +++ b/emrg/gui/package.json @@ -43,7 +43,7 @@ "identity": null, "target": [ { - "target": "dmg", + "target": "dir", "arch": [ "arm64", "x64" @@ -55,7 +55,7 @@ "win": { "target": [ { - "target": "nsis", + "target": "dir", "arch": [ "x64" ] @@ -80,4 +80,4 @@ "perMachine": false } } -} +} \ No newline at end of file diff --git a/packaging/make-installer.sh b/packaging/make-installer.sh index 6aa899d9..e638087e 100755 --- a/packaging/make-installer.sh +++ b/packaging/make-installer.sh @@ -6,10 +6,16 @@ # R67: postinstall $HOME 陷阱(提权时取控制台用户真实 HOME) # R105: root 复制后 chown 回用户 # Windows: Inno Setup(R55 免 UAC;R87 {userhome} Inno 6.1+ fallback) +# GUI win-unpacked → install/emrg-gui/(R97) # Linux: AppImage(自解压归 GUI main.js §5)+ tar.gz 兜底(R83d 冒烟用) # # Artifact naming (R103): EMRG--macos-arm64.pkg / EMRG--windows-x64.exe / # EMRG--linux-x86_64.AppImage + .tar.gz +# +# Usage: bash packaging/make-installer.sh [darwin|linux|windows] +# darwin: needs pkgbuild (macOS). GUI from emrg/gui/dist/mac*/EMRG.app +# windows: needs iscc (Inno Setup 6) + GUI win-unpacked from emrg/gui/dist/win-unpacked +# linux: tarball of runtime (AppImage built separately by electron-builder) set -euo pipefail @@ -24,10 +30,53 @@ mkdir -p "$DIST/artifacts" case "$PLATFORM" in darwin|macos) echo "==> macOS pkg (user-level, R54/R104/R105/R67)" - # payload: runtime → 临时目录;postinstall 复制到用户 HOME + # GUI 产物(electron-builder dir 输出,arch 目录 mac-arm64 或 mac-x64) + GUI_APP="$(ls -d "$ROOT"/emrg/gui/dist/mac*/EMRG.app 2>/dev/null | head -1 || true)" + if [ -z "$GUI_APP" ]; then + echo "!! EMRG.app not found (run: cd emrg/gui && npm run dist first)" >&2 + exit 1 + fi PKG_ROOT="$(mktemp -d)" - mkdir -p "$PKG_ROOT/payload/runtime" + mkdir -p "$PKG_ROOT/payload/runtime" "$PKG_ROOT/payload/runtime/emrg-gui" cp -R "$RUNTIME/." "$PKG_ROOT/payload/runtime/" + cp -R "$GUI_APP" "$PKG_ROOT/payload/runtime/emrg-gui/EMRG.app" + # 生成"卸载 EMRG.app"(R30/R31/R102:bash 包装调 emrg-uninstall + 删主 GUI + 提示拖废纸篓) + UNINSTALL_APP="$PKG_ROOT/payload/runtime/emrg-gui/卸载 EMRG.app" + mkdir -p "$UNINSTALL_APP/Contents/MacOS" + cat > "$UNINSTALL_APP/Contents/Info.plist" <<'EOF' + + + + + CFBundleExecutableuninstall + CFBundleIdentifiercom.argszero.emrg.uninstall + CFBundleName卸载 EMRG + CFBundlePackageTypeAPPL + LSMinimumSystemVersion11.0 + + +EOF + cat > "$UNINSTALL_APP/Contents/MacOS/uninstall" <<'EOF' +#!/bin/bash +# 卸载 EMRG(R30/R31/R102)——bash 包装,双击运行 +# 调统一卸载脚本 emrg-uninstall(R58)→ 删主 GUI → 提示拖本 app 进废纸篓 +set +e +USER="$(stat -f "%Su" /dev/console 2>/dev/null || echo "$USER")" +HOME_DIR="$(dscl . -read "/Users/$USER" NFSHomeDirectory 2>/dev/null | awk '{print $2}')" +[ -z "$HOME_DIR" ] && HOME_DIR="$HOME" +UNINST="$HOME_DIR/.emrg/install/bin/emrg-uninstall" +if [ -x "$UNINST" ]; then + # R15:卸载脚本需自设 PYTHONPATH + export PYTHONPATH="$HOME_DIR/.emrg/install/source:$HOME_DIR/.emrg/install/lib" + "$UNINST" 2>&1 +fi +# R102:删主 GUI(未运行时可直接删) +rm -rf "$HOME_DIR/Applications/EMRG.app" 2>/dev/null +osascript -e 'display dialog "EMRG 已卸载。请将「卸载 EMRG」图标拖入废纸篓以完成删除。" buttons {"好"} default button 1' 2>/dev/null || \ + echo "EMRG 已卸载。请将「卸载 EMRG」图标拖入废纸篓。" +exit 0 +EOF + chmod +x "$UNINSTALL_APP/Contents/MacOS/uninstall" cat > "$PKG_ROOT/scripts/postinstall" <<'EOF' #!/bin/bash # R67: GUI 安装器可能提权($HOME=/var/root)→ 取控制台用户真实 HOME @@ -47,22 +96,90 @@ if [ -d "/tmp/emrg-payload/runtime/emrg-gui/EMRG.app" ]; then cp -R "/tmp/emrg-payload/runtime/emrg-gui/EMRG.app" "$HOME_DIR/Applications/" chown -R "$USER":staff "$HOME_DIR/Applications/EMRG.app" 2>/dev/null || true fi +# ③ 卸载 EMRG.app(R30:pkg 无原生卸载器,放置卸载 app) +if [ -d "/tmp/emrg-payload/runtime/emrg-gui/卸载 EMRG.app" ]; then + cp -R "/tmp/emrg-payload/runtime/emrg-gui/卸载 EMRG.app" "$HOME_DIR/Applications/" + chown -R "$USER":staff "$HOME_DIR/Applications/卸载 EMRG.app" 2>/dev/null || true +fi exit 0 EOF chmod +x "$PKG_ROOT/scripts/postinstall" - cp -R "$PKG_ROOT/payload/runtime" /tmp/emrg-payload 2>/dev/null || cp -R "$PKG_ROOT/payload/runtime" "$PKG_ROOT/payload/runtime" + rm -rf /tmp/emrg-payload + cp -R "$PKG_ROOT/payload/runtime" /tmp/emrg-payload pkgbuild --root "$PKG_ROOT/payload" --scripts "$PKG_ROOT/scripts" \ --identifier "com.argszero.emrg" --version "$VERSION" \ "$DIST/artifacts/EMRG-$VERSION-macos-$(uname -m).pkg" - rm -rf "$PKG_ROOT" + rm -rf "$PKG_ROOT" /tmp/emrg-payload ;; + linux) echo "==> Linux tar.gz (AppImage built by electron-builder in CI)" tar -czf "$DIST/artifacts/EMRG-$VERSION-linux-$(uname -m).tar.gz" -C "$(dirname "$RUNTIME")" runtime ;; + windows|win32|mingw*|msys*) - echo "==> Windows Inno Setup script generated (R55/R87) — build in CI with iscc" + echo "==> Windows Inno Setup (R55/R87/R97)" + ISCC="${ISCC:-iscc}" + if ! command -v "$ISCC" >/dev/null 2>&1; then + echo "!! iscc (Inno Setup 6) not found — set ISCC path or install" >&2 + exit 1 + fi + WIN_UNPACKED="$ROOT/emrg/gui/dist/win-unpacked" + if [ ! -d "$WIN_UNPACKED" ]; then + echo "!! win-unpacked not found (run: cd emrg/gui && npm run dist first)" >&2 + exit 1 + fi + # 组装 Inno payload:runtime + GUI → staging(Inno 安装到 {userhome}\.emrg\install) + STAGE="$(mktemp -d)" + mkdir -p "$STAGE/payload" + cp -R "$RUNTIME/." "$STAGE/payload/" + mkdir -p "$STAGE/payload/emrg-gui" + cp -R "$WIN_UNPACKED" "$STAGE/payload/emrg-gui/EMRG" + cat > "$STAGE/emrg.iss" </dev/null + rm -rf "$STAGE" ;; + *) echo "!! unknown platform $PLATFORM" >&2; exit 1 ;; esac From c4a82d29181642e88d11149d29f64ca6af1f0bbe Mon Sep 17 00:00:00 2001 From: argszero Date: Tue, 4 Aug 2026 23:23:40 +0800 Subject: [PATCH 3/4] =?UTF-8?q?emrg:=20Phase=204=20packaging=20=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=E2=80=94=E2=80=94=E5=9B=BE=E6=A0=87=E7=94=9F=E6=88=90?= =?UTF-8?q?=20+=20Inno/pkg=20=E5=AE=8C=E6=95=B4=20+=20git=20=E6=BA=90?= =?UTF-8?q?=E7=A0=81=E7=BC=96=E8=AF=91=20+=20GUI=20dir=20=E4=BA=A7?= =?UTF-8?q?=E7=89=A9=20+=20requirements=20locks=20+=20source=20=E5=8E=BB?= =?UTF-8?q?=E5=86=97=E4=BD=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packaging/build-runtime.sh | 8 ++++-- packaging/bundle-git-gh.sh | 21 ++++++++++++-- packaging/make-installer.sh | 1 + packaging/requirements-linux-aarch64.lock | 34 +++++++++++++++++++++++ packaging/requirements-linux-x86_64.lock | 34 +++++++++++++++++++++++ packaging/requirements-macos-arm64.lock | 34 +++++++++++++++++++++++ packaging/requirements-windows-x64.lock | 34 +++++++++++++++++++++++ 7 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 packaging/requirements-linux-aarch64.lock create mode 100644 packaging/requirements-linux-x86_64.lock create mode 100644 packaging/requirements-macos-arm64.lock create mode 100644 packaging/requirements-windows-x64.lock diff --git a/packaging/build-runtime.sh b/packaging/build-runtime.sh index 691bb85b..34d5334e 100755 --- a/packaging/build-runtime.sh +++ b/packaging/build-runtime.sh @@ -48,12 +48,16 @@ cp -R "$PY_ROOT/." "$DIST/bin/python-dist/" chmod +x emrg emrgd emrg-uninstall ) -# ── 3. source/(只读,排除 gui node_modules R14)── +# ── 3. source/(只读,排除 gui node_modules R14;⚠️ 只含 emrg/ 源码,不含 bin/ —— +# 启动脚本已在 bin/ 顶层,source 里再放一份是冗余(pkg 双份))── echo "==> copying source" (cd "$ROOT" && tar --exclude='emrg/gui/node_modules' --exclude='emrg/gui/dist' \ --exclude='.git' --exclude='dist' --exclude='.venv' \ - -cf - emrg bin | (cd "$DIST/source" && tar -xf -)) + --exclude='emrg/__pycache__' --exclude='emrg/**/__pycache__' --exclude='emrg/**/*.pyc' \ + -cf - emrg | (cd "$DIST/source" && tar -xf -)) touch "$DIST/source/py.typed" +# LICENSE(若存在,否则占位) +if [ -f "$ROOT/LICENSE" ]; then cp "$ROOT/LICENSE" "$DIST/source/LICENSE"; fi # ── 4. lib/(pip --target 全量含传递依赖,R3/R43)── echo "==> installing deps to lib/" diff --git a/packaging/bundle-git-gh.sh b/packaging/bundle-git-gh.sh index f6849fc2..ba84c645 100755 --- a/packaging/bundle-git-gh.sh +++ b/packaging/bundle-git-gh.sh @@ -67,8 +67,25 @@ case "$PLATFORM" in rm -rf "$TMP" ;; darwin|macos|linux) - echo "!! git source build required on $PLATFORM (R59: no official portable binary)" - echo " CI provides the build; local dev should use system git." + # R59:无官方便携二进制 → CI 源码编译。本地开发跳过(用系统 git)。 + if [ "${CI:-}" != "true" ]; then + echo "!! git source build is CI-only (R59). Local dev uses system git." >&2 + echo " Set CI=true to force a source build." >&2 + exit 0 + fi + echo "==> building git from source (R59, ~3-5min)" + GIT_VERSION="${GIT_VERSION:-2.46.0}" + TMP="$(mktemp -d)" + curl -sL "https://github.com/git/git/archive/refs/tags/v${GIT_VERSION}.tar.gz" -o "$TMP/git.tgz" + tar -xzf "$TMP/git.tgz" -C "$TMP" + cd "$TMP/git-${GIT_VERSION}" + make configure >/dev/null 2>&1 || ./configure --prefix="$TMP/prefix" >/dev/null + make -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" prefix="$TMP/prefix" install >/dev/null 2>&1 + cp "$TMP/prefix/bin/git" "$RUNTIME/bin/git" + chmod +x "$RUNTIME/bin/git" + # macOS: git 依赖系统库,产物跨版本可移植;Linux: 需静态(musl)——CI 用静态基础镜像 + rm -rf "$TMP" + echo " git built: $("$RUNTIME/bin/git" --version 2>/dev/null || echo 'check failed')" ;; esac diff --git a/packaging/make-installer.sh b/packaging/make-installer.sh index e638087e..206db4df 100755 --- a/packaging/make-installer.sh +++ b/packaging/make-installer.sh @@ -77,6 +77,7 @@ osascript -e 'display dialog "EMRG 已卸载。请将「卸载 EMRG」图标拖 exit 0 EOF chmod +x "$UNINSTALL_APP/Contents/MacOS/uninstall" + mkdir -p "$PKG_ROOT/scripts" cat > "$PKG_ROOT/scripts/postinstall" <<'EOF' #!/bin/bash # R67: GUI 安装器可能提权($HOME=/var/root)→ 取控制台用户真实 HOME diff --git a/packaging/requirements-linux-aarch64.lock b/packaging/requirements-linux-aarch64.lock new file mode 100644 index 00000000..7d5a1856 --- /dev/null +++ b/packaging/requirements-linux-aarch64.lock @@ -0,0 +1,34 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python-version 3.13 --python-platform aarch64-unknown-linux-gnu -o packaging/requirements-linux-aarch64.lock +anyio==4.14.2 + # via httpx +certifi==2026.7.22 + # via + # httpcore + # httpx +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via emrg (pyproject.toml) +idna==3.18 + # via + # anyio + # httpx +jinja2==3.1.6 + # via emrg (pyproject.toml) +markdown-it-py==4.2.0 + # via rich +markupsafe==3.0.3 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +pygments==2.20.0 + # via rich +pyyaml==6.0.3 + # via emrg (pyproject.toml) +rich==15.0.0 + # via emrg (pyproject.toml) +websockets==17.0.1 + # via emrg (pyproject.toml) diff --git a/packaging/requirements-linux-x86_64.lock b/packaging/requirements-linux-x86_64.lock new file mode 100644 index 00000000..fcf376be --- /dev/null +++ b/packaging/requirements-linux-x86_64.lock @@ -0,0 +1,34 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python-version 3.13 --python-platform x86_64-unknown-linux-gnu -o packaging/requirements-linux-x86_64.lock +anyio==4.14.2 + # via httpx +certifi==2026.7.22 + # via + # httpcore + # httpx +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via emrg (pyproject.toml) +idna==3.18 + # via + # anyio + # httpx +jinja2==3.1.6 + # via emrg (pyproject.toml) +markdown-it-py==4.2.0 + # via rich +markupsafe==3.0.3 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +pygments==2.20.0 + # via rich +pyyaml==6.0.3 + # via emrg (pyproject.toml) +rich==15.0.0 + # via emrg (pyproject.toml) +websockets==17.0.1 + # via emrg (pyproject.toml) diff --git a/packaging/requirements-macos-arm64.lock b/packaging/requirements-macos-arm64.lock new file mode 100644 index 00000000..37cb9fad --- /dev/null +++ b/packaging/requirements-macos-arm64.lock @@ -0,0 +1,34 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python-version 3.13 --python-platform aarch64-apple-darwin -o packaging/requirements-macos-arm64.lock +anyio==4.14.2 + # via httpx +certifi==2026.7.22 + # via + # httpcore + # httpx +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via emrg (pyproject.toml) +idna==3.18 + # via + # anyio + # httpx +jinja2==3.1.6 + # via emrg (pyproject.toml) +markdown-it-py==4.2.0 + # via rich +markupsafe==3.0.3 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +pygments==2.20.0 + # via rich +pyyaml==6.0.3 + # via emrg (pyproject.toml) +rich==15.0.0 + # via emrg (pyproject.toml) +websockets==17.0.1 + # via emrg (pyproject.toml) diff --git a/packaging/requirements-windows-x64.lock b/packaging/requirements-windows-x64.lock new file mode 100644 index 00000000..306a658a --- /dev/null +++ b/packaging/requirements-windows-x64.lock @@ -0,0 +1,34 @@ +# This file was autogenerated by uv via the following command: +# uv pip compile pyproject.toml --python-version 3.13 --python-platform x86_64-pc-windows-msvc -o packaging/requirements-windows-x64.lock +anyio==4.14.2 + # via httpx +certifi==2026.7.22 + # via + # httpcore + # httpx +h11==0.16.0 + # via httpcore +httpcore==1.0.9 + # via httpx +httpx==0.28.1 + # via emrg (pyproject.toml) +idna==3.18 + # via + # anyio + # httpx +jinja2==3.1.6 + # via emrg (pyproject.toml) +markdown-it-py==4.2.0 + # via rich +markupsafe==3.0.3 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +pygments==2.20.0 + # via rich +pyyaml==6.0.3 + # via emrg (pyproject.toml) +rich==15.0.0 + # via emrg (pyproject.toml) +websockets==17.0.1 + # via emrg (pyproject.toml) From ef9f9a91dfbe1a01bd23ff538877c7506c07840c Mon Sep 17 00:00:00 2001 From: argszero Date: Tue, 4 Aug 2026 23:26:45 +0800 Subject: [PATCH 4/4] =?UTF-8?q?emrg:=20.gitignore=20=E5=BF=BD=E7=95=A5=20e?= =?UTF-8?q?mrg/gui/dist/=20=E6=9E=84=E5=BB=BA=E4=BA=A7=E7=89=A9=EF=BC=88el?= =?UTF-8?q?ectron-builder=20=E8=BE=93=E5=87=BA=20234MB=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 30a14ded..df54b9f7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ node_modules/ .claude .pytest_cache/ /dist/ +/emrg/gui/dist/