Skip to content

Commit

Permalink
perf: optimized upgrade code
Browse files Browse the repository at this point in the history
  • Loading branch information
teamssix committed Aug 13, 2022
1 parent 6f91bfd commit f8a473f
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 64 deletions.
20 changes: 11 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
BUILD_ENV := CGO_ENABLED=0
LDFLAGS=-v -a -ldflags '-s -w' -gcflags="all=-trimpath=${PWD}" -asmflags="all=-trimpath=${PWD}"
VERSION=v0.3.2

TARGET_EXEC := cf

Expand All @@ -9,15 +8,18 @@ TARGET_EXEC := cf
all: setup build-linux build-osx build-windows

setup:
mkdir -p build/linux
mkdir -p build/osx
mkdir -p build/windows

build-linux:
${BUILD_ENV} GOARCH=amd64 GOOS=linux go build ${LDFLAGS} -o build/linux/${TARGET_EXEC}-${VERSION}-linux-amd64
mkdir -p build

build-osx:
${BUILD_ENV} GOARCH=amd64 GOOS=darwin go build ${LDFLAGS} -o build/osx/${TARGET_EXEC}-${VERSION}-darwin-amd64
${BUILD_ENV} GOARCH=amd64 GOOS=darwin go build ${LDFLAGS} -o build/${TARGET_EXEC}_darwin_amd64
${BUILD_ENV} GOARCH=arm64 GOOS=darwin go build ${LDFLAGS} -o build/${TARGET_EXEC}_darwin_arm64

build-linux:
${BUILD_ENV} GOARCH=amd64 GOOS=linux go build ${LDFLAGS} -o build/${TARGET_EXEC}_linux_amd64
${BUILD_ENV} GOARCH=arm64 GOOS=linux go build ${LDFLAGS} -o build/${TARGET_EXEC}_linux_arm64
${BUILD_ENV} GOARCH=386 GOOS=linux go build ${LDFLAGS} -o build/${TARGET_EXEC}_linux_386

build-windows:
${BUILD_ENV} GOARCH=amd64 GOOS=windows go build ${LDFLAGS} -o build/windows/${TARGET_EXEC}-${VERSION}-windows-amd64.exe
${BUILD_ENV} GOARCH=amd64 GOOS=windows go build ${LDFLAGS} -o build/${TARGET_EXEC}_windows_amd64.exe
${BUILD_ENV} GOARCH=arm64 GOOS=windows go build ${LDFLAGS} -o build/${TARGET_EXEC}_windows_arm64.exe
${BUILD_ENV} GOARCH=386 GOOS=windows go build ${LDFLAGS} -o build/${TARGET_EXEC}_windows_386.exe
3 changes: 2 additions & 1 deletion cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"github.com/spf13/cobra"
"github.com/teamssix/cf/pkg/util"
"github.com/teamssix/cf/pkg/util/cmdutil"
)

Expand All @@ -14,6 +15,6 @@ var upgradeCmd = &cobra.Command{
Short: "更新 cf 到最新版本 (Update cf to the latest version)",
Long: "更新 cf 到最新版本 (Update cf to the latest version)",
Run: func(cmd *cobra.Command, args []string) {
cmdutil.Upgrade()
cmdutil.Upgrade(util.GetCurrentVersion())
},
}
202 changes: 181 additions & 21 deletions pkg/util/cmdutil/upgrade.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,200 @@
package cmdutil

import (
"archive/tar"
"archive/zip"
"compress/gzip"
"fmt"
"github.com/schollz/progressbar/v3"
log "github.com/sirupsen/logrus"
"github.com/teamssix/cf/pkg/util"
"github.com/tj/go-update"
"github.com/tj/go-update/progress"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
)

