Browse Source

Improve code formatting with gofmt -w -s

master
NGnius (Graham) 5 years ago
parent
commit
b6ec943198
2 changed files with 304 additions and 304 deletions
  1. +236
    -236
      rxsm-updater/rxsm-updater.go
  2. +68
    -68
      rxsm-updater/update.go

+ 236
- 236
rxsm-updater/rxsm-updater.go View File

@@ -3,266 +3,266 @@
package main

import (
"runtime"
"os"
"io"
"log"
"errors"
"archive/zip"
"path/filepath"
"flag"
"time"
"archive/zip"
"errors"
"flag"
"io"
"log"
"os"
"path/filepath"
"runtime"
"time"
)

const (
DefaultZipFile string = "rxsm-update.zip"
RXSMUpdaterVersion string = "v0.0.1"
DefaultUpdateServer string = "https://rxsm-update.exmods.org"
DefaultZipFile string = "rxsm-update.zip"
RXSMUpdaterVersion string = "v0.0.1"
DefaultUpdateServer string = "https://rxsm-update.exmods.org"
)

var (
// command line flag arguments
Zipfile string = DefaultZipFile
Target string
Unattended bool
PlatformStream string
UpdateServer string
TargetBinary string
Delay time.Duration
IsLogged bool
// command line flag arguments
Zipfile string = DefaultZipFile
Target string
Unattended bool
PlatformStream string
UpdateServer string
TargetBinary string
Delay time.Duration
IsLogged bool
)

func init() {
log.Println("RXSM Updater version", RXSMUpdaterVersion)
log.Println("This program updates RXSM headlessly. Use rxsm-updater --help to view advanced features")
log.Println(os.Args)
flag.StringVar(&Zipfile, "zip", DefaultZipFile, "The zipfile to extract from (and download to, in unattended mode)")
flag.StringVar(&Target, "target", "", "The directory to target for the update (the directory containing RXSM)")
flag.BoolVar(&Unattended, "unattended", false, "Download & extract the RXSM update (WIP)")
flag.StringVar(&PlatformStream, "stream", "release", "The update stream to use when retrieving updates in unattended mode")
flag.StringVar(&UpdateServer, "server", DefaultUpdateServer, "The web server to use for retrieving update information")
flag.DurationVar(&Delay, "wait", 0, "Time to wait before starting")
flag.BoolVar(&IsLogged, "log", false, "Send output to log")
log.Println("RXSM Updater version", RXSMUpdaterVersion)
log.Println("This program updates RXSM headlessly. Use rxsm-updater --help to view advanced features")
log.Println(os.Args)
flag.StringVar(&Zipfile, "zip", DefaultZipFile, "The zipfile to extract from (and download to, in unattended mode)")
flag.StringVar(&Target, "target", "", "The directory to target for the update (the directory containing RXSM)")
flag.BoolVar(&Unattended, "unattended", false, "Download & extract the RXSM update (WIP)")
flag.StringVar(&PlatformStream, "stream", "release", "The update stream to use when retrieving updates in unattended mode")
flag.StringVar(&UpdateServer, "server", DefaultUpdateServer, "The web server to use for retrieving update information")
flag.DurationVar(&Delay, "wait", 0, "Time to wait before starting")
flag.BoolVar(&IsLogged, "log", false, "Send output to log")
}

