chore: better upgrade
This commit is contained in:
parent
f047ff0ee1
commit
b7b6e1c646
3 changed files with 47 additions and 32 deletions
|
@ -38,7 +38,12 @@ func restart(w http.ResponseWriter, r *http.Request) {
|
||||||
// The background context is used because the underlying functions wrap it
|
// The background context is used because the underlying functions wrap it
|
||||||
// with timeout and shut down the server, which handles current request. It
|
// with timeout and shut down the server, which handles current request. It
|
||||||
// also should be done in a separate goroutine for the same reason.
|
// also should be done in a separate goroutine for the same reason.
|
||||||
go func() {
|
go runRestart(execPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runRestart(execPath string) {
|
||||||
|
var err error
|
||||||
|
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
cmd := exec.Command(execPath, os.Args[1:]...)
|
cmd := exec.Command(execPath, os.Args[1:]...)
|
||||||
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
log.Infoln("restarting: %q %q", execPath, os.Args[1:])
|
||||||
|
@ -58,5 +63,4 @@ func restart(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("restarting: %s", err)
|
log.Fatalln("restarting: %s", err)
|
||||||
}
|
}
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/hub/updater"
|
"github.com/Dreamacro/clash/hub/updater"
|
||||||
"github.com/Dreamacro/clash/log"
|
"github.com/Dreamacro/clash/log"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
func upgradeRouter() http.Handler {
|
func upgradeRouter() http.Handler {
|
||||||
|
@ -18,11 +21,24 @@ func upgradeRouter() http.Handler {
|
||||||
func upgrade(w http.ResponseWriter, r *http.Request) {
|
func upgrade(w http.ResponseWriter, r *http.Request) {
|
||||||
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/home/controlupdate.go#L108
|
// modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/home/controlupdate.go#L108
|
||||||
log.Infoln("start update")
|
log.Infoln("start update")
|
||||||
err := updater.Update()
|
execPath, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("err:%s", err)
|
render.Status(r, http.StatusInternalServerError)
|
||||||
|
render.JSON(w, r, newError(fmt.Sprintf("getting path: %s", err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
restart(w, r)
|
err = updater.Update(execPath)
|
||||||
|
if err != nil {
|
||||||
|
render.Status(r, http.StatusInternalServerError)
|
||||||
|
render.JSON(w, r, newError(fmt.Sprintf("Upgrade: %s", err)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
render.JSON(w, r, render.M{"status": "ok"})
|
||||||
|
if f, ok := w.(http.Flusher); ok {
|
||||||
|
f.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
go runRestart(execPath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,12 +50,12 @@ type updateError struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *updateError) Error() string {
|
func (e *updateError) Error() string {
|
||||||
return fmt.Sprintf("error: %s", e.Message)
|
return fmt.Sprintf("update error: %s", e.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update performs the auto-updater. It returns an error if the updater failed.
|
// Update performs the auto-updater. It returns an error if the updater failed.
|
||||||
// If firstRun is true, it assumes the configuration file doesn't exist.
|
// If firstRun is true, it assumes the configuration file doesn't exist.
|
||||||
func Update() (err error) {
|
func Update(execPath string) (err error) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
|
|
||||||
|
@ -63,7 +63,6 @@ func Update() (err error) {
|
||||||
goarch = runtime.GOARCH
|
goarch = runtime.GOARCH
|
||||||
latestVersion, err = getLatestVersion()
|
latestVersion, err = getLatestVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := &updateError{Message: err.Error()}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,11 +83,6 @@ func Update() (err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
execPath, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("getting executable path: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workDir = filepath.Dir(execPath)
|
workDir = filepath.Dir(execPath)
|
||||||
|
|
||||||
err = prepare(execPath)
|
err = prepare(execPath)
|
||||||
|
@ -110,7 +104,7 @@ func Update() (err error) {
|
||||||
|
|
||||||
err = backup()
|
err = backup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("replacing: %w", err)
|
return fmt.Errorf("backuping: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = replace()
|
err = replace()
|
||||||
|
@ -186,9 +180,9 @@ func unpack() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// backup makes a backup of the current configuration and supporting files.
|
// backup makes a backup of the current executable file
|
||||||
func backup() (err error) {
|
func backup() (err error) {
|
||||||
log.Infoln("updater: backing up current ExecFile:%s", currentExeName)
|
log.Infoln("updater: backing up current ExecFile:%s to %s", currentExeName, backupExeName)
|
||||||
_ = os.Mkdir(backupDir, 0o755)
|
_ = os.Mkdir(backupDir, 0o755)
|
||||||
|
|
||||||
err = os.Rename(currentExeName, backupExeName)
|
err = os.Rename(currentExeName, backupExeName)
|
||||||
|
@ -199,12 +193,11 @@ func backup() (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace moves the current executable with the updated one and also copies the
|
// replace moves the current executable with the updated one
|
||||||
// supporting files.
|
|
||||||
func replace() error {
|
func replace() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
log.Infoln("copying: %s to %s", updateExeName, currentExeName)
|
log.Infoln("replacing: %s to %s", updateExeName, currentExeName)
|
||||||
if goos == "windows" {
|
if goos == "windows" {
|
||||||
// rename fails with "File in use" error
|
// rename fails with "File in use" error
|
||||||
err = copyFile(updateExeName, currentExeName)
|
err = copyFile(updateExeName, currentExeName)
|
||||||
|
@ -214,7 +207,9 @@ func replace() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infoln("updater: renamed: %s to %s", updateExeName, currentExeName)
|
log.Infoln("updater: renamed: %s to %s", updateExeName, currentExeName)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue