package cmd import ( "net" "os" "path/filepath" "sylixos-uploader/common" "sylixos-uploader/detector" "sylixos-uploader/log" "sylixos-uploader/parser" "sylixos-uploader/pusher" "github.com/spf13/cobra" ) var uplaodCmd = &cobra.Command{ Use: "upload", Short: "upload SylixOS project", Long: `upload SylixOS project to device`, Run: func(cmd *cobra.Command, args []string) { if ProjectPath == "" { ProjectPath = "." } if UploadMethod != "ftp" { log.DefaultLogger(log.LogLevelError, "Only support upload ftp now.") return } prj := detector.NewSylixOSPrj(ProjectPath) if !prj.IsSylixOSPrj() { log.DefaultLogger(log.LogLevelError, "%s is Not a SylixOS project!", ProjectPath) return } if !prj.HasUploadYml { generateYamlFromRealEvo(ProjectPath, BasePrjPath, Device) } uploader := new(parser.UploadSetting) err := uploader.LoadConfig(filepath.Join(ProjectPath, common.YamlFile)) if err != nil { log.DefaultLogger(log.LogLevelError, "Error load %s: %v", filepath.Join(ProjectPath, common.YamlFile), err) return } remoteIP := net.ParseIP(uploader.RemoteSettings.IP) if remoteIP != nil { log.DefaultLogger(log.LogLevelInfo, "Upload Device IP: %s", uploader.RemoteSettings.IP) } else { log.DefaultLogger(log.LogLevelWarn, "No Valid Device IP in YML, please set Device IP by --device") return } if UploadMethod == "ftp" { p := pusher.NewFtpPusher(uploader.RemoteSettings.IP) err := p.Login(common.SylixOSUser, common.SylixOSPassword) if err != nil { log.DefaultLogger(log.LogLevelError, "Error login to %s: %v", uploader.RemoteSettings.IP, err) return } else { 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 { log.DefaultLogger(log.LogLevelError, "Error getting absolute path for %s: %v", UploadFile.LocalPath, err) return } err = p.Push(absLocalFilePath, UploadFile.RemotePath, log.DefaultLogger, log.DefaultClearLinesUp) if err != nil { log.DefaultLogger(log.LogLevelError, "Error uploading %s to %s: %v", UploadFile.LocalPath, UploadFile.RemotePath, err) return } else { info, _ := os.Stat(absLocalFilePath) if info.IsDir() { // 统计文件和子文件夹数量 fileCount, dirCount := countFilesAndDirs(absLocalFilePath) log.DefaultLogger(log.LogLevelInfo, "Upload Dir Success: %s, Files: %d, Subdirectories: %d", UploadFile.RemotePath, fileCount, dirCount) } else { log.DefaultLogger(log.LogLevelInfo, "Upload File Success: %s", UploadFile.RemotePath) } } } } }, } // countFilesAndDirs 递归统计文件和子文件夹数量 func countFilesAndDirs(dirPath string) (int, int) { var fileCount, dirCount int err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { if err != nil { // 忽略单个文件/文件夹的错误 log.DefaultLogger(log.LogLevelWarn, "Error accessing %s: %v", path, err) return nil } if info.IsDir() { dirCount++ } else { fileCount++ } return nil }) if err != nil { log.DefaultLogger(log.LogLevelError, "Error walking the directory %s: %v", dirPath, err) } // 返回文件数和子文件夹数 return fileCount, dirCount - 1 // 减去根目录本身 } func init() { RootCmd.AddCommand(uplaodCmd) // Adding flags with long names uplaodCmd.Flags().StringVar(&ProjectPath, "path", "", "Project path") uplaodCmd.Flags().StringVar(&BasePrjPath, "base", "", "Base project path") uplaodCmd.Flags().StringVar(&Device, "device", "", "Device") uplaodCmd.Flags().StringVar(&UploadMethod, "method", "ftp", "Upload method now only support ftp") }