Skip to content

Commit 14fc5d2

Browse files
committed
Implemented the autoupdater for MacOS
1 parent 0270870 commit 14fc5d2

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

updater/updater_macos.go

+96-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,105 @@
1717

1818
package updater
1919

20+
import (
21+
"bytes"
22+
"context"
23+
"crypto/sha256"
24+
"fmt"
25+
"io"
26+
"os"
27+
28+
"github.com/arduino/go-paths-helper"
29+
"github.com/codeclysm/extract/v3"
30+
)
31+
2032
func start(src string) string {
2133
return ""
2234
}
2335

2436
func checkForUpdates(currentVersion string, updateAPIURL, updateBinURL string, cmdName string) (string, error) {
25-
return "", nil
37+
executablePath, err := os.Executable()
38+
if err != nil {
39+
return "", fmt.Errorf("could not app path: %w", err)
40+
}
41+
currentAppPath := paths.New(executablePath).Parent().Parent().Parent()
42+
if currentAppPath.Ext() != ".app" {
43+
return "", fmt.Errorf("could not find app root in %s", executablePath)
44+
}
45+
oldAppPath := currentAppPath.Parent().Join("ArdiunoCreateAgent.old.app")
46+
if oldAppPath.Exist() {
47+
return "", fmt.Errorf("temp app already exists: %s, cannot update", oldAppPath)
48+
}
49+
50+
// Fetch information about updates
51+
info, err := fetchInfo(updateAPIURL, cmdName)
52+
if err != nil {
53+
return "", err
54+
}
55+
if info.Version == currentVersion {
56+
// No updates available, bye bye
57+
return "", nil
58+
}
59+
60+
tmp := paths.TempDir().Join("arduino-create-agent")
61+
tmpZip := tmp.Join("update.zip")
62+
tmpAppPath := tmp.Join("ArduinoCreateAgent-update.app")
63+
defer tmp.RemoveAll()
64+
65+
// Download the update.
66+
download, err := fetch(updateBinURL + cmdName + "/" + plat + "/" + info.Version + "/" + cmdName)
67+
if err != nil {
68+
return "", err
69+
}
70+
defer download.Close()
71+
72+
f, err := tmpZip.Create()
73+
if err != nil {
74+
return "", err
75+
}
76+
defer f.Close()
77+
78+
sha := sha256.New()
79+
if _, err := io.Copy(io.MultiWriter(sha, f), download); err != nil {
80+
return "", err
81+
}
82+
f.Close()
83+
84+
// Check the hash
85+
if s := sha.Sum(nil); !bytes.Equal(s, info.Sha256) {
86+
return "", fmt.Errorf("bad hash: %s (expected %s)", s, info.Sha256)
87+
}
88+
89+
// Unzip the update
90+
if err := tmpAppPath.MkdirAll(); err != nil {
91+
return "", fmt.Errorf("could not create tmp dir to unzip update: %w", err)
92+
}
93+
94+
f, err = tmpZip.Open()
95+
if err != nil {
96+
return "", fmt.Errorf("could not open archive for unzip: %w", err)
97+
}
98+
defer f.Close()
99+
if err := extract.Archive(context.Background(), f, tmpAppPath.String(), nil); err != nil {
100+
return "", fmt.Errorf("extracting archive: %w", err)
101+
}
102+
103+
// Rename current app as .old
104+
if err := currentAppPath.Rename(oldAppPath); err != nil {
105+
return "", fmt.Errorf("could not rename old app as .old: %w", err)
106+
}
107+
108+
// Install new app
109+
if err := tmpAppPath.CopyDirTo(currentAppPath); err != nil {
110+
// Try rollback changes
111+
_ = currentAppPath.RemoveAll()
112+
_ = oldAppPath.Rename(currentAppPath)
113+
return "", fmt.Errorf("could not install app: %w", err)
114+
}
115+
116+
// Remove old app
117+
_ = oldAppPath.RemoveAll()
118+
119+
// Restart agent
120+
return currentAppPath.Join("Contents", "MacOS", "Arduino_Create_Agent").String(), nil
26121
}

0 commit comments

Comments
 (0)