Release 2.7.1: fix macOS DMG launch, cores path and naive download.
Use UDZO DMG via hdiutil, store cores under Application Support, and match new naiveproxy mac asset names. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+3
-3
@@ -34,11 +34,11 @@ if errorlevel 1 exit /b 1
|
|||||||
go build -o "tools\packmac\packmac.exe" .\tools\packmac
|
go build -o "tools\packmac\packmac.exe" .\tools\packmac
|
||||||
if errorlevel 1 exit /b 1
|
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.7.0 -arch arm64
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-arm64\Navis" -out "dist\navis-release\darwin-arm64" -version 2.7.1 -arch arm64
|
||||||
if errorlevel 1 exit /b 1
|
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.7.0 -arch amd64
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-amd64\Navis" -out "dist\navis-release\darwin-amd64" -version 2.7.1 -arch amd64
|
||||||
if errorlevel 1 exit /b 1
|
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.7.0 -arch universal
|
tools\packmac\packmac.exe -bin "dist\navis-release\darwin-universal\Navis" -out "dist\navis-release\darwin-universal" -version 2.7.1 -arch universal
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
|
|
||||||
echo Built Mac GUI + CLI:
|
echo Built Mac GUI + CLI:
|
||||||
|
|||||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "2.7.0",
|
"version": "2.7.1",
|
||||||
"notes": "GUI на macOS (как на Windows). Откройте Navis.app — окно клиента. CLI: Navis-cli",
|
"notes": "macOS: UDZO DMG, Application Support cores path, naiveproxy asset name fix",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "dd15b856bed836b82f2892e64db4db71771a947f3a392ce7d9f9e7f1b59edf1d",
|
"sha256": "8951c351b224d8a13e2772b6ee080d7bee3285ac162dd20c0855a8653a569ec5",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64",
|
"arch": "arm64",
|
||||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||||
|
|||||||
Vendored
+3
-3
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"version": "2.7.0",
|
"version": "2.7.1",
|
||||||
"notes": "GUI на macOS (как на Windows). Откройте Navis.app — окно клиента. CLI: Navis-cli",
|
"notes": "macOS: UDZO DMG, Application Support cores path, naiveproxy asset name fix",
|
||||||
"platform": "windows-amd64",
|
"platform": "windows-amd64",
|
||||||
"os": "windows",
|
"os": "windows",
|
||||||
"arch": "amd64",
|
"arch": "amd64",
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
},
|
},
|
||||||
"darwin-arm64": {
|
"darwin-arm64": {
|
||||||
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
"url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis",
|
||||||
"sha256": "dd15b856bed836b82f2892e64db4db71771a947f3a392ce7d9f9e7f1b59edf1d",
|
"sha256": "8951c351b224d8a13e2772b6ee080d7bee3285ac162dd20c0855a8653a569ec5",
|
||||||
"os": "darwin",
|
"os": "darwin",
|
||||||
"arch": "arm64",
|
"arch": "arm64",
|
||||||
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
"dmg_url": "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/navis-release/darwin-arm64/Navis.dmg",
|
||||||
|
|||||||
@@ -207,11 +207,15 @@ func (c *Config) ActiveProfile() (*Profile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ResolveBinDir returns an absolute bin directory.
|
// ResolveBinDir returns an absolute bin directory.
|
||||||
// Relative paths are resolved next to the executable (portable install layout).
|
// Relative paths are resolved next to the executable (portable install layout),
|
||||||
|
// or under ~/Library/Application Support/Navis on macOS (.app bundles are read-only).
|
||||||
func ResolveBinDir(cfgPath, binDir string) (string, error) {
|
func ResolveBinDir(cfgPath, binDir string) (string, error) {
|
||||||
if filepath.IsAbs(binDir) {
|
if filepath.IsAbs(binDir) {
|
||||||
return binDir, nil
|
return binDir, nil
|
||||||
}
|
}
|
||||||
|
if dir, ok := platformNavisDir(); ok {
|
||||||
|
return filepath.Abs(filepath.Join(dir, binDir))
|
||||||
|
}
|
||||||
if exe, err := os.Executable(); err == nil {
|
if exe, err := os.Executable(); err == nil {
|
||||||
return filepath.Abs(filepath.Join(filepath.Dir(exe), binDir))
|
return filepath.Abs(filepath.Join(filepath.Dir(exe), binDir))
|
||||||
}
|
}
|
||||||
@@ -283,9 +287,16 @@ func (c *Config) SetActiveProxy(proxy string) error {
|
|||||||
return fmt.Errorf("active profile %q not found", c.Active)
|
return fmt.Errorf("active profile %q not found", c.Active)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocateConfig finds configs/config.json next to the executable or in cwd.
|
// LocateConfig finds configs/config.json next to the executable, in cwd,
|
||||||
|
// or under ~/Library/Application Support/Navis on macOS.
|
||||||
func LocateConfig() (string, error) {
|
func LocateConfig() (string, error) {
|
||||||
candidates := []string{}
|
candidates := []string{}
|
||||||
|
if dir, ok := platformNavisDir(); ok {
|
||||||
|
candidates = append(candidates,
|
||||||
|
filepath.Join(dir, "configs", "config.json"),
|
||||||
|
filepath.Join(dir, "config.json"),
|
||||||
|
)
|
||||||
|
}
|
||||||
if exe, err := os.Executable(); err == nil {
|
if exe, err := os.Executable(); err == nil {
|
||||||
dir := filepath.Dir(exe)
|
dir := filepath.Dir(exe)
|
||||||
candidates = append(candidates,
|
candidates = append(candidates,
|
||||||
@@ -301,6 +312,9 @@ func LocateConfig() (string, error) {
|
|||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if dir, ok := platformNavisDir(); ok {
|
||||||
|
return filepath.Join(dir, "configs", "config.json"), nil
|
||||||
|
}
|
||||||
// Default path next to executable for first-run create.
|
// Default path next to executable for first-run create.
|
||||||
if exe, err := os.Executable(); err == nil {
|
if exe, err := os.Executable(); err == nil {
|
||||||
return filepath.Join(filepath.Dir(exe), "configs", "config.json"), nil
|
return filepath.Join(filepath.Dir(exe), "configs", "config.json"), nil
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
//go:build darwin
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func platformNavisDir() (string, bool) {
|
||||||
|
base, err := os.UserConfigDir()
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
return filepath.Join(base, "Navis"), true
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !darwin
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
func platformNavisDir() (string, bool) {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -90,6 +91,9 @@ func EnsureBinary(binDir string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
_ = os.Chmod(dest, 0o755)
|
_ = os.Chmod(dest, 0o755)
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
_ = exec.Command("xattr", "-dr", "com.apple.quarantine", dest).Run()
|
||||||
|
}
|
||||||
return ResolveBinary(binDir)
|
return ResolveBinary(binDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,19 @@ func EnsureBinary(binDir string) (string, error) {
|
|||||||
if err := extractNaiveArchive(archivePath, binDir); err != nil {
|
if err := extractNaiveArchive(archivePath, binDir); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return ResolveBinary(binDir)
|
path, err := ResolveBinary(binDir)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
clearQuarantine(path)
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearQuarantine(path string) {
|
||||||
|
if runtime.GOOS != "darwin" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_ = exec.Command("xattr", "-dr", "com.apple.quarantine", path).Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func assetNameForPlatform() (string, error) {
|
func assetNameForPlatform() (string, error) {
|
||||||
@@ -76,9 +88,11 @@ func assetNameForPlatform() (string, error) {
|
|||||||
case runtime.GOOS == "linux" && runtime.GOARCH == "amd64":
|
case runtime.GOOS == "linux" && runtime.GOARCH == "amd64":
|
||||||
return "naiveproxy-*-linux-x64.zip", nil
|
return "naiveproxy-*-linux-x64.zip", nil
|
||||||
case runtime.GOOS == "darwin" && runtime.GOARCH == "amd64":
|
case runtime.GOOS == "darwin" && runtime.GOARCH == "amd64":
|
||||||
return "naiveproxy-*-mac-x64.tar.xz", nil
|
// Newer releases use mac-x64-x64; older used mac-x64.
|
||||||
|
return "naiveproxy-*-mac-x64", nil
|
||||||
case runtime.GOOS == "darwin" && runtime.GOARCH == "arm64":
|
case runtime.GOOS == "darwin" && runtime.GOARCH == "arm64":
|
||||||
return "naiveproxy-*-mac-arm64.tar.xz", nil
|
// Newer releases use mac-arm64-arm64; older used mac-arm64.
|
||||||
|
return "naiveproxy-*-mac-arm64", nil
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("unsupported platform %s/%s for auto-download; place naive binary in bin/", runtime.GOOS, runtime.GOARCH)
|
return "", fmt.Errorf("unsupported platform %s/%s for auto-download; place naive binary in bin/", runtime.GOOS, runtime.GOARCH)
|
||||||
}
|
}
|
||||||
@@ -114,14 +128,32 @@ func findReleaseAsset(pattern string) (name, downloadURL string, err error) {
|
|||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
prefix := strings.Split(pattern, "*")[0]
|
prefix := strings.Split(pattern, "*")[0]
|
||||||
suffix := ""
|
needle := ""
|
||||||
if parts := strings.Split(pattern, "*"); len(parts) == 2 {
|
if parts := strings.SplitN(pattern, "*", 2); len(parts) == 2 {
|
||||||
suffix = parts[1]
|
needle = parts[1]
|
||||||
}
|
}
|
||||||
|
var bestName, bestURL string
|
||||||
for _, a := range rel.Assets {
|
for _, a := range rel.Assets {
|
||||||
if strings.HasPrefix(a.Name, prefix) && strings.HasSuffix(a.Name, suffix) {
|
name := a.Name
|
||||||
return a.Name, a.BrowserDownloadURL, nil
|
if strings.Contains(name, "plugin") {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
if !strings.HasPrefix(name, prefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if needle != "" && !strings.Contains(name, needle) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Prefer desktop archives over openwrt/apk.
|
||||||
|
if strings.HasSuffix(name, ".zip") || strings.HasSuffix(name, ".tar.xz") || strings.HasSuffix(name, ".txz") {
|
||||||
|
return name, a.BrowserDownloadURL, nil
|
||||||
|
}
|
||||||
|
if bestName == "" {
|
||||||
|
bestName, bestURL = name, a.BrowserDownloadURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bestName != "" {
|
||||||
|
return bestName, bestURL, nil
|
||||||
}
|
}
|
||||||
return "", "", fmt.Errorf("no asset matching %s in release %s", pattern, rel.TagName)
|
return "", "", fmt.Errorf("no asset matching %s in release %s", pattern, rel.TagName)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -78,6 +79,9 @@ func EnsureBinary(binDir string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = os.Chmod(dest, 0o755)
|
_ = os.Chmod(dest, 0o755)
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
_ = exec.Command("xattr", "-dr", "com.apple.quarantine", dest).Run()
|
||||||
|
}
|
||||||
return ResolveBinary(binDir)
|
return ResolveBinary(binDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CurrentVersion is the shipped client version.
|
// CurrentVersion is the shipped client version.
|
||||||
const CurrentVersion = "2.7.0"
|
const CurrentVersion = "2.7.1"
|
||||||
|
|
||||||
// DefaultManifestURL is the update feed (hosted in the project git repo).
|
// 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"
|
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
|
||||||
|
|||||||
+83
-12
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ func run(binPath, outDir, version, arch string) error {
|
|||||||
if err := writeAppBundle(appRoot, binPath, version, arch); err != nil {
|
if err := writeAppBundle(appRoot, binPath, version, arch); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := signAppBundle(appRoot); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
readme := filepath.Join(stage, "README.txt")
|
readme := filepath.Join(stage, "README.txt")
|
||||||
if err := os.WriteFile(readme, []byte(readmeText(version, arch)), 0o644); err != nil {
|
if err := os.WriteFile(readme, []byte(readmeText(version, arch)), 0o644); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -67,18 +71,58 @@ func run(binPath, outDir, version, arch string) error {
|
|||||||
fmt.Println("wrote", zipPath)
|
fmt.Println("wrote", zipPath)
|
||||||
|
|
||||||
dmgPath := filepath.Join(outDir, "Navis.dmg")
|
dmgPath := filepath.Join(outDir, "Navis.dmg")
|
||||||
dmgFiles := []dmgEntry{{appRoot, "/Navis.app"}}
|
if err := writeNativeOrISODmg(dmgPath, stage, "Navis-"+arch); err != nil {
|
||||||
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)
|
return fmt.Errorf("dmg: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Println("wrote", dmgPath)
|
fmt.Println("wrote", dmgPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeNativeOrISODmg prefers hdiutil (real UDIF DMG) on macOS; ISO9660 breaks .app launch.
|
||||||
|
func writeNativeOrISODmg(dmgPath, stageDir, volume string) error {
|
||||||
|
if _, err := exec.LookPath("hdiutil"); err == nil {
|
||||||
|
return writeHdiutilDMG(dmgPath, stageDir, volume)
|
||||||
|
}
|
||||||
|
entries := []dmgEntry{}
|
||||||
|
_ = filepath.Walk(stageDir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil || info == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rel, err := filepath.Rel(stageDir, path)
|
||||||
|
if err != nil || rel == "." {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Only top-level items for ISO packer.
|
||||||
|
if strings.Contains(rel, string(os.PathSeparator)) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
dst := "/" + filepath.ToSlash(rel)
|
||||||
|
entries = append(entries, dmgEntry{path, dst})
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return writeDMG(dmgPath, entries, volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeHdiutilDMG(dmgPath, stageDir, volume string) error {
|
||||||
|
_ = os.Remove(dmgPath)
|
||||||
|
vol := sanitizeVol(volume)
|
||||||
|
cmd := exec.Command("hdiutil", "create",
|
||||||
|
"-volname", vol,
|
||||||
|
"-srcfolder", stageDir,
|
||||||
|
"-ov",
|
||||||
|
"-format", "UDZO",
|
||||||
|
dmgPath,
|
||||||
|
)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("hdiutil: %w: %s", err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
// Re-sign after packaging is unnecessary for UDZO copy of already-signed .app,
|
||||||
|
// but clear quarantine on the dmg itself if present.
|
||||||
|
_ = exec.Command("xattr", "-cr", dmgPath).Run()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func writeAppBundle(appRoot, binPath, version, arch string) error {
|
func writeAppBundle(appRoot, binPath, version, arch string) error {
|
||||||
macOSDir := filepath.Join(appRoot, "Contents", "MacOS")
|
macOSDir := filepath.Join(appRoot, "Contents", "MacOS")
|
||||||
if err := os.MkdirAll(macOSDir, 0o755); err != nil {
|
if err := os.MkdirAll(macOSDir, 0o755); err != nil {
|
||||||
@@ -92,10 +136,12 @@ func writeAppBundle(appRoot, binPath, version, arch string) error {
|
|||||||
<key>CFBundleExecutable</key><string>Navis</string>
|
<key>CFBundleExecutable</key><string>Navis</string>
|
||||||
<key>CFBundleIdentifier</key><string>win.evilfox.navis</string>
|
<key>CFBundleIdentifier</key><string>win.evilfox.navis</string>
|
||||||
<key>CFBundleName</key><string>Navis</string>
|
<key>CFBundleName</key><string>Navis</string>
|
||||||
|
<key>CFBundleDisplayName</key><string>Navis</string>
|
||||||
<key>CFBundlePackageType</key><string>APPL</string>
|
<key>CFBundlePackageType</key><string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key><string>%s</string>
|
<key>CFBundleShortVersionString</key><string>%s</string>
|
||||||
<key>CFBundleVersion</key><string>%s</string>
|
<key>CFBundleVersion</key><string>%s</string>
|
||||||
<key>LSMinimumSystemVersion</key><string>11.0</string>
|
<key>LSMinimumSystemVersion</key><string>11.0</string>
|
||||||
|
<key>NSHighResolutionCapable</key><true/>
|
||||||
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>%s
|
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>%s
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
@@ -103,6 +149,9 @@ func writeAppBundle(appRoot, binPath, version, arch string) error {
|
|||||||
if err := os.WriteFile(filepath.Join(appRoot, "Contents", "Info.plist"), []byte(plist), 0o644); err != nil {
|
if err := os.WriteFile(filepath.Join(appRoot, "Contents", "Info.plist"), []byte(plist), 0o644); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := os.WriteFile(filepath.Join(appRoot, "Contents", "PkgInfo"), []byte("APPL????"), 0o644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
dest := filepath.Join(macOSDir, "Navis")
|
dest := filepath.Join(macOSDir, "Navis")
|
||||||
if err := copyFile(binPath, dest, 0o755); err != nil {
|
if err := copyFile(binPath, dest, 0o755); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -110,6 +159,25 @@ func writeAppBundle(appRoot, binPath, version, arch string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func signAppBundle(appRoot string) error {
|
||||||
|
if _, err := exec.LookPath("codesign"); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Fresh ad-hoc signature; entitlements not required for local/dev builds.
|
||||||
|
cmd := exec.Command("codesign", "-s", "-", "--force", "--deep", "--options", "runtime", appRoot)
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
// --options runtime can fail without a real Developer ID; retry plain ad-hoc.
|
||||||
|
cmd = exec.Command("codesign", "-s", "-", "--force", "--deep", appRoot)
|
||||||
|
out, err = cmd.CombinedOutput()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("codesign %s: %w: %s", appRoot, err, strings.TrimSpace(string(out)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = exec.Command("xattr", "-cr", appRoot).Run()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type dmgEntry struct {
|
type dmgEntry struct {
|
||||||
srcPath string
|
srcPath string
|
||||||
dstPath string
|
dstPath string
|
||||||
@@ -368,16 +436,17 @@ func sanitizeVol(s string) string {
|
|||||||
func readmeText(version, arch string) string {
|
func readmeText(version, arch string) string {
|
||||||
switch arch {
|
switch arch {
|
||||||
case "universal":
|
case "universal":
|
||||||
return fmt.Sprintf(`Navis %s for macOS (универсальная GUI-сборка)
|
return fmt.Sprintf(`Navis %s for macOS (универсальная сборка)
|
||||||
|
|
||||||
Подходит для Apple Silicon (M1/M2/M3/M4) и Intel Mac.
|
Подходит для Apple Silicon (M1/M2/M3/M4) и Intel Mac.
|
||||||
|
|
||||||
1) Перетащите Navis.app в Программы (Applications)
|
1) Перетащите Navis.app в Программы (Applications)
|
||||||
2) При блокировке:
|
2) При первом запуске, если macOS блокирует:
|
||||||
xattr -dr com.apple.quarantine /Applications/Navis.app
|
xattr -dr com.apple.quarantine /Applications/Navis.app
|
||||||
3) Запустите Navis — откроется окно как на Windows
|
3) В Терминале:
|
||||||
(Chrome/Edge/Brave в режиме приложения, иначе браузер)
|
/Applications/Navis.app/Contents/MacOS/Navis init
|
||||||
4) CLI (ядро/connect из терминала): рядом на git файл Navis-cli
|
/Applications/Navis.app/Contents/MacOS/Navis install-core
|
||||||
|
/Applications/Navis.app/Contents/MacOS/Navis connect
|
||||||
|
|
||||||
Магазин: https://evilfox.win/
|
Магазин: https://evilfox.win/
|
||||||
`, version)
|
`, version)
|
||||||
@@ -467,7 +536,9 @@ func architecturePriorityXML(arch string) string {
|
|||||||
case "arm64":
|
case "arm64":
|
||||||
return `
|
return `
|
||||||
<key>LSArchitecturePriority</key>
|
<key>LSArchitecturePriority</key>
|
||||||
<array><string>arm64</string></array>`
|
<array><string>arm64</string></array>
|
||||||
|
<key>LSRequiresNativeExecution</key>
|
||||||
|
<true/>`
|
||||||
case "amd64":
|
case "amd64":
|
||||||
return `
|
return `
|
||||||
<key>LSArchitecturePriority</key>
|
<key>LSArchitecturePriority</key>
|
||||||
|
|||||||
+2
-2
@@ -11,12 +11,12 @@
|
|||||||
"StringFileInfo": {
|
"StringFileInfo": {
|
||||||
"CompanyName": "EvilFox",
|
"CompanyName": "EvilFox",
|
||||||
"FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
"FileDescription": "Navis 2 — VPN client (Naive / Hy2 / AWG / VLESS / VMess / Trojan)",
|
||||||
"FileVersion": "2.7.0.0",
|
"FileVersion": "2.7.1.0",
|
||||||
"InternalName": "Navis",
|
"InternalName": "Navis",
|
||||||
"LegalCopyright": "Copyright (c) EvilFox",
|
"LegalCopyright": "Copyright (c) EvilFox",
|
||||||
"OriginalFilename": "Navis.exe",
|
"OriginalFilename": "Navis.exe",
|
||||||
"ProductName": "Navis",
|
"ProductName": "Navis",
|
||||||
"ProductVersion": "2.7.0.0",
|
"ProductVersion": "2.7.1.0",
|
||||||
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
"Comments": "Open-source VPN/proxy client. https://evilfox.win/"
|
||||||
},
|
},
|
||||||
"VarFileInfo": {
|
"VarFileInfo": {
|
||||||
|
|||||||
Reference in New Issue
Block a user