diff --git a/selfupdate/uncompress.go b/selfupdate/uncompress.go new file mode 100644 index 0000000..9c3070d --- /dev/null +++ b/selfupdate/uncompress.go @@ -0,0 +1,62 @@ +package selfupdate + +import ( + "archive/tar" + "archive/zip" + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "strings" +) + +func uncompress(src io.Reader, url, cmd string) (io.Reader, error) { + if strings.HasSuffix(url, ".zip") { + // Zip format requires its file size for uncompressing. + // So we need to read the HTTP response into a buffer at first. + buf, err := ioutil.ReadAll(src) + if err != nil { + return nil, err + } + + r := bytes.NewReader(buf) + z, err := zip.NewReader(r, r.Size()) + if err != nil { + return nil, err + } + + for _, file := range z.File { + if file.Name == cmd { + return file.Open() + } + } + + return nil, fmt.Errorf("File '%s' for the command is not found in %s", cmd, url) + } else if strings.HasSuffix(url, ".gzip") { + return gzip.NewReader(src) + } else if strings.HasSuffix(url, ".tar.gz") { + gz, err := gzip.NewReader(src) + if err != nil { + return nil, err + } + + t := tar.NewReader(gz) + for { + h, err := t.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + if h.Name == cmd { + return t, nil + } + } + + return nil, fmt.Errorf("File '%s' for the command is not found in %s", cmd, url) + } + + return src, nil +} diff --git a/selfupdate/update.go b/selfupdate/update.go index 89836b4..592822a 100644 --- a/selfupdate/update.go +++ b/selfupdate/update.go @@ -1,71 +1,14 @@ package selfupdate import ( - "archive/tar" - "archive/zip" - "bytes" - "compress/gzip" "fmt" "github.com/blang/semver" "github.com/inconshreveable/go-update" - "io" - "io/ioutil" "net/http" "os" "path/filepath" - "strings" ) -func uncompress(src io.Reader, url, cmd string) (io.Reader, error) { - if strings.HasSuffix(url, ".zip") { - // Zip format requires its file size for uncompressing. - // So we need to read the HTTP response into a buffer at first. - buf, err := ioutil.ReadAll(src) - if err != nil { - return nil, err - } - - r := bytes.NewReader(buf) - z, err := zip.NewReader(r, r.Size()) - if err != nil { - return nil, err - } - - for _, file := range z.File { - if file.Name == cmd { - return file.Open() - } - } - - return nil, fmt.Errorf("File '%s' for the command is not found in %s", cmd, url) - } else if strings.HasSuffix(url, ".gzip") { - return gzip.NewReader(src) - } else if strings.HasSuffix(url, ".tar.gz") { - gz, err := gzip.NewReader(src) - if err != nil { - return nil, err - } - - t := tar.NewReader(gz) - for { - h, err := t.Next() - if err == io.EOF { - break - } - if err != nil { - return nil, err - } - if h.Name == cmd { - return t, nil - } - } - - return nil, fmt.Errorf("File '%s' for the command is not found in %s", cmd, url) - } - - return src, nil -} - // UpdateTo download an executable from assetURL and replace the current binary with the downloaded one. cmdPath is a file path to command executable. func UpdateTo(assetURL, cmdPath string) error { res, err := http.Get(assetURL)