fix: loading print panic
This commit is contained in:
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@ -11,9 +12,9 @@ import (
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/loveuer/nf/nft/loading"
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"github.com/loveuer/nf/nft/nfctl/internal/opt"
|
||||
"github.com/loveuer/nf/nft/nfctl/pkg/loading"
|
||||
"github.com/loveuer/nf/nft/tool"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -32,7 +33,7 @@ func initNew() *cobra.Command {
|
||||
return newCmd
|
||||
}
|
||||
|
||||
func doNew(cmd *cobra.Command, args []string) error {
|
||||
func doNew(cmd *cobra.Command, args []string) (err error) {
|
||||
if len(args) == 0 {
|
||||
return errors.New("必须提供 project 名称")
|
||||
}
|
||||
@ -46,108 +47,103 @@ func doNew(cmd *cobra.Command, args []string) error {
|
||||
return errors.New("project 名称不能以 . 开头")
|
||||
}
|
||||
|
||||
ch := make(chan *loading.Loading)
|
||||
defer close(ch)
|
||||
return loading.Do(cmd.Context(), func(ctx context.Context, print func(msg string, types ...loading.Type)) error {
|
||||
print("开始新建项目: "+args[0], loading.TypeInfo)
|
||||
|
||||
go loading.Print(cmd.Context(), ch)
|
||||
ch <- &loading.Loading{Content: "开始新建项目: " + args[0], Type: loading.TypeInfo}
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeError}
|
||||
return err
|
||||
}
|
||||
|
||||
moduleName := args[0]
|
||||
pwd = path.Join(filepath.ToSlash(pwd), base)
|
||||
|
||||
log.Debug("cmd.new: new project, pwd = %s, name = %s, template = %s", pwd, moduleName, opt.Cfg.New.Template)
|
||||
|
||||
ch <- &loading.Loading{Content: "开始下载模板: " + opt.Cfg.New.Template, Type: loading.TypeProcessing}
|
||||
|
||||
repo := opt.Cfg.New.Template
|
||||
if v, ok := opt.TemplateMap[repo]; ok {
|
||||
repo = v
|
||||
}
|
||||
|
||||
if err = tool.Clone(pwd, repo); err != nil {
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeError}
|
||||
return err
|
||||
}
|
||||
|
||||
ch <- &loading.Loading{Content: "下载模板完成: " + opt.Cfg.New.Template, Type: loading.TypeSuccess}
|
||||
|
||||
if err = os.RemoveAll(path.Join(pwd, ".git")); err != nil {
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeWarning}
|
||||
}
|
||||
|
||||
ch <- &loading.Loading{Content: "开始初始化项目: " + args[0], Type: loading.TypeProcessing}
|
||||
|
||||
if err = filepath.Walk(pwd, func(path string, info os.FileInfo, err error) error {
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
moduleName := args[0]
|
||||
pwd = path.Join(filepath.ToSlash(pwd), base)
|
||||
|
||||
log.Debug("cmd.new: new project, pwd = %s, name = %s, template = %s", pwd, moduleName, opt.Cfg.New.Template)
|
||||
|
||||
print("开始下载模板: "+opt.Cfg.New.Template, loading.TypeProcessing)
|
||||
|
||||
repo := opt.Cfg.New.Template
|
||||
if v, ok := opt.TemplateMap[repo]; ok {
|
||||
repo = v
|
||||
}
|
||||
|
||||
if strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "go.mod") {
|
||||
var content []byte
|
||||
if content, err = os.ReadFile(path); err != nil {
|
||||
ch <- &loading.Loading{Content: "初始化文件失败: " + err.Error(), Type: loading.TypeWarning}
|
||||
ch <- &loading.Loading{Content: "开始初始化项目: " + args[0], Type: loading.TypeProcessing}
|
||||
if err = tool.Clone(pwd, repo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print("下载模板完成: "+opt.Cfg.New.Template, loading.TypeSuccess)
|
||||
|
||||
if err = os.RemoveAll(path.Join(pwd, ".git")); err != nil {
|
||||
print(err.Error(), loading.TypeWarning)
|
||||
}
|
||||
|
||||
print("开始初始化项目: "+args[0], loading.TypeProcessing)
|
||||
|
||||
if err = filepath.Walk(pwd, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(content))
|
||||
replaced := make([]string, 0, 16)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// 操作 go.mod 文件时, 忽略 toolchain 行, 以更好的兼容 go1.20
|
||||
if strings.HasSuffix(path, "go.mod") && strings.HasPrefix(line, "toolchain") {
|
||||
continue
|
||||
if strings.HasSuffix(path, ".go") || strings.HasSuffix(path, "go.mod") {
|
||||
var content []byte
|
||||
if content, err = os.ReadFile(path); err != nil {
|
||||
print("初始化文件失败: "+err.Error(), loading.TypeWarning)
|
||||
print("开始初始化项目: "+args[0], loading.TypeProcessing)
|
||||
return nil
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewReader(content))
|
||||
replaced := make([]string, 0, 16)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
// 操作 go.mod 文件时, 忽略 toolchain 行, 以更好的兼容 go1.20
|
||||
if strings.HasSuffix(path, "go.mod") && strings.HasPrefix(line, "toolchain") {
|
||||
continue
|
||||
}
|
||||
replaced = append(replaced, strings.ReplaceAll(line, opt.Cfg.New.Template, moduleName))
|
||||
}
|
||||
if err = os.WriteFile(path, []byte(strings.Join(replaced, "\n")), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
replaced = append(replaced, strings.ReplaceAll(line, opt.Cfg.New.Template, moduleName))
|
||||
}
|
||||
if err = os.WriteFile(path, []byte(strings.Join(replaced, "\n")), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
render *template.Template
|
||||
rf *os.File
|
||||
)
|
||||
|
||||
if render, err = template.New(base).Parse(opt.README); err != nil {
|
||||
log.Debug("cmd.new: new text template err, err = %s", err.Error())
|
||||
print("生成 readme 失败", loading.TypeWarning)
|
||||
goto END
|
||||
}
|
||||
|
||||
if rf, err = os.OpenFile(path.Join(pwd, "readme.md"), os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o644); err != nil {
|
||||
log.Debug("cmd.new: new readme file err, err = %s", err.Error())
|
||||
print("生成 readme 失败", loading.TypeWarning)
|
||||
goto END
|
||||
}
|
||||
defer rf.Close()
|
||||
|
||||
if err = render.Execute(rf, map[string]any{
|
||||
"project_name": base,
|
||||
}); err != nil {
|
||||
log.Debug("cmd.new: template execute err, err = %s", err.Error())
|
||||
print("生成 readme 失败", loading.TypeWarning)
|
||||
}
|
||||
|
||||
END:
|
||||
print(fmt.Sprintf("项目: %s 初始化成功", args[0]), loading.TypeSuccess)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
ch <- &loading.Loading{Content: "初始化文件失败: " + err.Error(), Type: loading.TypeWarning}
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
render *template.Template
|
||||
rf *os.File
|
||||
)
|
||||
|
||||
if render, err = template.New(base).Parse(opt.README); err != nil {
|
||||
log.Debug("cmd.new: new text template err, err = %s", err.Error())
|
||||
ch <- &loading.Loading{Content: "生成 readme 失败", Type: loading.TypeWarning}
|
||||
goto END
|
||||
}
|
||||
|
||||
if rf, err = os.OpenFile(path.Join(pwd, "readme.md"), os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o644); err != nil {
|
||||
log.Debug("cmd.new: new readme file err, err = %s", err.Error())
|
||||
ch <- &loading.Loading{Content: "生成 readme 失败", Type: loading.TypeWarning}
|
||||
goto END
|
||||
}
|
||||
defer rf.Close()
|
||||
|
||||
if err = render.Execute(rf, map[string]any{
|
||||
"project_name": base,
|
||||
}); err != nil {
|
||||
log.Debug("cmd.new: template execute err, err = %s", err.Error())
|
||||
ch <- &loading.Loading{Content: "生成 readme 失败", Type: loading.TypeWarning}
|
||||
}
|
||||
|
||||
END:
|
||||
ch <- &loading.Loading{Content: fmt.Sprintf("项目: %s 初始化成功", args[0]), Type: loading.TypeSuccess}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -9,16 +9,19 @@ import (
|
||||
"time"
|
||||
|
||||
resty "github.com/go-resty/resty/v2"
|
||||
"github.com/loveuer/nf/nft/loading"
|
||||
"github.com/loveuer/nf/nft/log"
|
||||
"github.com/loveuer/nf/nft/nfctl/internal/opt"
|
||||
"github.com/loveuer/nf/nft/nfctl/pkg/loading"
|
||||
"github.com/loveuer/nf/nft/tool"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var updateCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "update nfctl self",
|
||||
RunE: func(cmd *cobra.Command, args []string) error { return nil },
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func initUpdate() *cobra.Command {
|
||||
@ -26,61 +29,55 @@ func initUpdate() *cobra.Command {
|
||||
}
|
||||
|
||||
func doUpdate(ctx context.Context) (err error) {
|
||||
ch := make(chan *loading.Loading)
|
||||
defer close(ch)
|
||||
return loading.Do(tool.TimeoutCtx(ctx, 30), func(ctx context.Context, print func(msg string, types ...loading.Type)) error {
|
||||
print("正在检查更新...")
|
||||
tip := "❗ 请尝试手动更新: go install github.com/loveuer/nf/nft/nfctl@master"
|
||||
version := ""
|
||||
|
||||
go func() {
|
||||
loading.Print(ctx, ch)
|
||||
}()
|
||||
|
||||
ch <- &loading.Loading{Content: "正在检查更新...", Type: loading.TypeProcessing}
|
||||
tip := "❗ 请尝试手动更新: go install github.com/loveuer/nf/nft/nfctl@latest"
|
||||
version := ""
|
||||
|
||||
var rr *resty.Response
|
||||
if rr, err = resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).R().
|
||||
SetContext(ctx).
|
||||
Get(opt.VersionURL); err != nil {
|
||||
err = fmt.Errorf("检查更新失败: %s\n%s", err.Error(), tip)
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeError}
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("cmd.update: url = %s, raw_response = %s", opt.VersionURL, rr.String())
|
||||
|
||||
if rr.StatusCode() != 200 {
|
||||
err = fmt.Errorf("检查更新失败: %s\n%s", rr.Status(), tip)
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeError}
|
||||
return
|
||||
}
|
||||
|
||||
reg := regexp.MustCompile(`const Version = "v\d{2}\.\d{2}\.\d{2}-r\d{1,2}"`)
|
||||
for _, line := range strings.Split(rr.String(), "\n") {
|
||||
if reg.MatchString(line) {
|
||||
version = strings.TrimSpace(strings.TrimPrefix(line, "const Version = "))
|
||||
version = version[1 : len(version)-1]
|
||||
break
|
||||
var rr *resty.Response
|
||||
if rr, err = resty.New().SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}).R().
|
||||
SetContext(ctx).
|
||||
Get(opt.VersionURL); err != nil {
|
||||
err = fmt.Errorf("检查更新失败: %s\n%s", err.Error(), tip)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if version == "" {
|
||||
err = fmt.Errorf("检查更新失败: 未找到版本信息\n%s", tip)
|
||||
ch <- &loading.Loading{Content: err.Error(), Type: loading.TypeError}
|
||||
return err
|
||||
}
|
||||
log.Debug("cmd.update: url = %s, raw_response = %s", opt.VersionURL, rr.String())
|
||||
|
||||
log.Debug("cmd.update: find version = %s, now_version = %s", version, opt.Version)
|
||||
if rr.StatusCode() != 200 {
|
||||
err = fmt.Errorf("检查更新失败: %s\n%s", rr.Status(), tip)
|
||||
return err
|
||||
}
|
||||
|
||||
reg := regexp.MustCompile(`const Version = "v\d{2}\.\d{2}\.\d{2}-r\d{1,2}"`)
|
||||
for _, line := range strings.Split(rr.String(), "\n") {
|
||||
if reg.MatchString(line) {
|
||||
version = strings.TrimSpace(strings.TrimPrefix(line, "const Version = "))
|
||||
version = version[1 : len(version)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if version == "" {
|
||||
err = fmt.Errorf("检查更新失败: 未找到版本信息\n%s", tip)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debug("cmd.update: find version = %s, now_version = %s", version, opt.Version)
|
||||
|
||||
if version <= opt.Version {
|
||||
print(fmt.Sprintf("已是最新版本: %s", opt.Version), loading.TypeSuccess)
|
||||
return nil
|
||||
}
|
||||
|
||||
print(fmt.Sprintf("发现新版本: %s", version), loading.TypeInfo)
|
||||
|
||||
print(fmt.Sprintf("正在更新到 %s ...", version))
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
print("暂时无法自动更新, 请尝试手动更新: go install github.com/loveuer/nf/nft/nfctl@master", loading.TypeWarning)
|
||||
|
||||
if version <= opt.Version {
|
||||
ch <- &loading.Loading{Content: fmt.Sprintf("已是最新版本: %s", opt.Version), Type: loading.TypeSuccess}
|
||||
return nil
|
||||
}
|
||||
|
||||
ch <- &loading.Loading{Content: fmt.Sprintf("发现新版本: %s", version), Type: loading.TypeInfo}
|
||||
|
||||
ch <- &loading.Loading{Content: fmt.Sprintf("正在更新到 %s ...", version)}
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
ch <- &loading.Loading{Content: "暂时无法自动更新, 请尝试手动更新: go install github.com/loveuer/nf/nft/nfctl@latest", Type: loading.TypeWarning}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package opt
|
||||
|
||||
const Version = "v24.12.27-r02"
|
||||
const Version = "v24.12.27-r03"
|
||||
|
||||
// const VersionURL = "https://github.com/loveuer/nf/nft/nfctl/internal/opt/version.go"
|
||||
|
||||
|
Reference in New Issue
Block a user