Skip to content

Commit f557b29

Browse files
committed
Implemented the autoupdater for MacOS
1 parent 4af6250 commit f557b29

File tree

1 file changed

+96
-1
lines changed

1 file changed

+96
-1
lines changed

updater/updater_darwin.go

+96-1
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,105 @@
1515

1616
package updater
1717

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

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

0 commit comments

Comments
 (0)