mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-09-19 17:56:42 +08:00
222 lines
5.5 KiB
Go
222 lines
5.5 KiB
Go
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
// If a copy of the MIT was not distributed with this file,
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"runtime"
|
|
|
|
"github.com/gogf/selfupdate"
|
|
|
|
"github.com/gogf/gf/v2/container/gset"
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
"github.com/gogf/gf/v2/os/gfile"
|
|
"github.com/gogf/gf/v2/os/gproc"
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
"github.com/gogf/gf/v2/util/gtag"
|
|
|
|
"hotgo/internal/library/hggen/internal/utility/mlog"
|
|
"hotgo/internal/library/hggen/internal/utility/utils"
|
|
)
|
|
|
|
var (
|
|
Up = cUp{}
|
|
)
|
|
|
|
type cUp struct {
|
|
g.Meta `name:"up" brief:"upgrade GoFrame version/tool to latest one in current project" eg:"{cUpEg}" `
|
|
}
|
|
|
|
const (
|
|
gfPackage = `github.com/gogf/gf/`
|
|
cUpEg = `
|
|
gf up
|
|
gf up -a
|
|
gf up -c
|
|
gf up -cf
|
|
`
|
|
)
|
|
|
|
func init() {
|
|
gtag.Sets(g.MapStrStr{
|
|
`cUpEg`: cUpEg,
|
|
})
|
|
}
|
|
|
|
type cUpInput struct {
|
|
g.Meta `name:"up" config:"gfcli.up"`
|
|
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
|
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
|
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
|
}
|
|
|
|
type cUpOutput struct{}
|
|
|
|
func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error) {
|
|
defer func() {
|
|
if err == nil {
|
|
mlog.Print()
|
|
mlog.Print(`👏congratulations! you've upgraded to the latest version of GoFrame! enjoy it!👏`)
|
|
mlog.Print()
|
|
}
|
|
}()
|
|
|
|
var doUpgradeVersionOut *doUpgradeVersionOutput
|
|
if in.All {
|
|
in.Cli = true
|
|
in.Fix = true
|
|
}
|
|
if doUpgradeVersionOut, err = c.doUpgradeVersion(ctx, in); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if in.Cli {
|
|
if err = c.doUpgradeCLI(ctx); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if in.Cli && in.Fix {
|
|
if doUpgradeVersionOut != nil && len(doUpgradeVersionOut.Items) > 0 {
|
|
upgradedPathSet := gset.NewStrSet()
|
|
for _, item := range doUpgradeVersionOut.Items {
|
|
if !upgradedPathSet.AddIfNotExist(item.DirPath) {
|
|
continue
|
|
}
|
|
if err = c.doAutoFixing(ctx, item.DirPath, item.Version); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
type doUpgradeVersionOutput struct {
|
|
Items []doUpgradeVersionOutputItem
|
|
}
|
|
|
|
type doUpgradeVersionOutputItem struct {
|
|
DirPath string
|
|
Version string
|
|
}
|
|
|
|
func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeVersionOutput, err error) {
|
|
mlog.Print(`start upgrading version...`)
|
|
out = &doUpgradeVersionOutput{
|
|
Items: make([]doUpgradeVersionOutputItem, 0),
|
|
}
|
|
type Package struct {
|
|
Name string
|
|
Version string
|
|
}
|
|
|
|
var (
|
|
temp string
|
|
dirPath = gfile.Pwd()
|
|
goModPath = gfile.Join(dirPath, "go.mod")
|
|
)
|
|
// It recursively upgrades the go.mod from sub folder to its parent folders.
|
|
for {
|
|
if gfile.Exists(goModPath) {
|
|
var packages []Package
|
|
err = gfile.ReadLines(goModPath, func(line string) error {
|
|
line = gstr.Trim(line)
|
|
line = gstr.TrimLeftStr(line, "require ")
|
|
line = gstr.Trim(line)
|
|
if gstr.HasPrefix(line, gfPackage) {
|
|
array := gstr.SplitAndTrim(line, " ")
|
|
packages = append(packages, Package{
|
|
Name: array[0],
|
|
Version: array[1],
|
|
})
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, pkg := range packages {
|
|
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
|
|
mlog.Printf(`running command: go get %s@latest`, pkg.Name)
|
|
// go get @latest
|
|
command := fmt.Sprintf(`cd %s && go get %s@latest`, dirPath, pkg.Name)
|
|
if err = gproc.ShellRun(ctx, command); err != nil {
|
|
return
|
|
}
|
|
// go mod tidy
|
|
if err = utils.GoModTidy(ctx, dirPath); err != nil {
|
|
return nil, err
|
|
}
|
|
out.Items = append(out.Items, doUpgradeVersionOutputItem{
|
|
DirPath: dirPath,
|
|
Version: pkg.Version,
|
|
})
|
|
}
|
|
return
|
|
}
|
|
temp = gfile.Dir(dirPath)
|
|
if temp == "" || temp == dirPath {
|
|
return
|
|
}
|
|
dirPath = temp
|
|
goModPath = gfile.Join(dirPath, "go.mod")
|
|
}
|
|
}
|
|
|
|
// doUpgradeCLI downloads the new version binary with process.
|
|
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
|
mlog.Print(`start upgrading cli...`)
|
|
var (
|
|
downloadUrl = fmt.Sprintf(
|
|
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
|
|
runtime.GOOS, runtime.GOARCH,
|
|
)
|
|
localSaveFilePath = gfile.SelfPath() + "~"
|
|
)
|
|
|
|
if runtime.GOOS == "windows" {
|
|
downloadUrl += ".exe"
|
|
}
|
|
|
|
mlog.Printf(`start downloading "%s" to "%s", it may take some time`, downloadUrl, localSaveFilePath)
|
|
err = utils.HTTPDownloadFileWithPercent(downloadUrl, localSaveFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer func() {
|
|
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
|
|
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
|
|
_ = gfile.RemoveFile(localSaveFilePath)
|
|
}()
|
|
|
|
// It fails if file not exist or its size is less than 1MB.
|
|
if !gfile.Exists(localSaveFilePath) || gfile.Size(localSaveFilePath) < 1024*1024 {
|
|
mlog.Fatalf(`download "%s" to "%s" failed`, downloadUrl, localSaveFilePath)
|
|
}
|
|
|
|
newFile, err := gfile.Open(localSaveFilePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// selfupdate
|
|
err = selfupdate.Apply(newFile, selfupdate.Options{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return
|
|
}
|
|
|
|
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
|
|
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
|
|
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
|
|
_ = gproc.ShellRun(ctx, command)
|
|
return
|
|
}
|