func main() {
flag.Parse()
if IsLogged {
f, _ := os.Create("rxsm-updater.log")
log.SetOutput(f)
log.Println("RXSM Updater version", RXSMUpdaterVersion)
log.Println("This program updates RXSM headlessly. Use rxsm-updater --help to view advanced features")
log.Println(os.Args)
}
if Delay != 0 {
log.Println("Waiting", Delay.Seconds(), "second(s)")
time.Sleep(Delay)
}
if Unattended {
log.Println("Attempting WIP Unattended update")
log.Println("This is not advised, and will fail if an updater update is necessary")
URL, isUpdatable, ok := CheckForUpdate(UpdateServer, "", runtime.GOOS+"/"+runtime.GOARCH+"/"+PlatformStream)
if !(ok && isUpdatable && URL != "") {
log.Println("No update found")
return
}
downloadErr := DownloadRXSMUpdate(URL, func(int, string){})
if downloadErr != nil {
log.Println(downloadErr)
return
}
proc, forkErr := ForkRXSMUpdate()
if forkErr != nil {
log.Println(forkErr)
return
}
log.Println("Extraction forked to", proc.Pid)
} else {
log.Println("Installing from", Zipfile)
installErr := InstallRXSMUpdate(func(int, string){})
if installErr != nil {
log.Println(installErr)
return
}
}
log.Println("Operation complete")
// TODO: implement callback for Qt window
flag.Parse()
if IsLogged {
f, _ := os.Create("rxsm-updater.log")
log.SetOutput(f)
log.Println("RXSM Updater version", RXSMUpdaterVersion)
log.Println("This program updates RXSM headlessly. Use rxsm-updater --help to view advanced features")
log.Println(os.Args)
}
if Delay != 0 {
log.Println("Waiting", Delay.Seconds(), "second(s)")
time.Sleep(Delay)
}
if Unattended {
log.Println("Attempting WIP Unattended update")
log.Println("This is not advised, and will fail if an updater update is necessary")
URL, isUpdatable, ok := CheckForUpdate(UpdateServer, "", runtime.GOOS+"/"+runtime.GOARCH+"/"+PlatformStream)
if !(ok && isUpdatable && URL != "") {
log.Println("No update found")
return
}
downloadErr := DownloadRXSMUpdate(URL, func(int, string) {})
if downloadErr != nil {
log.Println(downloadErr)
return
}
proc, forkErr := ForkRXSMUpdate()
if forkErr != nil {
log.Println(forkErr)
return
}
log.Println("Extraction forked to", proc.Pid)
} else {
log.Println("Installing from", Zipfile)
installErr := InstallRXSMUpdate(func(int, string) {})
if installErr != nil {
log.Println(installErr)
return
}
}
log.Println("Operation complete")
// TODO: implement callback for Qt window
}

func DownloadRXSMUpdateQuiet(URL string) {
DownloadRXSMUpdate(URL, func(int, string){})
DownloadRXSMUpdate(URL, func(int, string) {})
}

