From e28b00f76d308d0772b39f79ac5b140274d33d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Tue, 24 Oct 2023 02:51:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=92=8C=E9=87=8D=E5=90=AF=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/console/commands/panel.go | 9 ++- app/http/controllers/info_controller.go | 19 ++++-- pkg/tools/tools.go | 87 +++++++++++++++++++++---- pkg/tools/tools_test.go | 42 ++++++++++-- 4 files changed, 137 insertions(+), 20 deletions(-) diff --git a/app/console/commands/panel.go b/app/console/commands/panel.go index ff7e93f8..c9b76a36 100644 --- a/app/console/commands/panel.go +++ b/app/console/commands/panel.go @@ -86,13 +86,20 @@ func (receiver *Panel) Handle(ctx console.Context) error { return nil } - err = tools.UpdatePanel() + panel, err := tools.GetLatestPanelVersion() + if err != nil { + color.Redln("获取最新版本失败") + return err + } + + err = tools.UpdatePanel(panel) if err != nil { color.Redln("更新失败: " + err.Error()) return nil } color.Greenln("更新成功") + tools.RestartPanel() case "getInfo": var user models.User diff --git a/app/http/controllers/info_controller.go b/app/http/controllers/info_controller.go index 9b042511..b4839d20 100644 --- a/app/http/controllers/info_controller.go +++ b/app/http/controllers/info_controller.go @@ -160,7 +160,7 @@ func (c *InfoController) CheckUpdate(ctx http.Context) http.Response { return Error(ctx, http.StatusInternalServerError, "获取最新版本失败") } - if version == remote.Version { + if tools.VersionCompare(version, remote.Version, ">=") { return Success(ctx, http.Json{ "update": false, "version": remote.Version, @@ -187,12 +187,23 @@ func (c *InfoController) Update(ctx http.Context) http.Response { return Error(ctx, http.StatusInternalServerError, "当前有任务正在执行,禁止更新") } - err = tools.UpdatePanel() + panel, err := tools.GetLatestPanelVersion() if err != nil { - facades.Log().Error("[面板][InfoController] 更新面板失败 ", err.Error()) + facades.Log().With(map[string]any{ + "error": err.Error(), + }).Error("[面板][InfoController] 获取最新版本失败") + return Error(ctx, http.StatusInternalServerError, "获取最新版本失败") + } + + err = tools.UpdatePanel(panel) + if err != nil { + facades.Log().With(map[string]any{ + "error": err.Error(), + }).Error("[面板][InfoController] 更新面板失败") return Error(ctx, http.StatusInternalServerError, "更新失败: "+err.Error()) } + tools.RestartPanel() return Success(ctx, nil) } @@ -204,6 +215,6 @@ func (c *InfoController) Restart(ctx http.Context) http.Response { return Error(ctx, http.StatusInternalServerError, "当前有任务正在执行,禁止重启") } - tools.Exec("systemctl restart panel") + tools.RestartPanel() return Success(ctx, nil) } diff --git a/pkg/tools/tools.go b/pkg/tools/tools.go index 22614e52..074d4005 100644 --- a/pkg/tools/tools.go +++ b/pkg/tools/tools.go @@ -3,7 +3,9 @@ package tools import ( "errors" + "fmt" "os" + "strconv" "strings" "time" @@ -82,6 +84,72 @@ func VersionCompare(ver1, ver2, operator string) bool { return operator == "==" || operator == ">=" || operator == "<=" } +// GenerateVersions 获取版本列表 +func GenerateVersions(start, end string) ([]string, error) { + var versions []string + start = strings.TrimPrefix(start, "v") + end = strings.TrimPrefix(end, "v") + startParts := strings.Split(start, ".") + endParts := strings.Split(end, ".") + + if len(startParts) != 3 || len(endParts) != 3 { + return nil, fmt.Errorf("版本格式错误") + } + + startMajor, err := strconv.Atoi(startParts[0]) + if err != nil { + return nil, fmt.Errorf("无效的起始主版本号: %v", err) + } + startMinor, err := strconv.Atoi(startParts[1]) + if err != nil { + return nil, fmt.Errorf("无效的起始次版本号: %v", err) + } + startPatch, err := strconv.Atoi(startParts[2]) + if err != nil { + return nil, fmt.Errorf("无效的起始修订号: %v", err) + } + endMajor, err := strconv.Atoi(endParts[0]) + if err != nil { + return nil, fmt.Errorf("无效的结束主版本号: %v", err) + } + endMinor, err := strconv.Atoi(endParts[1]) + if err != nil { + return nil, fmt.Errorf("无效的结束次版本号: %v", err) + } + endPatch, err := strconv.Atoi(endParts[2]) + if err != nil { + return nil, fmt.Errorf("无效的结束修订号: %v", err) + } + + for major := startMajor; major <= endMajor; major++ { + for minor := 0; minor <= 99; minor++ { + for patch := 0; patch <= 99; patch++ { + if major == startMajor && minor < startMinor { + continue + } + if major == startMajor && minor == startMinor && patch <= startPatch { + continue + } + + if major == endMajor && minor > endMinor { + return versions, nil + } + if major == endMajor && minor == endMinor && patch > endPatch { + return versions, nil + } + + versions = append(versions, fmt.Sprintf("%d.%d.%d", major, minor, patch)) + } + } + } + + if len(versions) == 0 { + return []string{}, nil + } + + return versions, nil +} + type PanelInfo struct { Name string `json:"name"` Version string `json:"version"` @@ -217,13 +285,8 @@ func GetPanelVersion(version string) (PanelInfo, error) { } // UpdatePanel 更新面板 -func UpdatePanel() error { - panelInfo, err := GetLatestPanelVersion() - if err != nil { - return err - } - - color.Greenln("最新版本: " + panelInfo.Version) +func UpdatePanel(panelInfo PanelInfo) error { + color.Greenln("目标版本: " + panelInfo.Version) color.Greenln("下载链接: " + panelInfo.DownloadUrl) color.Greenln("备份面板配置...") @@ -270,13 +333,15 @@ func UpdatePanel() error { Exec("rm -rf /tmp/panel.db.bak") Exec("rm -rf /tmp/panel.conf.bak") - color.Greenln("重启面板...") - Exec("systemctl restart panel") - color.Greenln("重启完成") - return nil } +func RestartPanel() { + color.Greenln("重启面板...") + ExecAsync("sleep 2 && systemctl restart panel") + color.Greenln("重启完成") +} + // IsChina 是否中国大陆 func IsChina() bool { client := req.C() diff --git a/pkg/tools/tools_test.go b/pkg/tools/tools_test.go index 553a303f..d5959e70 100644 --- a/pkg/tools/tools_test.go +++ b/pkg/tools/tools_test.go @@ -19,7 +19,6 @@ func (s *HelperTestSuite) TestGetMonitoringInfo() { } func (s *HelperTestSuite) TestVersionCompare() { - // 测试相等情况 s.True(VersionCompare("1.0.0", "1.0.0", "==")) s.True(VersionCompare("1.0.0", "1.0.0", ">=")) s.True(VersionCompare("1.0.0", "1.0.0", "<=")) @@ -27,7 +26,6 @@ func (s *HelperTestSuite) TestVersionCompare() { s.False(VersionCompare("1.0.0", "1.0.0", "<")) s.False(VersionCompare("1.0.0", "1.0.0", "!=")) - // 测试1.0.0小于1.0.1 s.True(VersionCompare("1.0.0", "1.0.1", "<")) s.True(VersionCompare("1.0.0", "1.0.1", "<=")) s.True(VersionCompare("1.0.0", "1.0.1", "!=")) @@ -35,7 +33,6 @@ func (s *HelperTestSuite) TestVersionCompare() { s.False(VersionCompare("1.0.0", "1.0.1", ">=")) s.False(VersionCompare("1.0.0", "1.0.1", ">")) - // 测试1.0.1大于1.0.0 s.True(VersionCompare("1.0.1", "1.0.0", ">")) s.True(VersionCompare("1.0.1", "1.0.0", ">=")) s.True(VersionCompare("1.0.1", "1.0.0", "!=")) @@ -43,12 +40,49 @@ func (s *HelperTestSuite) TestVersionCompare() { s.False(VersionCompare("1.0.1", "1.0.0", "<=")) s.False(VersionCompare("1.0.1", "1.0.0", "<")) - // 测试带有 'v' 前缀的版本号 s.True(VersionCompare("v1.0.0", "1.0.0", "==")) s.True(VersionCompare("1.0.0", "v1.0.0", "==")) s.True(VersionCompare("v1.0.0", "v1.0.0", "==")) } +func (s *HelperTestSuite) TestGenerateVersions() { + versions, err := GenerateVersions("1.0.0", "1.0.3") + s.NoError(err) + s.Equal([]string{"1.0.1", "1.0.2", "1.0.3"}, versions) + + versions, err = GenerateVersions("v1.0.0", "v1.0.3") + s.NoError(err) + s.Equal([]string{"1.0.1", "1.0.2", "1.0.3"}, versions) + + versions, err = GenerateVersions("1.0.0", "1.0.0") + s.NoError(err) + s.Equal([]string(nil), versions) + + versions, err = GenerateVersions("1.0.0", "1.1.1") + s.NoError(err) + s.Equal([]string{ + "1.0.1", "1.0.2", "1.0.3", "1.0.4", "1.0.5", "1.0.6", "1.0.7", "1.0.8", "1.0.9", "1.0.10", + "1.0.11", "1.0.12", "1.0.13", "1.0.14", "1.0.15", "1.0.16", "1.0.17", "1.0.18", "1.0.19", "1.0.20", + "1.0.21", "1.0.22", "1.0.23", "1.0.24", "1.0.25", "1.0.26", "1.0.27", "1.0.28", "1.0.29", "1.0.30", + "1.0.31", "1.0.32", "1.0.33", "1.0.34", "1.0.35", "1.0.36", "1.0.37", "1.0.38", "1.0.39", "1.0.40", + "1.0.41", "1.0.42", "1.0.43", "1.0.44", "1.0.45", "1.0.46", "1.0.47", "1.0.48", "1.0.49", "1.0.50", + "1.0.51", "1.0.52", "1.0.53", "1.0.54", "1.0.55", "1.0.56", "1.0.57", "1.0.58", "1.0.59", "1.0.60", + "1.0.61", "1.0.62", "1.0.63", "1.0.64", "1.0.65", "1.0.66", "1.0.67", "1.0.68", "1.0.69", "1.0.70", + "1.0.71", "1.0.72", "1.0.73", "1.0.74", "1.0.75", "1.0.76", "1.0.77", "1.0.78", "1.0.79", "1.0.80", + "1.0.81", "1.0.82", "1.0.83", "1.0.84", "1.0.85", "1.0.86", "1.0.87", "1.0.88", "1.0.89", "1.0.90", + "1.0.91", "1.0.92", "1.0.93", "1.0.94", "1.0.95", "1.0.96", "1.0.97", "1.0.98", "1.0.99", "1.1.0", + "1.1.1", + }, versions) + + versions, err = GenerateVersions("1..0", "1.0.1") + s.Error(err) + s.Nil(versions) + + versions, err = GenerateVersions("1.0.0", "1..1") + s.Error(err) + s.Nil(versions) +} + func (s *HelperTestSuite) TestGetLatestPanelVersion() { version, err := GetLatestPanelVersion() s.NotEmpty(version)