Release 2.2.1: universal macOS DMG and arch install fix.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+155
-30
@@ -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,13 +145,23 @@ func writeDMG(dmgPath, appRoot, readmePath, volume string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := copyTreeToISO(fs, appRoot, "/Navis.app"); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
if err := writeISOFile(fs, "/README.txt", readmePath, 0o644); err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
for _, f := range files {
|
||||
info, err := os.Stat(f.srcPath)
|
||||
if err != nil {
|
||||
_ = fs.Close()
|
||||
return err
|
||||
}
|
||||
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)
|
||||
@@ -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 ""
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user