func DownloadRXSMUpdate(URL string, statusCallback func(progress int, description string)) (error){
// progress is out of 100
statusCallback(25, "Downloading")
log.Println("Downloading update from "+URL)
f, createErr := os.Create(Zipfile)
if createErr != nil {
log.Println("Error creating temporary update file")
statusCallback(-1, "Error creating update temporary file")
return createErr
}
defer f.Close()
ok := DownloadUpdate(URL, f)
if !ok {
log.Println("Error downloading update")
statusCallback(-1, "Download failed")
return errors.New("download failed in update API")
}
statusCallback(50, "Installing Updater")
f.Sync()
f.Seek(0,0)
fStat, statErr := f.Stat()
if statErr != nil {
log.Println("Error getting download temp file stat")
return statErr
}
log.Println("Downloaded", fStat.Size(), "bytes")
statusCallback(75, "Extracting Updater")
// TODO: implement way to have this actually work
zipFile, zipErr := zip.NewReader(f, fStat.Size())
if zipErr != nil {
log.Println("Error creating zip reader")
log.Println(zipErr)
return zipErr
}
for _, f := range zipFile.File {
if !f.FileHeader.Mode().IsDir() {
filename := filepath.Clean(f.FileHeader.Name)
var updaterFilename string
if runtime.GOOS == "windows" {
updaterFilename = "rxsm-updater.exe"
TargetBinary = "rxsm-updater2.exe"
} else {
updaterFilename = "rxsm-updater"
TargetBinary = "rxsm-updater2"
}
if len(filename) >= len(updaterFilename) && filename[:len(updaterFilename)] == updaterFilename {
fileReadCloser, openErr := f.Open()
if openErr != nil {
log.Println("Error opening updater in zip archive")
return openErr
}
defer fileReadCloser.Close()
destFile, createErr := os.Create(TargetBinary)
if createErr != nil {
log.Println("Error creating updater file")
return createErr
}
defer destFile.Close()
_, copyErr := io.Copy(destFile, fileReadCloser)
if copyErr != nil {
log.Println("Error copying/extracting updater")
return copyErr
}
}
}
}
statusCallback(100, "Complete")
return nil
func DownloadRXSMUpdate(URL string, statusCallback func(progress int, description string)) error {
// progress is out of 100
statusCallback(25, "Downloading")
log.Println("Downloading update from " + URL)
f, createErr := os.Create(Zipfile)
if createErr != nil {
log.Println("Error creating temporary update file")
statusCallback(-1, "Error creating update temporary file")
return createErr
}
defer f.Close()
ok := DownloadUpdate(URL, f)
if !ok {
log.Println("Error downloading update")
statusCallback(-1, "Download failed")
return errors.New("download failed in update API")
}
statusCallback(50, "Installing Updater")
f.Sync()
f.Seek(0, 0)
fStat, statErr := f.Stat()
if statErr != nil {
log.Println("Error getting download temp file stat")
return statErr
}
log.Println("Downloaded", fStat.Size(), "bytes")
statusCallback(75, "Extracting Updater")
// TODO: implement way to have this actually work
zipFile, zipErr := zip.NewReader(f, fStat.Size())
if zipErr != nil {
log.Println("Error creating zip reader")
log.Println(zipErr)
return zipErr
}
for _, f := range zipFile.File {
if !f.FileHeader.Mode().IsDir() {
filename := filepath.Clean(f.FileHeader.Name)
var updaterFilename string
if runtime.GOOS == "windows" {
updaterFilename = "rxsm-updater.exe"
TargetBinary = "rxsm-updater2.exe"
} else {
updaterFilename = "rxsm-updater"
TargetBinary = "rxsm-updater2"
}
if len(filename) >= len(updaterFilename) && filename[:len(updaterFilename)] == updaterFilename {
fileReadCloser, openErr := f.Open()
if openErr != nil {
log.Println("Error opening updater in zip archive")
return openErr
}
defer fileReadCloser.Close()
destFile, createErr := os.Create(TargetBinary)
if createErr != nil {
log.Println("Error creating updater file")
return createErr
}
defer destFile.Close()
_, copyErr := io.Copy(destFile, fileReadCloser)
if copyErr != nil {
log.Println("Error copying/extracting updater")
return copyErr
}
}
}
}
statusCallback(100, "Complete")
return nil
}

func ForkRXSMUpdate() (process *os.Process, err error) {
if runtime.GOOS == "windows" {
return os.StartProcess(TargetBinary, []string{TargetBinary, "--zip", Zipfile, "--target", Target}, nil)
} else {
return os.StartProcess(TargetBinary, []string{TargetBinary, "--zip", Zipfile, "--target", Target}, nil)
}
if runtime.GOOS == "windows" {
return os.StartProcess(TargetBinary, []string{TargetBinary, "--zip", Zipfile, "--target", Target}, nil)
} else {
return os.StartProcess(TargetBinary, []string{TargetBinary, "--zip", Zipfile, "--target", Target}, nil)
}
}

func InstallRXSMUpdate(statusCallback func(progress int, description string)) (error){
f, openErr := os.Open(Zipfile)
if openErr != nil {
log.Println("Error opening zip file")
statusCallback(-1, "Opening zip file failed")
return openErr
}
statusCallback(1, "Extracting")
f.Sync()
f.Seek(0,0)
fStat, statErr := f.Stat()
if statErr != nil {
log.Println("Error retrieving file stats")
statusCallback(-1, "Extracting zip file failed")
return statErr
}
unpackErr := unpackRXSMInstall(f, fStat.Size(), func(p int, d string){statusCallback(1, d)})
if unpackErr != nil {
log.Println("Error extracting update")
statusCallback(-1, "Unpacking failed")
return unpackErr
}
statusCallback(2, "Installing")
// TODO: is there installation required?
rmErr := os.Remove(Zipfile)
if rmErr != nil {
log.Println("Error removing download file")
statusCallback(-1, "Installing failed")
return rmErr
}
return nil
func InstallRXSMUpdate(statusCallback func(progress int, description string)) error {
f, openErr := os.Open(Zipfile)
if openErr != nil {
log.Println("Error opening zip file")
statusCallback(-1, "Opening zip file failed")
return openErr
}
statusCallback(1, "Extracting")
f.Sync()
f.Seek(0, 0)
fStat, statErr := f.Stat()
if statErr != nil {
log.Println("Error retrieving file stats")
statusCallback(-1, "Extracting zip file failed")
return statErr
}
unpackErr := unpackRXSMInstall(f, fStat.Size(), func(p int, d string) { statusCallback(1, d) })
if unpackErr != nil {
log.Println("Error extracting update")
statusCallback(-1, "Unpacking failed")
return unpackErr
}
statusCallback(2, "Installing")
// TODO: is there installation required?
rmErr := os.Remove(Zipfile)
if rmErr != nil {
log.Println("Error removing download file")
statusCallback(-1, "Installing failed")
return rmErr
}
return nil
}

func unpackRXSMInstallPath(path string) (error) {
f, openErr := os.Open(path)
if openErr != nil {
return openErr
}
defer f.Close()
fStat, statErr := f.Stat()
if statErr != nil {
return statErr
}
return unpackRXSMInstall(f, fStat.Size(), func(int, string){})
func unpackRXSMInstallPath(path string) error {
f, openErr := os.Open(path)
if openErr != nil {
return openErr
}
defer f.Close()
fStat, statErr := f.Stat()
if statErr != nil {
return statErr
}
return unpackRXSMInstall(f, fStat.Size(), func(int, string) {})
}

func unpackRXSMInstall(reader io.ReaderAt, size int64, statusCallback func(progress int, description string)) (error) {
// progress is out of 100
// open zip
zipFile, zipErr := zip.NewReader(reader, size)
if zipErr != nil {
return zipErr
}
// NOTE: this could use go routines, but doesn't to keep your PC (& RXSM) usable while updating
// (And also to make the loading bar coherent)
for i, f := range zipFile.File {
if !f.FileHeader.Mode().IsDir() {
filename := filepath.Clean(f.FileHeader.Name)
statusCallback(100*(i+1)/len(zipFile.File), "Unpacking "+filename)
if filepath.IsAbs(filename) {
if runtime.GOOS == "windows" {
filename = filename[4:] // D:\\path\to\keep -> path\to\keep
} else {
filename = filename[1:] // /path/to/keep -> path/to/keep
}
}
if len(filename) > len(runtime.GOOS)+1 {
// remove windows/ or darwin/ or linux/ from path if exists
if filename[:len(runtime.GOOS)] == runtime.GOOS {
filename = filename[len(runtime.GOOS)+1:]
}
}
filename = filepath.Join(Target, filename)
dirErr := os.MkdirAll(filepath.Dir(filename), os.ModeDir | os.ModePerm)
if dirErr != nil {
log.Println("Dir err "+filepath.Dir(filename))
return dirErr
}
newFile, createErr := os.Create(filename)
if createErr != nil {
return createErr
}
srcFileReadCloser, zipOpenErr := f.Open()
if zipOpenErr != nil {
return zipOpenErr
}
defer srcFileReadCloser.Close()
_, copyErr := io.Copy(newFile, srcFileReadCloser)
if copyErr != nil {
return copyErr
}
}
}
return nil
func unpackRXSMInstall(reader io.ReaderAt, size int64, statusCallback func(progress int, description string)) error {
// progress is out of 100
// open zip
zipFile, zipErr := zip.NewReader(reader, size)
if zipErr != nil {
return zipErr
}
// NOTE: this could use go routines, but doesn't to keep your PC (& RXSM) usable while updating
// (And also to make the loading bar coherent)
for i, f := range zipFile.File {
if !f.FileHeader.Mode().IsDir() {
filename := filepath.Clean(f.FileHeader.Name)
statusCallback(100*(i+1)/len(zipFile.File), "Unpacking "+filename)
if filepath.IsAbs(filename) {
if runtime.GOOS == "windows" {
filename = filename[4:] // D:\\path\to\keep -> path\to\keep
} else {
filename = filename[1:] // /path/to/keep -> path/to/keep
}
}
if len(filename) > len(runtime.GOOS)+1 {
// remove windows/ or darwin/ or linux/ from path if exists
if filename[:len(runtime.GOOS)] == runtime.GOOS {
filename = filename[len(runtime.GOOS)+1:]
}
}
filename = filepath.Join(Target, filename)
dirErr := os.MkdirAll(filepath.Dir(filename), os.ModeDir|os.ModePerm)
if dirErr != nil {
log.Println("Dir err " + filepath.Dir(filename))
return dirErr
}
newFile, createErr := os.Create(filename)
if createErr != nil {
return createErr
}
srcFileReadCloser, zipOpenErr := f.Open()
if zipOpenErr != nil {
return zipOpenErr
}
defer srcFileReadCloser.Close()
_, copyErr := io.Copy(newFile, srcFileReadCloser)
if copyErr != nil {
return copyErr
}
}
}
return nil
}

+ 68
- 68
rxsm-updater/update.go View File

@@ -3,90 +3,90 @@
package main

import (
"net/http"
"encoding/json"
"io"
"io/ioutil"
"runtime"
"bytes"
"log"
"bytes"
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
"runtime"
)

const (
DNT_ON = "1"
DNT_OFF = "0"
DNT_ON = "1"
DNT_OFF = "0"
)

var (
ExtraHeader map[string][]string = make(map[string][]string)
client http.Client = http.Client{}
ExtraHeader map[string][]string = make(map[string][]string)
client http.Client = http.Client{}
)

type updateStruct struct {
Status int `json:"status"`
Reason string `json:"reason"`
Url string `json:"url"`
IsOutOfDate bool `json:"out-of-date"`
Status int `json:"status"`
Reason string `json:"reason"`
Url string `json:"url"`
IsOutOfDate bool `json:"out-of-date"`
}

func CheckForUpdate(baseURL string, version string, platform string) (downloadURL string, isOutOfDate bool, ok bool) {
body_map := make(map[string]string)
body_map["version"] = version
body_map["platform"] = platform
body_bytes, marshalErr := json.Marshal(body_map)
if marshalErr != nil {
log.Println(marshalErr)
return
}
req, _ := http.NewRequest("POST", baseURL+"/"+"update", bytes.NewReader(body_bytes))
for key, elem := range ExtraHeader {
req.Header[key] = elem
}
resp, httpErr := client.Do(req)
if httpErr != nil || resp.StatusCode != 200 {
log.Println(req.Header)
log.Println(httpErr)
if resp != nil {
log.Println(resp.StatusCode)
}
return
}
defer resp.Body.Close()
resp_struct := updateStruct{}
resp_body_bytes, readAllErr := ioutil.ReadAll(resp.Body)
if readAllErr != nil {
log.Println(readAllErr)
return
}
unmarshalErr := json.Unmarshal(resp_body_bytes, &resp_struct)
if unmarshalErr != nil {
log.Println(unmarshalErr)
return
}
isOutOfDate = resp_struct.IsOutOfDate
downloadURL = resp_struct.Url
ok = true
return
body_map := make(map[string]string)
body_map["version"] = version
body_map["platform"] = platform
body_bytes, marshalErr := json.Marshal(body_map)
if marshalErr != nil {
log.Println(marshalErr)
return
}
req, _ := http.NewRequest("POST", baseURL+"/"+"update", bytes.NewReader(body_bytes))
for key, elem := range ExtraHeader {
req.Header[key] = elem
}
resp, httpErr := client.Do(req)
if httpErr != nil || resp.StatusCode != 200 {
log.Println(req.Header)
log.Println(httpErr)
if resp != nil {
log.Println(resp.StatusCode)
}
return
}
defer resp.Body.Close()
resp_struct := updateStruct{}
resp_body_bytes, readAllErr := ioutil.ReadAll(resp.Body)
if readAllErr != nil {
log.Println(readAllErr)
return
}
unmarshalErr := json.Unmarshal(resp_body_bytes, &resp_struct)
if unmarshalErr != nil {
log.Println(unmarshalErr)
return
}
isOutOfDate = resp_struct.IsOutOfDate
downloadURL = resp_struct.Url
ok = true
return
}

func SimpleCheckForUpdate(baseURL string, version string) (downloadURL string, isOutOfDate bool, ok bool) {
return CheckForUpdate(baseURL, version, runtime.GOOS+"/"+runtime.GOARCH)
return CheckForUpdate(baseURL, version, runtime.GOOS+"/"+runtime.GOARCH)
}

func DownloadUpdate(downloadURL string, dest io.Writer) (ok bool) {
req, _ := http.NewRequest("GET", downloadURL, nil)
for key, elem := range ExtraHeader {
req.Header[key] = elem
}
resp, httpErr := client.Do(req)
if httpErr != nil || resp.StatusCode != 200 {
return
}
defer resp.Body.Close()
_, copyErr := io.Copy(dest, resp.Body)
if copyErr != nil {
return
}
ok = true
return
req, _ := http.NewRequest("GET", downloadURL, nil)
for key, elem := range ExtraHeader {
req.Header[key] = elem
}
resp, httpErr := client.Do(req)
if httpErr != nil || resp.StatusCode != 200 {
return
}
defer resp.Body.Close()
_, copyErr := io.Copy(dest, resp.Body)
if copyErr != nil {
return
}
ok = true
return
}