96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
//go:build darwin
|
|
|
|
package update
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// Apply downloads the new binary into ~/Downloads (no silent self-replace).
|
|
func Apply(ctx context.Context, manifestURL string) (string, error) {
|
|
st, err := Check(ctx, manifestURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if !st.Available {
|
|
if st.Error != "" {
|
|
return "", fmt.Errorf("%s", st.Error)
|
|
}
|
|
return "", fmt.Errorf("обновление не найдено")
|
|
}
|
|
if !allowedDownloadURL(st.URL) {
|
|
return "", fmt.Errorf("URL обновления должен быть на git.evilfox.cc или files.de4ima.uk")
|
|
}
|
|
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dir := filepath.Join(home, "Downloads")
|
|
_ = os.MkdirAll(dir, 0o755)
|
|
dest := filepath.Join(dir, fmt.Sprintf("Navis-%s-darwin-%s", sanitizeDarwinVer(st.Latest), runtime.GOARCH))
|
|
tmp := dest + ".part"
|
|
_ = os.Remove(tmp)
|
|
_ = os.Remove(dest)
|
|
|
|
if err := downloadFile(ctx, st.URL, tmp); err != nil {
|
|
return "", err
|
|
}
|
|
if st.SHA256 != "" {
|
|
sum, err := fileSHA256(tmp)
|
|
if err != nil {
|
|
_ = os.Remove(tmp)
|
|
return "", err
|
|
}
|
|
if sum != "" && !eqFold(sum, st.SHA256) {
|
|
_ = os.Remove(tmp)
|
|
return "", fmt.Errorf("checksum mismatch")
|
|
}
|
|
}
|
|
if err := os.Rename(tmp, dest); err != nil {
|
|
_ = os.Remove(tmp)
|
|
return "", err
|
|
}
|
|
_ = os.Chmod(dest, 0o755)
|
|
_ = exec.Command("open", "-R", dest).Start()
|
|
return fmt.Sprintf("Скачано v%s:\n%s\nЗакройте Navis и запустите новый файл.", st.Latest, dest), nil
|
|
}
|
|
|
|
func sanitizeDarwinVer(v string) string {
|
|
out := make([]rune, 0, len(v))
|
|
for _, r := range v {
|
|
switch {
|
|
case r >= '0' && r <= '9', r >= 'a' && r <= 'z', r >= 'A' && r <= 'Z', r == '.', r == '-':
|
|
out = append(out, r)
|
|
}
|
|
}
|
|
if len(out) == 0 {
|
|
return "update"
|
|
}
|
|
return string(out)
|
|
}
|
|
|
|
func eqFold(a, b string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for i := 0; i < len(a); i++ {
|
|
ca, cb := a[i], b[i]
|
|
if ca >= 'A' && ca <= 'F' {
|
|
ca += 'a' - 'A'
|
|
}
|
|
if cb >= 'A' && cb <= 'F' {
|
|
cb += 'a' - 'A'
|
|
}
|
|
if ca != cb {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|