Release 2.2.1: universal macOS DMG and arch install fix.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Navis
2026-07-29 10:36:24 +03:00
co-authored by Cursor
parent 8c513f6e08
commit a2cdad5ebe
22 changed files with 402 additions and 66 deletions
+30 -4
View File
@@ -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
View File
@@ -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
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+20 -8
View File
@@ -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"
}
}
}
+20 -8
View File
@@ -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"
}
}
}
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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"
+34
View File
@@ -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 в Программы."
+1
View File
@@ -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
View File
@@ -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"
}
}
}
+105
View File
@@ -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
View File
@@ -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
View File
@@ -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": {