func Upgrade() {
Check, latest, m := util.CheckVersion()
if Check {
currentOS := runtime.GOOS
var final *update.Asset
switch runtime.GOOS {
case "windows":
final = latest.FindZip(currentOS, runtime.GOARCH)
default:
final = latest.FindTarball(currentOS, runtime.GOARCH)
var cfWorkDir, _ = filepath.Abs(filepath.Dir(os.Args[0]))

func Upgrade(version string) {
var (
downloadURL string
fileName string
)
check, newVersion := util.CheckVersion(version)
if check {
log.Infof("当前版本为 %s ,发现 %s 新版本,正在下载新版本 (The current version is %s , Found %s new version, downloading new version now)", version, newVersion, version, newVersion)
if runtime.GOOS == "windows" {
fileName = fmt.Sprintf("cf_%s_%s_%s.zip", newVersion, runtime.GOOS, runtime.GOARCH)
} else {
fileName = fmt.Sprintf("cf_%s_%s_%s.tar.gz", newVersion, runtime.GOOS, runtime.GOARCH)
}
if final == nil {
log.Errorln("未找到该系统的二进制文件,更新失败 (The binary file for this system was not found and the update failed)")
os.Exit(0)
if isMainLand() {
downloadURL = fmt.Sprintf("https://ghproxy.com/github.com/teamssix/cf/releases/download/%s/%s", newVersion, fileName)
} else {
downloadURL = fmt.Sprintf("https://github.com/teamssix/cf/releases/download/%s/%s", newVersion, fileName)
}
log.Infoln("正在下载中…… (Downloading...)")
tarball, err := final.DownloadProxy(progress.Reader)
path, _ := os.Executable()
_, oldFileName := filepath.Split(path)
oldBakFileName := cfWorkDir + "/" + oldFileName + ".bak"
downloadFile(downloadURL, fileName)
err := os.Rename(cfWorkDir+"/"+oldFileName, oldBakFileName)
util.HandleErr(err)
unzipFile(fileName)
err = os.Remove(fileName)
util.HandleErr(err)
log.Infof("更新完成,历史版本已被重命名为 %s (The update is complete and the previous version has been renamed to %s)", oldFileName+".bak", oldFileName+".bak")
} else {
log.Infof("当前 %s 版本为最新版本,无需升级 (The current %s version is the latest version, no need to upgrade)", version, version)
}
}

func downloadFile(downloadURL string, fileName string) {
log.Debugln("下载地址 (download url): " + downloadURL)
req, err := http.NewRequest("GET", downloadURL, nil)
util.HandleErr(err)
resp, err := http.DefaultClient.Do(req)
util.HandleErr(err)
defer resp.Body.Close()
f, _ := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0644)
defer f.Close()
bar := progressbar.NewOptions64(resp.ContentLength,
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionEnableColorCodes(true),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
progressbar.OptionSetWidth(50),
progressbar.OptionSetDescription("Downloading..."),
progressbar.OptionOnCompletion(func() {
fmt.Println()
}),
progressbar.OptionSetTheme(progressbar.Theme{
Saucer: "[green]=[reset]",
SaucerHead: "[green]>[reset]",
SaucerPadding: " ",
BarStart: "[",
BarEnd: "]",
}))
io.Copy(io.MultiWriter(f, bar), resp.Body)
log.Debugln("下载完成 (Download completed)")
}

func unzipFile(fileName string) {
log.Debugf("正在解压 %s 文件 (Unpacking %s file now)", fileName, fileName)
cacheFolder := ReturnCacheDict()
if runtime.GOOS == "windows" {
archive, err := zip.OpenReader(fileName)
if err != nil {
util.HandleErr(err)
}
currentPath, _ := os.Getwd()
if err = m.InstallTo(tarball, currentPath); err != nil {
defer archive.Close()
for _, f := range archive.File {
filePath := filepath.Join(cacheFolder, f.Name)
if !strings.HasPrefix(filePath, filepath.Clean(cacheFolder)+string(os.PathSeparator)) {
log.Errorln("无效的文件路径 (invalid file path)")
}
if f.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
}

if err = os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
util.HandleErr(err)
}
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
util.HandleErr(err)
}
fileInArchive, err := f.Open()
if err != nil {
util.HandleErr(err)
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
util.HandleErr(err)
}
dstFile.Close()
fileInArchive.Close()
}
oldCfPath := filepath.Join(cacheFolder, "cf.exe")
newCfPath := filepath.Join(cfWorkDir, "cf.exe")
log.Tracef("将 %s 文件移动到 %s (Move the %s file to %s)", oldCfPath, newCfPath, oldCfPath, newCfPath)
os.Rename(oldCfPath, newCfPath)
} else {
gzipStream, err := os.Open(fileName)
util.HandleErr(err)
defer gzipStream.Close()
uncompressedStream, err := gzip.NewReader(gzipStream)
util.HandleErr(err)
defer uncompressedStream.Close()
tarReader := tar.NewReader(uncompressedStream)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
util.HandleErr(err)
if err != nil {
if err == io.EOF {
break
}
}
subFileName := filepath.Join(cacheFolder, header.Name)
file, err := createFile(subFileName)
util.HandleErr(err)
io.Copy(file, tarReader)
}
log.Infoln("升级完成 (Upgrade completed)")
log.Debugln("解压完成 (Unzip completed)")
oldCfPath := filepath.Join(cacheFolder, "cf")
newCfPath := filepath.Join(cfWorkDir, "cf")
log.Tracef("将 %s 文件移动到 %s (Move the %s file to %s)", oldCfPath, newCfPath, oldCfPath, newCfPath)
os.Rename(oldCfPath, newCfPath)
log.Traceln("为 ./cf 文件赋予可执行权限 (Grant execute permission to ./cf file)")
f, err := os.Open(newCfPath)
util.HandleErr(err)
defer f.Close()
err = f.Chmod(0755)
util.HandleErr(err)
}
}

func createFile(name string) (*os.File, error) {
err := os.MkdirAll(string([]rune(name)[0:strings.LastIndex(name, "/")]), 0755)
if err != nil {
return nil, err
}
return os.Create(name)
}

func isMainLand() bool {
client := &http.Client{}
req, _ := http.NewRequest("GET", "http://cip.cc", nil)
req.Header.Add("User-Agent", "curl/7.64.1")
resp, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
address := strings.Split(string(body), "\n")[1]
log.Tracef("当前地址为 (The current address is): %s", strings.Split(address, ":")[1])
if isRegions(address) && strings.Contains(address, "中国") {
return true
} else {
return false
}
}

func isRegions(address string) bool {
var (
cityList = [3]string{"香港", "澳门", "台湾"}
num = 0
)
for _, v := range cityList {
if strings.Contains(address, v) {
num = num + 1
}
}
if num == 0 {
return true
} else {
log.Infof("当前版本为最新版本,无需升级 (The current version is the latest version, no need to upgrade)")
return false
}
}
Loading

0 comments on commit f8a473f

Please sign in to comment.