better print style.

better print style.
This commit is contained in:
chengsiyuan 2024-11-19 00:31:06 +08:00
parent 1945aef5f0
commit 11613f5818
6 changed files with 199 additions and 88 deletions

View File

@ -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)

View File

@ -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)
}
}
}
}

View File

@ -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)
},
}

79
log/log.go Normal file
View File

@ -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")
}
}

View File

@ -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
}

View File

@ -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)
}