Skip to content

Commit 03d19d9

Browse files
committed
Implement auto update for macOS and linux
1 parent b886de2 commit 03d19d9

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/code-game-project/codegame-cli
22

3-
go 1.18
3+
go 1.19
44

55
require (
66
github.com/Bananenpro/cli v0.3.0

main.go

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,102 @@
11
package main
22

3-
import "github.com/code-game-project/codegame-cli/cmd"
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"path/filepath"
8+
"runtime"
9+
"strconv"
10+
"strings"
11+
"time"
12+
13+
"github.com/Bananenpro/cli"
14+
"github.com/adrg/xdg"
15+
"github.com/code-game-project/go-utils/external"
16+
"github.com/code-game-project/go-utils/semver"
17+
18+
cgExec "github.com/code-game-project/go-utils/exec"
19+
20+
"github.com/code-game-project/codegame-cli/cmd"
21+
)
22+
23+
const Version = "0.7.1"
424

525
func main() {
26+
checkVersion()
627
cmd.Execute()
728
}
29+
30+
// checkVersion prints a warning, if there is a newer version of codegame-cli available.
31+
// On macOS and linux the user is offered to update automatically.
32+
func checkVersion() {
33+
latest, err := getLatestVersion()
34+
if err != nil {
35+
return
36+
}
37+
38+
currentMajor, currentMinor, currentPatch, err := semver.ParseVersion(Version)
39+
if err != nil {
40+
return
41+
}
42+
43+
latestMajor, latestMinor, latestPatch, err := semver.ParseVersion(latest)
44+
if err != nil {
45+
return
46+
}
47+
48+
if latestMajor > currentMajor || (latestMajor == currentMajor && latestMinor > currentMinor) || (latestMajor == currentMajor && latestMinor == currentMinor && latestPatch > currentPatch) {
49+
_, shErr := exec.LookPath("sh")
50+
_, sudoErr := exec.LookPath("sudo")
51+
_, curlErr := exec.LookPath("curl")
52+
_, tarErr := exec.LookPath("tar")
53+
cgBin, codegameErr := os.Stat("/usr/local/bin/codegame")
54+
if codegameErr == nil && !cgBin.IsDir() && shErr == nil && sudoErr == nil && curlErr == nil && tarErr == nil && (runtime.GOOS == "darwin" || runtime.GOOS == "linux") {
55+
update()
56+
} else {
57+
cli.Warn("You are using an old version of codegame-cli (v%s).\nUpdate to the latest version (v%s): https://github.com/code-game-project/codegame-cli#installation", Version, latest)
58+
}
59+
}
60+
}
61+
62+
func update() {
63+
yes, err := cli.YesNo("A new version is available. Do you want to update now?", true)
64+
if err != nil {
65+
os.Exit(0)
66+
}
67+
if !yes {
68+
return
69+
}
70+
71+
_, err = cgExec.Execute(false, "sh", "-c", fmt.Sprintf("curl -L https://github.com/code-game-project/codegame-cli/releases/latest/download/codegame-cli-%s-%s.tar.gz | tar -xz codegame && sudo mv codegame /usr/local/bin", runtime.GOOS, runtime.GOARCH))
72+
if err != nil {
73+
cli.Error("Update failed.")
74+
os.Exit(1)
75+
}
76+
cli.Success("Update successful.")
77+
os.Exit(0)
78+
}
79+
80+
func getLatestVersion() (string, error) {
81+
cacheDir := filepath.Join(xdg.CacheHome, "codegame", "cli")
82+
os.MkdirAll(cacheDir, 0o755)
83+
84+
content, err := os.ReadFile(filepath.Join(cacheDir, "latest_version"))
85+
if err == nil {
86+
parts := strings.Split(string(content), "\n")
87+
if len(parts) >= 2 {
88+
cacheTime, err := strconv.Atoi(parts[0])
89+
if err == nil && time.Now().Unix()-int64(cacheTime) <= 60*60*24 {
90+
return parts[1], nil
91+
}
92+
}
93+
}
94+
95+
tag, err := external.LatestGithubTag("code-game-project", "codegame-cli")
96+
if err != nil {
97+
return "", err
98+
}
99+
version := strings.TrimPrefix(tag, "v")
100+
os.WriteFile(filepath.Join(cacheDir, "latest_version"), []byte(fmt.Sprintf("%d\n%s", time.Now().Unix(), version)), 0o644)
101+
return version, nil
102+
}

0 commit comments

Comments
 (0)