Release 2.2.1: universal macOS DMG and arch install fix.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -7,14 +7,34 @@
|
||||
| OS | Артефакты | UI |
|
||||
|----|----------|----|
|
||||
| Windows amd64 | `Navis.exe` | GUI (WebView2) |
|
||||
| macOS arm64 | `Navis` · **`Navis.dmg`** · `Navis.app.zip` | CLI / .app |
|
||||
| macOS amd64 | `Navis` · **`Navis.dmg`** · `Navis.app.zip` | CLI / .app |
|
||||
| macOS universal | `Navis.dmg` · `Navis.app.zip` | CLI / .app — **рекомендуется** |
|
||||
| macOS arm64 | `Navis` · `Navis.dmg` · `Navis.app.zip` | CLI / .app |
|
||||
| macOS amd64 | `Navis` · `Navis.dmg` · `Navis.app.zip` | CLI / .app |
|
||||
|
||||
## Скачать macOS прямо с git
|
||||
|
||||
Репозиторий: https://git.evilfox.cc/test2/navi
|
||||
|
||||
### 1. Узнайте архитектуру Mac
|
||||
### Быстрая установка (автовыбор архитектуры)
|
||||
|
||||
```bash
|
||||
curl -fsSL "https://git.evilfox.cc/test2/navi/raw/branch/main/scripts/install-macos.sh" | bash
|
||||
```
|
||||
|
||||
Скрипт скачает **универсальный DMG** (работает на Intel и Apple Silicon) и откроет его.
|
||||
|
||||
### Универсальный DMG (рекомендуется)
|
||||
|
||||
Подходит для **всех** Mac — M1/M2/M3/M4 и Intel:
|
||||
|
||||
```bash
|
||||
cd ~/Downloads
|
||||
curl -fL -o Navis.dmg \
|
||||
"https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg"
|
||||
open Navis.dmg
|
||||
```
|
||||
|
||||
### 1. Узнайте архитектуру Mac (если нужна отдельная сборка)
|
||||
|
||||
В Терминале:
|
||||
|
||||
@@ -25,7 +45,9 @@ uname -m
|
||||
- `arm64` → Apple Silicon (M1/M2/M3/M4) → папка **darwin-arm64**
|
||||
- `x86_64` → Intel → папка **darwin-amd64**
|
||||
|
||||
### 2a. Скачать DMG (удобнее)
|
||||
> **Важно:** на Mac M4 нельзя ставить сборку из `darwin-amd64` — иконка будет с перечёркиванием. Используйте **darwin-universal** или **darwin-arm64**.
|
||||
|
||||
### 2a. Скачать DMG для конкретной архитектуры
|
||||
|
||||
**Apple Silicon:**
|
||||
|
||||
@@ -153,6 +175,7 @@ cd ~/Navis
|
||||
|
||||
| Архитектура | CLI | DMG | ZIP (.app) |
|
||||
|-------------|-----|-----|------------|
|
||||
| **universal** | [Navis](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis) | [Navis.dmg](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg) | [Navis.app.zip](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.app.zip) |
|
||||
| arm64 | [Navis](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis) | [Navis.dmg](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg) | [Navis.app.zip](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip) |
|
||||
| amd64 | [Navis](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis) | [Navis.dmg](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg) | [Navis.app.zip](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.app.zip) |
|
||||
| манифест | [update.json](https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json) | | |
|
||||
@@ -210,6 +233,9 @@ https://evilfox.win/
|
||||
|
||||
Некоторые AV (Bkav, Microsoft Wacapew/Wacatac, Ikarus Trojan.WinGo.Agent, Google, Trapmine) часто помечают **любые** неподписанные Go-бинарники с сетью и сменой системного прокси.
|
||||
|
||||
В 2.2.1:
|
||||
- универсальный macOS DMG (Intel + Apple Silicon), скрипт автоустановки, предупреждения при неверной архитектуре.
|
||||
|
||||
В 2.2.0:
|
||||
- компактный список нод с пингом (как в Happ);
|
||||
- параллельный пинг, кнопка «Лучший», автоподключение к серверу с минимальной задержкой после подписки.
|
||||
|
||||
+11
-2
@@ -4,6 +4,7 @@ cd /d "%~dp0"
|
||||
|
||||
mkdir "dist\navis-release\darwin-arm64" 2>nul
|
||||
mkdir "dist\navis-release\darwin-amd64" 2>nul
|
||||
mkdir "dist\navis-release\darwin-universal" 2>nul
|
||||
|
||||
set CGO_ENABLED=0
|
||||
set GOOS=darwin
|
||||
@@ -19,15 +20,23 @@ set GOOS=
|
||||
set GOARCH=
|
||||
set CGO_ENABLED=
|
||||
|
||||
go build -o "tools\mklipo\mklipo.exe" .\tools\mklipo
|
||||
if errorlevel 1 exit /b 1
|
||||
tools\mklipo\mklipo.exe "dist\navis-release\darwin-amd64\Navis" "dist\navis-release\darwin-arm64\Navis" "dist\navis-release\darwin-universal\Navis"
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
go build -o "tools\packmac\packmac.exe" .\tools\packmac
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 2.2.0 -arch arm64
|
||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 2.2.1 -arch arm64
|
||||
if errorlevel 1 exit /b 1
|
||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 2.2.0 -arch amd64
|
||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 2.2.1 -arch amd64
|
||||
if errorlevel 1 exit /b 1
|
||||
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-universal\Navis" -out "dist\navis-release\darwin-universal" -version 2.2.1 -arch universal
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
echo Built:
|
||||
dir "dist\navis-release\darwin-universal"
|
||||
dir "dist\navis-release\darwin-arm64"
|
||||
dir "dist\navis-release\darwin-amd64"
|
||||
endlocal
|
||||
|
||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Vendored
+20
-8
@@ -1,30 +1,42 @@
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"notes": "Компактный список нод с пингом (как Happ), автовыбор и подключение к серверу с лучшим пингом",
|
||||
"version": "2.2.1",
|
||||
"notes": "Универсальный macOS DMG (Intel + Apple Silicon), скрипт автоустановки, предупреждения при неверной архитектуре",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "777564f1605209deb67b440a8f94667443498df38cef0a34a0ab8ab9922dab44",
|
||||
"sha256": "b1589bffebb7cbeee17ca5a40cedb6ca614a3580be22488505a1403e1021c2b6",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
"arch": "arm64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "5d0b0e3a2edebdb26f78eb39a7a67c6d7d7fb46beaa737869a0fec1150da3935",
|
||||
"sha256": "149258fbad816aa2e73384da492bc91e3bf6700d4d01d55c9f35a3f68998232c",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
"arch": "amd64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.app.zip"
|
||||
},
|
||||
"darwin-universal": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
|
||||
"sha256": "37ceb0e47cd542dadcd406cedecc760d9aa71a40f0b109f81d560de3a4eba79",
|
||||
"os": "darwin",
|
||||
"arch": "universal",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.app.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+20
-8
@@ -1,30 +1,42 @@
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"notes": "Компактный список нод с пингом (как Happ), автовыбор и подключение к серверу с лучшим пингом",
|
||||
"version": "2.2.1",
|
||||
"notes": "Универсальный macOS DMG (Intel + Apple Silicon), скрипт автоустановки, предупреждения при неверной архитектуре",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "777564f1605209deb67b440a8f94667443498df38cef0a34a0ab8ab9922dab44",
|
||||
"sha256": "b1589bffebb7cbeee17ca5a40cedb6ca614a3580be22488505a1403e1021c2b6",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
"arch": "arm64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "5d0b0e3a2edebdb26f78eb39a7a67c6d7d7fb46beaa737869a0fec1150da3935",
|
||||
"sha256": "149258fbad816aa2e73384da492bc91e3bf6700d4d01d55c9f35a3f68998232c",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
"arch": "amd64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.app.zip"
|
||||
},
|
||||
"darwin-universal": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
|
||||
"sha256": "37ceb0e47cd542dadcd406cedecc760d9aa71a40f0b109f81d560de3a4eba79",
|
||||
"os": "darwin",
|
||||
"arch": "universal",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.app.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,7 +725,7 @@
|
||||
<div class="brand-wrap">
|
||||
<div class="brand-row">
|
||||
<h1 class="brand">Navis</h1>
|
||||
<span class="badge-ver">2.2</span>
|
||||
<span class="badge-ver">2.2.1</span>
|
||||
</div>
|
||||
<p class="tagline">Быстрый клиент · Naive · Hy2 · AWG · Xray</p>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// CurrentVersion is the shipped client version.
|
||||
const CurrentVersion = "2.2.0"
|
||||
const CurrentVersion = "2.2.1"
|
||||
|
||||
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
||||
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
BASE="https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release"
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
case "$ARCH" in
|
||||
arm64)
|
||||
SUBDIR="darwin-arm64"
|
||||
;;
|
||||
x86_64)
|
||||
SUBDIR="darwin-amd64"
|
||||
;;
|
||||
*)
|
||||
echo "Неподдерживаемая архитектура: $ARCH" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
DEST="${1:-$HOME/Downloads/Navis.dmg}"
|
||||
UNIVERSAL="$BASE/darwin-universal/Navis.dmg"
|
||||
SPECIFIC="$BASE/$SUBDIR/Navis.dmg"
|
||||
|
||||
echo "Mac: $ARCH"
|
||||
echo "Рекомендуется универсальный DMG (Intel + Apple Silicon)…"
|
||||
if curl -fL -o "$DEST" "$UNIVERSAL"; then
|
||||
echo "Скачан: $DEST"
|
||||
else
|
||||
echo "Универсальный DMG недоступен, скачиваю $SUBDIR…"
|
||||
curl -fL -o "$DEST" "$SPECIFIC"
|
||||
fi
|
||||
|
||||
open "$DEST"
|
||||
echo "Откройте диск и перетащите Navis.app в Программы."
|
||||
@@ -6,6 +6,7 @@
|
||||
- Windows: `…/dist/navis-release/Navis.exe`
|
||||
- macOS arm64: `…/dist/navis-release/darwin-arm64/Navis`
|
||||
- macOS amd64: `…/dist/navis-release/darwin-amd64/Navis`
|
||||
- macOS universal (рекомендуется): `…/dist/navis-release/darwin-universal/Navis.dmg`
|
||||
|
||||
Пример `dist/update.json` (multi-platform + legacy url для старых клиентов):
|
||||
|
||||
|
||||
+20
-8
@@ -1,30 +1,42 @@
|
||||
{
|
||||
"version": "2.2.0",
|
||||
"notes": "Компактный список нод с пингом (как Happ), автовыбор и подключение к серверу с лучшим пингом",
|
||||
"version": "2.2.1",
|
||||
"notes": "Универсальный macOS DMG (Intel + Apple Silicon), скрипт автоустановки, предупреждения при неверной архитектуре",
|
||||
"platform": "windows-amd64",
|
||||
"os": "windows",
|
||||
"arch": "amd64",
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"mandatory": false,
|
||||
"platforms": {
|
||||
"windows-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/Navis.exe",
|
||||
"sha256": "acd3a57cb52d745ecd0dc24074cfbd0299820d863ce00c2d4ce7753fb7dc73f3",
|
||||
"sha256": "993e17d6390c8a4378e51016012006f18db1f6bd7c25957a4bf82fe31ab63473",
|
||||
"os": "windows",
|
||||
"arch": "amd64"
|
||||
},
|
||||
"darwin-arm64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||
"sha256": "777564f1605209deb67b440a8f94667443498df38cef0a34a0ab8ab9922dab44",
|
||||
"sha256": "b1589bffebb7cbeee17ca5a40cedb6ca614a3580be22488505a1403e1021c2b6",
|
||||
"os": "darwin",
|
||||
"arch": "arm64"
|
||||
"arch": "arm64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.app.zip"
|
||||
},
|
||||
"darwin-amd64": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis",
|
||||
"sha256": "5d0b0e3a2edebdb26f78eb39a7a67c6d7d7fb46beaa737869a0fec1150da3935",
|
||||
"sha256": "149258fbad816aa2e73384da492bc91e3bf6700d4d01d55c9f35a3f68998232c",
|
||||
"os": "darwin",
|
||||
"arch": "amd64"
|
||||
"arch": "amd64",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-amd64/Navis.app.zip"
|
||||
},
|
||||
"darwin-universal": {
|
||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis",
|
||||
"sha256": "37ceb0e47cd542dadcd406cedecc760d9aa71a40f0b109f81d560de3a4eba79",
|
||||
"os": "darwin",
|
||||
"arch": "universal",
|
||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg",
|
||||
"zip_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.app.zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// mklipo merges two Mach-O binaries into one macOS universal (fat) binary.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
fatMagic = 0xCAFEBABE
|
||||
cpuTypeX86_64 = 0x01000007
|
||||
cpuTypeARM64 = 0x0100000c
|
||||
fatArchSize = 20
|
||||
)
|
||||
|
||||
type slice struct {
|
||||
cpu, sub uint32
|
||||
data []byte
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 4 {
|
||||
fmt.Fprintln(os.Stderr, "usage: mklipo <amd64-bin> <arm64-bin> <out>")
|
||||
os.Exit(2)
|
||||
}
|
||||
amd, err := os.ReadFile(os.Args[1])
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
arm, err := os.ReadFile(os.Args[2])
|
||||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
if err := writeFat(os.Args[3], []slice{
|
||||
{cpuTypeX86_64, 3, amd},
|
||||
{cpuTypeARM64, 0, arm},
|
||||
}); err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func writeFat(path string, parts []slice) error {
|
||||
const align uint32 = 0x4000
|
||||
hdr := 8 + fatArchSize*len(parts)
|
||||
offsets := make([]uint32, len(parts))
|
||||
cur := uint32(hdr)
|
||||
for i, p := range parts {
|
||||
pad := (align - (cur % align)) % align
|
||||
cur += pad
|
||||
offsets[i] = cur
|
||||
cur += uint32(len(p.data))
|
||||
}
|
||||
|
||||
out, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(fatMagic)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(len(parts))); err != nil {
|
||||
return err
|
||||
}
|
||||
for i, p := range parts {
|
||||
if err := binary.Write(out, binary.BigEndian, p.cpu); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, p.sub); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, offsets[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, uint32(len(p.data))); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binary.Write(out, binary.BigEndian, align); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cur = uint32(hdr)
|
||||
for _, p := range parts {
|
||||
pad := (align - (cur % align)) % align
|
||||
if pad > 0 {
|
||||
if _, err := out.Write(make([]byte, pad)); err != nil {
|
||||
return err
|
||||
}
|
||||
cur += pad
|
||||
}
|
||||
if _, err := out.Write(p.data); err != nil {
|
||||
return err
|
||||
}
|
||||
cur += uint32(len(p.data))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fatal(err error) {
|
||||
fmt.Fprintln(os.Stderr, "mklipo:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
+149
-24
@@ -42,33 +42,49 @@ func run(binPath, outDir, version, arch string) error {
|
||||
defer os.RemoveAll(stage)
|
||||
|
||||
appRoot := filepath.Join(stage, "Navis.app")
|
||||
if err := writeAppBundle(appRoot, binPath, version); err != nil {
|
||||
if err := writeAppBundle(appRoot, binPath, version, arch); err != nil {
|
||||
return err
|
||||
}
|
||||
readme := filepath.Join(stage, "README.txt")
|
||||
if err := os.WriteFile(readme, []byte(readmeText(version, arch)), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
warnName := archWarningFilename(arch)
|
||||
if warnName != "" {
|
||||
if err := os.WriteFile(filepath.Join(stage, warnName), []byte(archWarningText(arch)), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
zipEntries := []string{"Navis.app", "README.txt"}
|
||||
if warnName != "" {
|
||||
zipEntries = append(zipEntries, warnName)
|
||||
}
|
||||
zipPath := filepath.Join(outDir, "Navis.app.zip")
|
||||
if err := zipDir(zipPath, stage, []string{"Navis.app", "README.txt"}); err != nil {
|
||||
if err := zipDir(zipPath, stage, zipEntries); err != nil {
|
||||
return fmt.Errorf("zip: %w", err)
|
||||
}
|
||||
fmt.Println("wrote", zipPath)
|
||||
|
||||
dmgPath := filepath.Join(outDir, "Navis.dmg")
|
||||
if err := writeDMG(dmgPath, appRoot, readme, "Navis-"+arch); err != nil {
|
||||
dmgFiles := []dmgEntry{{appRoot, "/Navis.app"}}
|
||||
if warnName != "" {
|
||||
dmgFiles = append(dmgFiles, dmgEntry{filepath.Join(stage, warnName), "/" + warnName})
|
||||
}
|
||||
dmgFiles = append(dmgFiles, dmgEntry{readme, "/README.txt"})
|
||||
if err := writeDMG(dmgPath, dmgFiles, "Navis-"+arch); err != nil {
|
||||
return fmt.Errorf("dmg: %w", err)
|
||||
}
|
||||
fmt.Println("wrote", dmgPath)
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeAppBundle(appRoot, binPath, version string) error {
|
||||
func writeAppBundle(appRoot, binPath, version, arch string) error {
|
||||
macOSDir := filepath.Join(appRoot, "Contents", "MacOS")
|
||||
if err := os.MkdirAll(macOSDir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
archPriority := architecturePriorityXML(arch)
|
||||
plist := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -80,10 +96,10 @@ func writeAppBundle(appRoot, binPath, version string) error {
|
||||
<key>CFBundleShortVersionString</key><string>%s</string>
|
||||
<key>CFBundleVersion</key><string>%s</string>
|
||||
<key>LSMinimumSystemVersion</key><string>11.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>%s
|
||||
</dict>
|
||||
</plist>
|
||||
`, version, version)
|
||||
`, version, version, archPriority)
|
||||
if err := os.WriteFile(filepath.Join(appRoot, "Contents", "Info.plist"), []byte(plist), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -94,21 +110,25 @@ func writeAppBundle(appRoot, binPath, version string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeDMG(dmgPath, appRoot, readmePath, volume string) error {
|
||||
type dmgEntry struct {
|
||||
srcPath string
|
||||
dstPath string
|
||||
}
|
||||
|
||||
func writeDMG(dmgPath string, files []dmgEntry, volume string) error {
|
||||
_ = os.Remove(dmgPath)
|
||||
appSize, err := dirSize(appRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
var need int64
|
||||
for _, f := range files {
|
||||
if fi, err := os.Stat(f.srcPath); err == nil && !fi.IsDir() {
|
||||
need += fi.Size()
|
||||
} else if sz, err := dirSize(f.srcPath); err == nil {
|
||||
need += sz
|
||||
}
|
||||
readmeSize, err := fileSize(readmePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
need := appSize + readmeSize + 4*1024*1024
|
||||
need += 4 * 1024 * 1024
|
||||
if need < 12*1024*1024 {
|
||||
need = 12 * 1024 * 1024
|
||||
}
|
||||
// round up to 2048
|
||||
need = ((need + 2047) / 2048) * 2048
|
||||
|
||||
mydisk, err := diskfs.Create(dmgPath, need, diskfs.SectorSizeDefault)
|
||||
@@ -125,14 +145,24 @@ func writeDMG(dmgPath, appRoot, readmePath, volume string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copyTreeToISO(fs, appRoot, "/Navis.app"); err != nil {
|
||||
for _, f := range files {
|
||||
info, err := os.Stat(f.srcPath)
|
||||
if err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
if err := writeISOFile(fs, "/README.txt", readmePath, 0o644); err != nil {
|
||||
if info.IsDir() {
|
||||
if err := copyTreeToISO(fs, f.srcPath, f.dstPath); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err := writeISOFile(fs, f.dstPath, f.srcPath, 0o644); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
iso, ok := fs.(*iso9660.FileSystem)
|
||||
if !ok {
|
||||
@@ -336,19 +366,114 @@ func sanitizeVol(s string) string {
|
||||
}
|
||||
|
||||
func readmeText(version, arch string) string {
|
||||
return fmt.Sprintf(`Navis %s for macOS (%s)
|
||||
switch arch {
|
||||
case "universal":
|
||||
return fmt.Sprintf(`Navis %s for macOS (универсальная сборка)
|
||||
|
||||
1) Open this disk image
|
||||
2) Drag Navis.app to Applications (or any folder)
|
||||
3) First launch may need:
|
||||
Подходит для Apple Silicon (M1/M2/M3/M4) и Intel Mac.
|
||||
|
||||
1) Перетащите Navis.app в Программы (Applications)
|
||||
2) При первом запуске, если macOS блокирует:
|
||||
xattr -dr com.apple.quarantine /Applications/Navis.app
|
||||
4) Run from Terminal:
|
||||
3) В Терминале:
|
||||
/Applications/Navis.app/Contents/MacOS/Navis init
|
||||
/Applications/Navis.app/Contents/MacOS/Navis install-core
|
||||
/Applications/Navis.app/Contents/MacOS/Navis connect
|
||||
|
||||
Or use the CLI binary next to this DMG on git (file named Navis).
|
||||
Магазин: https://evilfox.win/
|
||||
`, version)
|
||||
case "arm64":
|
||||
return fmt.Sprintf(`Navis %s for macOS (Apple Silicon: M1/M2/M3/M4)
|
||||
|
||||
Shop: https://evilfox.win/
|
||||
⚠️ Только для Mac с чипом Apple Silicon (arm64).
|
||||
На Intel Mac скачайте darwin-amd64 или darwin-universal.
|
||||
|
||||
1) Перетащите Navis.app в Программы
|
||||
2) xattr -dr com.apple.quarantine /Applications/Navis.app
|
||||
3) /Applications/Navis.app/Contents/MacOS/Navis connect
|
||||
|
||||
Магазин: https://evilfox.win/
|
||||
`, version)
|
||||
case "amd64":
|
||||
return fmt.Sprintf(`Navis %s for macOS (Intel x86_64)
|
||||
|
||||
⚠️ Только для Intel Mac.
|
||||
На Mac M1/M2/M3/M4 эта сборка НЕ запустится — скачайте darwin-arm64 или darwin-universal.
|
||||
|
||||
1) Перетащите Navis.app в Программы
|
||||
2) xattr -dr com.apple.quarantine /Applications/Navis.app
|
||||
3) /Applications/Navis.app/Contents/MacOS/Navis connect
|
||||
|
||||
Магазин: https://evilfox.win/
|
||||
`, version)
|
||||
default:
|
||||
return fmt.Sprintf(`Navis %s for macOS (%s)
|
||||
|
||||
1) Drag Navis.app to Applications
|
||||
2) xattr -dr com.apple.quarantine /Applications/Navis.app
|
||||
3) /Applications/Navis.app/Contents/MacOS/Navis connect
|
||||
`, version, arch)
|
||||
}
|
||||
}
|
||||
|
||||
func archWarningFilename(arch string) string {
|
||||
switch arch {
|
||||
case "amd64":
|
||||
return "ТОЛЬКО-INTEL-MAC.txt"
|
||||
case "arm64":
|
||||
return "ТОЛЬКО-APPLE-SILICON.txt"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func archWarningText(arch string) string {
|
||||
switch arch {
|
||||
case "amd64":
|
||||
return `ВНИМАНИЕ
|
||||
|
||||
Эта сборка Navis только для Intel Mac (x86_64).
|
||||
|
||||
Если у вас Mac mini / MacBook с чипом M1, M2, M3 или M4 —
|
||||
закройте этот диск и скачайте универсальный DMG:
|
||||
|
||||
https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg
|
||||
|
||||
Или arm64:
|
||||
https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg
|
||||
`
|
||||
case "arm64":
|
||||
return `ВНИМАНИЕ
|
||||
|
||||
Эта сборка Navis только для Apple Silicon (M1/M2/M3/M4).
|
||||
|
||||
Если у вас Intel Mac — скачайте darwin-amd64 или универсальный DMG:
|
||||
|
||||
https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-universal/Navis.dmg
|
||||
`
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func architecturePriorityXML(arch string) string {
|
||||
switch arch {
|
||||
case "universal":
|
||||
return `
|
||||
<key>LSArchitecturePriority</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>`
|
||||
case "arm64":
|
||||
return `
|
||||
<key>LSArchitecturePriority</key>
|
||||
<array><string>arm64</string></array>`
|
||||
case "amd64":
|
||||
return `
|
||||
<key>LSArchitecturePriority</key>
|
||||
<array><string>x86_64</string></array>`
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"FixedFileInfo": {
|
||||
"FileVersion": { "Major": 2, "Minor": 2, "Patch": 0, "Build": 0 },
|
||||
"ProductVersion": { "Major": 2, "Minor": 2, "Patch": 0, "Build": 0 },
|
||||
"FileVersion": { "Major": 2, "Minor": 2, "Patch": 1, "Build": 0 },
|
||||
"ProductVersion": { "Major": 2, "Minor": 2, "Patch": 1, "Build": 0 },
|
||||
"FileFlagsMask": "3f",
|
||||
"FileFlags": "00",
|
||||
"FileOS": "40004",
|
||||
@@ -11,12 +11,12 @@
|
||||
"StringFileInfo": {
|
||||
"CompanyName": "EvilFox",
|
||||
"FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
||||
"FileVersion": "2.2.0.0",
|
||||
"FileVersion": "2.2.1.0",
|
||||
"InternalName": "Navis",
|
||||
"LegalCopyright": "Copyright (c) EvilFox",
|
||||
"OriginalFilename": "Navis.exe",
|
||||
"ProductName": "Navis",
|
||||
"ProductVersion": "2.2.0.0",
|
||||
"ProductVersion": "2.2.1.0",
|
||||
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
||||
},
|
||||
"VarFileInfo": {
|
||||
|
||||
Reference in New Issue
Block a user