From 11613f5818a6d059cade6ead63cc07eb7919b6c1 Mon Sep 17 00:00:00 2001 From: chengsiyuan Date: Tue, 19 Nov 2024 00:31:06 +0800 Subject: [PATCH] better print style. better print style. --- cmd/gen_yaml.go | 86 +++++++++++++++++++++------------------ cmd/upload.go | 53 +++++++++--------------- cmd/version.go | 4 +- log/log.go | 79 +++++++++++++++++++++++++++++++++++ pusher/ftp_pusher.go | 62 +++++++++++++++++++++++----- pusher/ftp_pusher_test.go | 3 +- 6 files changed, 199 insertions(+), 88 deletions(-) create mode 100644 log/log.go diff --git a/cmd/gen_yaml.go b/cmd/gen_yaml.go index deee013..a389a8a 100644 --- a/cmd/gen_yaml.go +++ b/cmd/gen_yaml.go @@ -1,11 +1,12 @@ package cmd import ( - "fmt" + "errors" "net" "path/filepath" "sylixos-uploader/common" "sylixos-uploader/detector" + "sylixos-uploader/log" "sylixos-uploader/parser" "github.com/spf13/cobra" @@ -16,48 +17,53 @@ var genYamlCmd = &cobra.Command{ Short: "generate upload yaml file from real evo project", Long: `generate upload yaml file from real evo project`, Run: func(cmd *cobra.Command, args []string) { - u := new(parser.UploadSetting) - - if ProjectPath == "" { - ProjectPath = "." - } - - prj := detector.NewSylixOSPrj(ProjectPath) - - if !prj.IsSylixOSPrj() { - fmt.Println("Not a SylixOS project!") - return - } - - if BasePrjPath != "" { - if !detector.NewSylixOSPrj(BasePrjPath).IsSylixOSPrj() { - fmt.Println("Base is set but the path is not a SylixOS project!, ignore it.") - BasePrjPath = "" - } - } - - u.GenerateFromRealEvo(ProjectPath, BasePrjPath) - deviceIP := net.ParseIP(Device) - - deviceXmlIP := net.ParseIP(u.RemoteSettings.IP) - - if deviceIP != nil { - fmt.Println("Override Device IP:", Device) - u.RemoteSettings.IP = Device - } else if deviceXmlIP != nil { - fmt.Println("Set Device IP as the IP in the XML:", u.RemoteSettings.IP) - } else { - fmt.Println("No Valid Device IP in XML, please set Device IP by --device") - return - } - - u.ClearYaml() - u.SaveYaml() - - fmt.Println("Done generate:", filepath.Join(u.BaseSettings.ProjectPath, common.YamlFile)) + generateYamlFromRealEvo(ProjectPath, BasePrjPath, Device) }, } +func generateYamlFromRealEvo(projectPath, basePath, device string) error { + u := new(parser.UploadSetting) + + if projectPath == "" { + projectPath = "." + } + + prj := detector.NewSylixOSPrj(projectPath) + + if !prj.IsSylixOSPrj() { + log.DefaultLogger(log.LogLevelError, "%s is Not a SylixOS project!", projectPath) + return errors.New("not a SylixOS project") + } + + if basePath != "" { + if !detector.NewSylixOSPrj(basePath).IsSylixOSPrj() { + log.DefaultLogger(log.LogLevelWarn, "Base is set but the path is not a SylixOS project!, ignore it.") + basePath = "" + } + } + + u.GenerateFromRealEvo(projectPath, basePath) + deviceIP := net.ParseIP(device) + + deviceXmlIP := net.ParseIP(u.RemoteSettings.IP) + + if deviceIP != nil { + log.DefaultLogger(log.LogLevelInfo, "Override Device IP as %s", deviceIP.String()) + u.RemoteSettings.IP = device + } else if deviceXmlIP != nil { + log.DefaultLogger(log.LogLevelInfo, "Use Device IP in XML as %s", deviceXmlIP.String()) + } else { + log.DefaultLogger(log.LogLevelError, "No Valid Device IP in XML, please set Device IP by --device") + return errors.New("no valid device ip") + } + + u.ClearYaml() + u.SaveYaml() + + log.DefaultLogger(log.LogLevelInfo, "Generate Success: %s", filepath.Join(u.BaseSettings.ProjectPath, common.YamlFile)) + return nil +} + func init() { RootCmd.AddCommand(genYamlCmd) diff --git a/cmd/upload.go b/cmd/upload.go index 49d4128..c232fad 100644 --- a/cmd/upload.go +++ b/cmd/upload.go @@ -1,11 +1,12 @@ package cmd import ( - "fmt" "net" + "os" "path/filepath" "sylixos-uploader/common" "sylixos-uploader/detector" + "sylixos-uploader/log" "sylixos-uploader/parser" "sylixos-uploader/pusher" @@ -17,60 +18,39 @@ var uplaodCmd = &cobra.Command{ Short: "upload SylixOS project", Long: `upload SylixOS project to device`, Run: func(cmd *cobra.Command, args []string) { - u := new(parser.UploadSetting) - if ProjectPath == "" { ProjectPath = "." } if UploadMethod != "ftp" { - fmt.Println("Only support upload ftp now.") + log.DefaultLogger(log.LogLevelError, "Only support upload ftp now.") return } prj := detector.NewSylixOSPrj(ProjectPath) if !prj.IsSylixOSPrj() { - fmt.Println("Not a SylixOS project!") + log.DefaultLogger(log.LogLevelError, "%s is Not a SylixOS project!", ProjectPath) return } if !prj.HasUploadYml { - fmt.Println("This is a SylixOS project without yml, generate one.") - - if BasePrjPath != "" { - if !detector.NewSylixOSPrj(BasePrjPath).IsSylixOSPrj() { - fmt.Println("Base is set but the path is not a SylixOS project!, ignore it.") - BasePrjPath = "" - } - } - - u.GenerateFromRealEvo(ProjectPath, BasePrjPath) - deviceIP := net.ParseIP(Device) - - if deviceIP != nil { - u.RemoteSettings.IP = Device - } - - u.ClearYaml() - u.SaveYaml() - - fmt.Println("Done generate:", filepath.Join(u.BaseSettings.ProjectPath, common.YamlFile)) + generateYamlFromRealEvo(ProjectPath, BasePrjPath, Device) } uploader := new(parser.UploadSetting) err := uploader.LoadConfig(filepath.Join(ProjectPath, common.YamlFile)) if err != nil { - fmt.Println(err) + log.DefaultLogger(log.LogLevelError, "Error load %s: %v", filepath.Join(ProjectPath, common.YamlFile), err) return } remoteIP := net.ParseIP(uploader.RemoteSettings.IP) if remoteIP != nil { - fmt.Println("Upload Device IP:", uploader.RemoteSettings.IP) + log.DefaultLogger(log.LogLevelInfo, "Upload Device IP: %s", uploader.RemoteSettings.IP) } else { - fmt.Println("No Valid Device IP in YML, please set Device IP by --device") + log.DefaultLogger(log.LogLevelWarn, "No Valid Device IP in YML, please set Device IP by --device") return } @@ -78,26 +58,31 @@ var uplaodCmd = &cobra.Command{ p := pusher.NewFtpPusher(uploader.RemoteSettings.IP) err := p.Login(common.SylixOSUser, common.SylixOSPassword) if err != nil { - fmt.Println(err) + log.DefaultLogger(log.LogLevelError, "Error login to %s: %v", uploader.RemoteSettings.IP, err) return } else { - fmt.Println("Login Success:", uploader.RemoteSettings.IP) + log.DefaultLogger(log.LogLevelInfo, "Login Success: %s", uploader.RemoteSettings.IP) } defer p.Logout() for _, UploadFile := range uploader.UploadPair { absLocalFilePath, err := uploader.GetAbsLocalPath(UploadFile.LocalPath, "") if err != nil { - fmt.Println(err) + log.DefaultLogger(log.LogLevelError, "Error getting absolute path for %s: %v", UploadFile.LocalPath, err) return } - err = p.Push(absLocalFilePath, UploadFile.RemotePath) + err = p.Push(absLocalFilePath, UploadFile.RemotePath, log.DefaultLogger, log.DefaultClearLinesUp) if err != nil { - fmt.Println(err) + log.DefaultLogger(log.LogLevelError, "Error uploading %s to %s: %v", UploadFile.LocalPath, UploadFile.RemotePath, err) return } else { - fmt.Println("Upload Success:", UploadFile.RemotePath) + info, _ := os.Stat(absLocalFilePath) + if info.IsDir() { + log.DefaultLogger(log.LogLevelInfo, "Upload Dir Success: %s", UploadFile.RemotePath) + } else { + log.DefaultLogger(log.LogLevelInfo, "Upload File Success: %s", UploadFile.RemotePath) + } } } } diff --git a/cmd/version.go b/cmd/version.go index f396f13..25ed630 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,8 +1,8 @@ package cmd import ( - "fmt" "sylixos-uploader/common" + "sylixos-uploader/log" "github.com/spf13/cobra" ) @@ -12,7 +12,7 @@ var versionCmd = &cobra.Command{ Short: "show sylixos-uploader version", Long: `show sylixos-uploader version`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Version:", common.Version) + log.DefaultLogger(log.LogLevelInfo, "Version: %s", common.Version) }, } diff --git a/log/log.go b/log/log.go new file mode 100644 index 0000000..6a053db --- /dev/null +++ b/log/log.go @@ -0,0 +1,79 @@ +package log + +import ( + "context" + "fmt" + "log/slog" +) + +type LogLevel int + +const ( + LogLevelDebug LogLevel = iota + LogLevelInfo + LogLevelWarn + LogLevelError +) + +func DefaultLogger(level LogLevel, format string, args ...interface{}) { + // Print log with level prefix + switch level { + case LogLevelDebug: + slog.Debug(fmt.Sprintf(format, args...)) + return + case LogLevelInfo: + slog.Info(fmt.Sprintf(format, args...)) + return + case LogLevelWarn: + slog.Warn(fmt.Sprintf(format, args...)) + return + case LogLevelError: + slog.Error(fmt.Sprintf(format, args...)) + return + } +} + +// DefaultClearLinesUp clears the specified number of lines above the current cursor position. +func DefaultClearLinesUp(level LogLevel, lines int) { + switch level { + case LogLevelDebug: + if slog.Default().Enabled(context.Background(), slog.LevelDebug) { + clearLinesUp(lines) + } + return + case LogLevelInfo: + if slog.Default().Enabled(context.Background(), slog.LevelInfo) { + clearLinesUp(lines) + } + return + case LogLevelWarn: + if slog.Default().Enabled(context.Background(), slog.LevelWarn) { + clearLinesUp(lines) + } + return + case LogLevelError: + if slog.Default().Enabled(context.Background(), slog.LevelError) { + clearLinesUp(lines) + } + } +} + +func SetLogLevel(level LogLevel) { + switch level { + case LogLevelDebug: + slog.SetLogLoggerLevel(slog.LevelDebug) + case LogLevelInfo: + slog.SetLogLoggerLevel(slog.LevelInfo) + case LogLevelWarn: + slog.SetLogLoggerLevel(slog.LevelWarn) + case LogLevelError: + slog.SetLogLoggerLevel(slog.LevelError) + } +} + +func clearLinesUp(lines int) { + for i := 0; i < lines; i++ { + // Move cursor up one line and clear the line + fmt.Print("\033[1A\033[2K") + } +} diff --git a/pusher/ftp_pusher.go b/pusher/ftp_pusher.go index 7514566..ac5d4e1 100644 --- a/pusher/ftp_pusher.go +++ b/pusher/ftp_pusher.go @@ -3,10 +3,10 @@ package pusher import ( "debug/elf" "errors" - "fmt" "os" "path/filepath" "strings" + "sylixos-uploader/log" "sync" "github.com/jlaffaye/ftp" @@ -77,7 +77,12 @@ func (f *FtpSylixOSPusher) Logout() { } // Push uploads a file or directory to the remote FTP server -func (f *FtpSylixOSPusher) Push(src, dst string) error { +func (f *FtpSylixOSPusher) Push(src, dst string, + logFn func(level log.LogLevel, + format string, + args ...interface{}), + logClear func(level log.LogLevel, + lines int)) error { f.m.Lock() defer f.m.Unlock() @@ -97,37 +102,59 @@ func (f *FtpSylixOSPusher) Push(src, dst string) error { if info.IsDir() { // Push directory - return f.pushDir(src, dst) + return f.pushDir(src, dst, logFn, logClear) } // Push file - fmt.Println("Pushing", src, "to", dst) - return f.pushFile(src, dst) + return f.pushFile(src, dst, logFn, logClear) } -// pushDir recursively uploads a directory and its contents -func (f *FtpSylixOSPusher) pushDir(src, dst string) error { +func (f *FtpSylixOSPusher) pushDir(src, dst string, + logFn func(level log.LogLevel, + format string, + args ...interface{}), + logClear func(level log.LogLevel, + lines int)) error { // Walk through the local directory return filepath.Walk(src, func(path string, info os.FileInfo, err error) error { if err != nil { + if logFn != nil { + logFn(log.LogLevelError, "Error accessing path %s: %v", path, err) + } return err } // Create relative path for remote destination relPath, err := filepath.Rel(src, path) if err != nil { + if logFn != nil { + logFn(log.LogLevelError, "Error creating relative path: %v", err) + } return err } remotePath := filepath.Join(dst, relPath) if info.IsDir() { // Create remote directory - return f.ensureRemoteDir(remotePath) + if logFn != nil { + logFn(log.LogLevelInfo, "Creating remote directory: %s", remotePath) + } + err = f.ensureRemoteDir(remotePath) + if err != nil { + if logFn != nil { + logFn(log.LogLevelError, "Error creating remote directory: %v", err) + } + return err + } else { + if logClear != nil { + logClear(log.LogLevelInfo, 1) + } + } + return nil } // Push file - fmt.Println("Pushing", path, "to", remotePath) - return f.pushFile(path, remotePath) + return f.pushFile(path, remotePath, logFn, logClear) }) } @@ -136,7 +163,16 @@ func (f *FtpSylixOSPusher) pushDir(src, dst string) error { // // The caller is responsible for ensuring that the file is closed, which is // done automatically via the defer statement in this function. -func (f *FtpSylixOSPusher) pushFile(src, dst string) error { +func (f *FtpSylixOSPusher) pushFile(src, dst string, + logFn func(level log.LogLevel, + format string, + args ...interface{}), + logClear func(level log.LogLevel, + lines int)) error { + if logFn != nil { + logFn(log.LogLevelInfo, "Pushing \r\n\tfrom %s \r\n\tto %s", src, dst) + } + // Open the file for reading file, err := os.Open(src) if err != nil { @@ -162,6 +198,10 @@ func (f *FtpSylixOSPusher) pushFile(src, dst string) error { } } + if logClear != nil { + logClear(log.LogLevelInfo, 3) + } + return nil } diff --git a/pusher/ftp_pusher_test.go b/pusher/ftp_pusher_test.go index 4057415..1d5c138 100644 --- a/pusher/ftp_pusher_test.go +++ b/pusher/ftp_pusher_test.go @@ -2,6 +2,7 @@ package pusher import ( "sylixos-uploader/common" + "sylixos-uploader/log" "testing" ) @@ -13,7 +14,7 @@ func TestPush(t *testing.T) { } defer p.Logout() - err := p.Push("./", "/apps/ftp_pusher_test") + err := p.Push("./", "/apps/ftp_pusher_test", log.DefaultLogger, log.DefaultClearLinesUp) if err != nil { t.Error(err) }