Skip to content

Commit

Permalink
support self upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
PWZER committed Oct 15, 2024
1 parent de01b02 commit fca6f2e
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 82 deletions.
27 changes: 27 additions & 0 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright © 2024 PWZER <[email protected]>
*/
package cmd

import (
"github.com/PWZER/govm/internal"
"github.com/spf13/cobra"
)

var (
dummy bool
)

var upgradeCmd = &cobra.Command{
Use: "upgrade",
Short: "upgrade govm to the latest version",
Long: "upgrade govm to the latest version",
RunE: func(cmd *cobra.Command, args []string) error {
return internal.Upgrade(dummy, Version)
},
}

func init() {
rootCmd.AddCommand(upgradeCmd)
upgradeCmd.Flags().BoolVar(&dummy, "dummy", false, "dummy flag for testing")
}
8 changes: 5 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ module github.com/PWZER/govm

go 1.23.0

toolchain go1.21.0

require (
github.com/schollz/progressbar/v3 v3.16.1
github.com/spf13/cobra v1.8.1
golang.org/x/mod v0.21.0
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
)
23 changes: 21 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/schollz/progressbar/v3 v3.16.1 h1:RnF1neWZFzLCoGx8yp1yF7SDl4AzNDI5y4I0aUJRrZQ=
github.com/schollz/progressbar/v3 v3.16.1/go.mod h1:I2ILR76gz5VXqYMIY/LdLecvMHDPVcQm3W/MSKi1TME=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
11 changes: 8 additions & 3 deletions internal/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"path/filepath"
"runtime"
"strings"

"github.com/schollz/progressbar/v3"
)

func init() {
Expand Down Expand Up @@ -75,15 +77,18 @@ func downloadArchiveFileFromURL(saveFile, srcURL string) (err error) {
if res.StatusCode != http.StatusOK {
return errors.New(res.Status)
}
pw := &progressWriter{w: fd, total: res.ContentLength, output: os.Stderr}
n, err := io.Copy(pw, res.Body)

bar := progressbar.DefaultBytes(
res.ContentLength,
"Downloading",
)
n, err := io.Copy(io.MultiWriter(fd, bar), res.Body)
if err != nil {
return err
}
if res.ContentLength != -1 && res.ContentLength != n {
return fmt.Errorf("downloaded size mismatch, expect %d but got %d", res.ContentLength, n)
}
pw.update() // 100%
return fd.Close()
}

Expand Down
74 changes: 0 additions & 74 deletions internal/progress.go

This file was deleted.

109 changes: 109 additions & 0 deletions internal/upgrade.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package internal

import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"runtime"
)

const (
latestVersionUrl string = "https://api.github.com/repos/PWZER/govm/releases/latest"
)

type versionAsset struct {
Url string `json:"url"`
Name string `json:"name"`
Size int `json:"size"`
BrowserDownloadUrl string `json:"browser_download_url"`
}

type latestVersion struct {
TagName string `json:"tag_name"`
Assets []versionAsset `json:"assets"`
}

func Upgrade(dummy bool, currentVersion string) (err error) {
req, err := http.NewRequest(http.MethodGet, latestVersionUrl, nil)
if err != nil {
return err
}
req.Header.Set("Accept", "application/vnd.github+json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to get latest version: %s", resp.Status)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return err
}

var latestVersion latestVersion
if err := json.Unmarshal(body, &latestVersion); err != nil {
return err
}

if latestVersion.TagName == "" {
return fmt.Errorf("failed to get latest version")
}

if latestVersion.TagName <= currentVersion {
fmt.Println("already the latest version")
return nil
}

if dummy {
fmt.Printf("Current version: %s, Latest version: %s\n", currentVersion, latestVersion.TagName)
return err
}

binPath, err := os.Executable()
if err != nil {
return err
}

var useAsset *versionAsset = nil
expectedAssetName := fmt.Sprintf("govm-%s-%s", runtime.GOOS, runtime.GOARCH)
for _, asset := range latestVersion.Assets {
if asset.Name == expectedAssetName {
useAsset = &asset
break
}
}

if useAsset == nil {
return fmt.Errorf("no asset found for %s", expectedAssetName)
}
fmt.Printf("Upgrade version %s => %s, downloading from %s\n",
currentVersion, latestVersion.TagName, useAsset.BrowserDownloadUrl)

tmpPath := filepath.Join(filepath.Dir(binPath), fmt.Sprintf(".%s.tmp", filepath.Base(binPath)))
if err := downloadArchiveFileFromURL(tmpPath, useAsset.BrowserDownloadUrl); err != nil {
return err
}

// check file size
stat, err := os.Stat(tmpPath)
if os.IsNotExist(err) {
return fmt.Errorf("downloaded file not found: %s", tmpPath)
} else if stat.Size() != int64(useAsset.Size) {
return fmt.Errorf("downloaded file size mismatch, expect %d but got %d", useAsset.Size, stat.Size())
}

// replace the binary
if err := os.Rename(tmpPath, binPath); err != nil {
return err
}
fmt.Printf("upgrade to version %s successfully\n", latestVersion.TagName)
return nil
}

0 comments on commit fca6f2e

Please sign in to comment.