diff --git a/cmds.go b/cmds.go index 0489311..2d4444e 100644 --- a/cmds.go +++ b/cmds.go @@ -164,7 +164,7 @@ func actionShutdown(c *cli.Context) error { } func actionUpdateSelf(c *cli.Context) error { - return equinoxUpdate(c.String("channel"), c.Bool("yes")) + return githubUpdate(c.Bool("yes")) } func actionEdit(c *cli.Context) error { diff --git a/gosuv.go b/gosuv.go index 3392d25..77bc04d 100644 --- a/gosuv.go +++ b/gosuv.go @@ -8,8 +8,10 @@ import ( "net/http" "os" "path/filepath" + "runtime" + "strings" - "github.com/equinox-io/equinox" + "github.com/franela/goreq" "github.com/qiniu/log" "github.com/urfave/cli" ) @@ -17,54 +19,72 @@ import ( const appID = "app_8Gji4eEAdDx" var ( - version string = "master" - publicKey = []byte(` ------BEGIN ECDSA PUBLIC KEY----- -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEY8xsSkcFs8XXUicw3n7E77qN/vqKUQ/6 -/X5aBiOVF1yTIRYRXrV3aEvJRzErvQxziT9cLxQq+BFUZqn9pISnPSf9dn0wf9kU -TxI79zIvne9UT/rDsM0BxSydwtjG00MT ------END ECDSA PUBLIC KEY----- -`) - cfg Configuration + version string = "master" + cfg Configuration ) -func equinoxUpdate(channel string, skipConfirm bool) error { - var opts equinox.Options - if err := opts.SetPublicKeyPEM(publicKey); err != nil { - return err +type TagInfo struct { + Version string `json:"tag_name"` + Body string `json:"body"` + CreatedAt string `json:"created_at"` +} + +func githubLatestVersion(repo, name string) (tag TagInfo, err error) { + githubURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", repo, name) + req := goreq.Request{Uri: githubURL} + ghToken := os.Getenv("GITHUB_TOKEN") + if ghToken != "" { + req.AddHeader("Authorization", "token "+ghToken) } - opts.Channel = channel + res, err := req.Do() + if err != nil { + return + } + err = res.Body.FromJsonTo(&tag) + return +} - // check for the update - resp, err := equinox.Check(appID, opts) - switch { - case err == equinox.NotAvailableErr: - fmt.Println("No update available, already at the latest version!") - return nil - case err != nil: +func githubUpdate(skipConfirm bool) error { + repo, name := "codeskyblue", "gosuv" + tag, err := githubLatestVersion(repo, name) + if err != nil { fmt.Println("Update failed:", err) return err } + if tag.Version == version { + fmt.Println("No update available, already at the latest version!") + return nil + } - fmt.Println("New version available!") - fmt.Println("Version:", resp.ReleaseVersion) - fmt.Println("Name:", resp.ReleaseTitle) - fmt.Println("Details:", resp.ReleaseDescription) + fmt.Println("New version available -- ", tag.Version) + fmt.Print(tag.Body) if !skipConfirm { - fmt.Printf("Would you like to update [y/n]? ") - if !askForConfirmation() { + if !askForConfirmation("Would you like to update [Y/n]? ", true) { return nil } } - //fmt.Printf("New version available: %s downloading ... \n", resp.ReleaseVersion) - // fetch the update and apply it - err = resp.Apply() - if err != nil { - return err + fmt.Printf("New version available: %s downloading ... \n", tag.Version) + // // fetch the update and apply it + // err = resp.Apply() + // if err != nil { + // return err + // } + cleanVersion := tag.Version + if strings.HasPrefix(cleanVersion, "v") { + cleanVersion = cleanVersion[1:] } + osArch := runtime.GOOS + "_" + runtime.GOARCH - fmt.Printf("Updated to new version: %s!\n", resp.ReleaseVersion) + downloadURL := StringFormat("https://github.com/{repo}/{name}/releases/download/{tag}/{name}_{version}_{os_arch}.tar.gz", map[string]interface{}{ + "repo": "codeskyblue", + "name": "gosuv", + "tag": tag.Version, + "version": cleanVersion, + "os_arch": osArch, + }) + fmt.Println("Not finished yet. download from:", downloadURL) + // fmt.Printf("Updated to new version: %s!\n", tag.Version) return nil } diff --git a/utils.go b/utils.go index 6175265..84f0c42 100644 --- a/utils.go +++ b/utils.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "runtime" + "strings" "time" "github.com/qiniu/log" @@ -70,11 +71,12 @@ func UserHomeDir() string { // confirmations. If the input is not recognized, it will ask again. The function does not return // until it gets a valid response from the user. Typically, you should use fmt to print out a question // before calling askForConfirmation. E.g. fmt.Println("WARNING: Are you sure? (yes/no)") -func askForConfirmation() bool { +func askForConfirmation(prompt string, _default bool) bool { var response string + fmt.Print(prompt) _, err := fmt.Scanln(&response) if err != nil { - log.Fatal(err) + return _default } okayResponses := []string{"y", "Y", "yes", "Yes", "YES"} nokayResponses := []string{"n", "N", "no", "No", "NO"} @@ -83,8 +85,7 @@ func askForConfirmation() bool { } else if containsString(nokayResponses, response) { return false } else { - fmt.Println("Please type yes or no and then press enter:") - return askForConfirmation() + return askForConfirmation(prompt, _default) } } @@ -105,3 +106,10 @@ func posString(slice []string, element string) int { func containsString(slice []string, element string) bool { return !(posString(slice, element) == -1) } + +func StringFormat(format string, m map[string]interface{}) string { + for k, v := range m { + format = strings.Replace(format, "{"+k+"}", fmt.Sprintf("%v", v), -1) + } + return format +}