mirror of https://github.com/liamg/aminal.git
142 lines
2.9 KiB
Go
142 lines
2.9 KiB
Go
// +build windows
|
|
//go:generate goversioninfo -icon=aminal.ico
|
|
|
|
/*
|
|
Looks at directory "Versions" next to this executable. Finds the latest version
|
|
and runs the executable with the same name as this executable in that directory.
|
|
Eg.:
|
|
Aminal.exe (=launcher.exe)
|
|
Versions/
|
|
1.0.0/
|
|
Aminal.exe
|
|
1.0.1
|
|
Aminal.exe
|
|
-> Launches Versions/1.0.1/Aminal.exe.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/liamg/aminal/windows/winutil"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"path/filepath"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
type Version struct {
|
|
number [3]int
|
|
name string
|
|
}
|
|
type Versions []Version
|
|
|
|
func main() {
|
|
executable, err := winutil.GetExecutablePath()
|
|
check(err)
|
|
executableDir, executableName := filepath.Split(executable)
|
|
versionsDir := filepath.Join(executableDir, "Versions")
|
|
latestVersion, err := getLatestVersion(versionsDir)
|
|
check(err)
|
|
usr, err := user.Current()
|
|
check(err)
|
|
cmd := exec.Command("C:\\Windows\\System32\\cmd.exe", "/C", "start", "Aminal", "/B", executableName)
|
|
cmd.Dir = usr.HomeDir
|
|
latestVersionDir := filepath.Join(versionsDir, latestVersion)
|
|
path, pathSet := os.LookupEnv("PATH")
|
|
if pathSet {
|
|
path += ";" + latestVersionDir
|
|
} else {
|
|
path = latestVersionDir
|
|
}
|
|
cmd.Env = append(os.Environ(), "PATH="+path)
|
|
const CREATE_NO_WINDOW = 0x08000000
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
HideWindow: true,
|
|
CreationFlags: CREATE_NO_WINDOW,
|
|
}
|
|
check(cmd.Start())
|
|
}
|
|
|
|
func getLatestVersion(versionsDir string) (string, error) {
|
|
potentialVersions, err := ioutil.ReadDir(versionsDir)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var versions Versions
|
|
for _, file := range potentialVersions {
|
|
if !file.IsDir() {
|
|
continue
|
|
}
|
|
version, err := parseVersionString(file.Name())
|
|
if err != nil {
|
|
continue
|
|
}
|
|
versions = append(versions, version)
|
|
}
|
|
if len(versions) == 0 {
|
|
errMsg := fmt.Sprintf("No valid version in %s.", versionsDir)
|
|
return "", errors.New(errMsg)
|
|
}
|
|
sort.Sort(versions)
|
|
return versions[len(versions)-1].String(), nil
|
|
}
|
|
|
|
func parseVersionString(version string) (Version, error) {
|
|
var result Version
|
|
result.name = version
|
|
err := error(nil)
|
|
version = strings.TrimSuffix(version, "-SNAPSHOT")
|
|
parts := strings.Split(version, ".")
|
|
if len(parts) != len(result.number) {
|
|
err = errors.New("Wrong number of parts.")
|
|
} else {
|
|
for i, partStr := range parts {
|
|
result.number[i], err = strconv.Atoi(partStr)
|
|
if err != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
func (arr Versions) Len() int {
|
|
return len(arr)
|
|
}
|
|
|
|
func (arr Versions) Less(i, j int) bool {
|
|
for k, left := range arr[i].number {
|
|
right := arr[j].number[k]
|
|
if left > right {
|
|
return false
|
|
} else if left < right {
|
|
return true
|
|
}
|
|
}
|
|
fmt.Printf("%s < %s\n", arr[i], arr[j])
|
|
return true
|
|
}
|
|
|
|
func (arr Versions) Swap(i, j int) {
|
|
tmp := arr[j]
|
|
arr[j] = arr[i]
|
|
arr[i] = tmp
|
|
}
|
|
|
|
func (version Version) String() string {
|
|
return version.name
|
|
}
|
|
|
|
func check(e error) {
|
|
if e != nil {
|
|
panic(e)
|
|
}
|
|
}
|