| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- // 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/minio/selfupdate"
- "github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
- "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
- "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"
- )
- 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)
- // go get -u
- command := fmt.Sprintf(`cd %s && go get -u %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.Remove(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
- }
|