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:
M4
2026-07-29 16:31:37 +03:00
co-authored by Cursor
parent 2d4a797eb1
commit 53eb845d04
16 changed files with 182 additions and 34 deletions
+16 -2
View File
@@ -207,11 +207,15 @@ func (c *Config) ActiveProfile() (*Profile, error) {
}
// 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) {
if filepath.IsAbs(binDir) {
return binDir, nil
}
if dir, ok := platformNavisDir(); ok {
return filepath.Abs(filepath.Join(dir, binDir))
}
if exe, err := os.Executable(); err == nil {
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)
}
// 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) {
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 {
dir := filepath.Dir(exe)
candidates = append(candidates,
@@ -301,6 +312,9 @@ func LocateConfig() (string, error) {
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.
if exe, err := os.Executable(); err == nil {
return filepath.Join(filepath.Dir(exe), "configs", "config.json"), nil
+16
View File
@@ -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
}
+7
View File
@@ -0,0 +1,7 @@
//go:build !darwin
package config
func platformNavisDir() (string, bool) {
return "", false
}
+4
View File
@@ -6,6 +6,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
@@ -90,6 +91,9 @@ func EnsureBinary(binDir string) (string, error) {
return "", err
}
_ = os.Chmod(dest, 0o755)
if runtime.GOOS == "darwin" {
_ = exec.Command("xattr", "-dr", "com.apple.quarantine", dest).Run()
}
return ResolveBinary(binDir)
}
+40 -8
View File
@@ -64,7 +64,19 @@ func EnsureBinary(binDir string) (string, error) {
if err := extractNaiveArchive(archivePath, binDir); err != nil {
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) {
@@ -76,9 +88,11 @@ func assetNameForPlatform() (string, error) {
case runtime.GOOS == "linux" && runtime.GOARCH == "amd64":
return "naiveproxy-*-linux-x64.zip", nil
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":
return "naiveproxy-*-mac-arm64.tar.xz", nil
// Newer releases use mac-arm64-arm64; older used mac-arm64.
return "naiveproxy-*-mac-arm64", nil
default:
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
}
prefix := strings.Split(pattern, "*")[0]
suffix := ""
if parts := strings.Split(pattern, "*"); len(parts) == 2 {
suffix = parts[1]
needle := ""
if parts := strings.SplitN(pattern, "*", 2); len(parts) == 2 {
needle = parts[1]
}
var bestName, bestURL string
for _, a := range rel.Assets {
if strings.HasPrefix(a.Name, prefix) && strings.HasSuffix(a.Name, suffix) {
return a.Name, a.BrowserDownloadURL, nil
name := a.Name
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)
}
+4
View File
@@ -7,6 +7,7 @@ import (
"io"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
@@ -78,6 +79,9 @@ func EnsureBinary(binDir string) (string, error) {
}
}
_ = os.Chmod(dest, 0o755)
if runtime.GOOS == "darwin" {
_ = exec.Command("xattr", "-dr", "com.apple.quarantine", dest).Run()
}
return ResolveBinary(binDir)
}
+1 -1
View File
@@ -17,7 +17,7 @@ import (
)
// 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).
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"