diff --git a/cmd/logs.go b/cmd/logs.go index f448401..f979aad 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -1,10 +1,14 @@ package cmd import ( + "bufio" "fmt" + "os" + "strings" "rioctl/internal/transfer" "rioctl/internal/ui" + "rioctl/internal/utils" "github.com/spf13/cobra" ) @@ -13,7 +17,7 @@ var logsCmd = &cobra.Command{ Use: "logs", Short: "Log operations", } - +var defaultSource = "/media/sda1" var logsPullCmd = &cobra.Command{ Use: "pull [files...]", Short: "Pull logs from RoboRIO", @@ -28,19 +32,23 @@ var logsPullCmd = &cobra.Command{ source, _ := cmd.Flags().GetString("source") // If no dir provided → prompt if source == "" { - input, err := ui.RunTextInput("/media/sda1") + input, err := ui.RunTextInput(defaultSource) if err != nil { return err } if input == "" { - source = "/media/sda1" + source = defaultSource } else { source = input } } dest, _ := cmd.Flags().GetString("dest") + eventCode, _ := cmd.Flags().GetString("event") + practice, _ := cmd.Flags().GetBool("practice") + qual, _ := cmd.Flags().GetBool("qual") + elim, _ := cmd.Flags().GetBool("elim") var files []string @@ -49,19 +57,54 @@ var logsPullCmd = &cobra.Command{ files = args } else { fmt.Println("Fetching file list...") - allFiles, err := client.ListFiles(source) if err != nil { return err } + if eventCode != "" || practice || qual || elim { + allFiles, err := client.ListFiles(source) + if err != nil { + return err + } + var totalSize int64 + for _, file := range allFiles { + if eventCode != "" && file.Event != eventCode { + continue + } + if !practice && !elim && !qual { + files = append(files, file.Name) + totalSize += file.Size + } else if practice && file.MatchType == "p" { + files = append(files, file.Name) + totalSize += file.Size + } else if qual && file.MatchType == "q" { + files = append(files, file.Name) + totalSize += file.Size + } else if elim && file.MatchType == "e" { + files = append(files, file.Name) + totalSize += file.Size + } + } + + fmt.Printf("⚠️ This will pull %d files (%s). Continue? (yes/no): ", len(files), utils.Humanize(totalSize)) + + reader := bufio.NewReader(os.Stdin) + text, _ := reader.ReadString('\n') + + if strings.ToLower(text) != "yes\n" { + fmt.Println("Aborted.") + return nil + } - // Launch TUI selector - selected, err := ui.RunFilePicker(allFiles) - if err != nil { - return err - } + } else { + // Launch TUI selector + selected, err := ui.RunFilePicker(allFiles) + if err != nil { + return err + } - files = selected + files = selected + } } fmt.Println("Downloading selected files...") @@ -70,8 +113,12 @@ var logsPullCmd = &cobra.Command{ } func init() { - logsPullCmd.Flags().String("source", "/media/sda1", "Source directory") + logsPullCmd.Flags().String("source", "", "Source directory") logsPullCmd.Flags().String("dest", "./logs", "Destination directory") + logsPullCmd.Flags().String("event", "", "Event Code to download Event only logs") + logsPullCmd.Flags().Bool("practice", false, "Pull Practice Match Logs") + logsPullCmd.Flags().Bool("qual", false, "Pull Qual Match Logs") + logsPullCmd.Flags().Bool("elim", false, "Pull Elim Match Logs") logsCmd.AddCommand(logsPullCmd) rootCmd.AddCommand(logsCmd) diff --git a/cmd/ssh.go b/cmd/ssh.go index b6ef0a0..69c5995 100644 --- a/cmd/ssh.go +++ b/cmd/ssh.go @@ -20,9 +20,18 @@ func getSSHClient(cmd *cobra.Command) (*sshclient.Client, error) { return nil, fmt.Errorf("team number is required") } - host := teamToIP(team) - - fmt.Printf("Connecting to %s as %s...\n", host, user) - - return sshclient.New(host, user, pass) + hostOptions := []string{ + teamToIP(team), + fmt.Sprintf("roboRIO-%d-FRC.local", team), + "172.22.11.2", + } + for _, host := range hostOptions { + fmt.Printf("Connecting to %s as %s...\n", host, user) + client, err := sshclient.New(host, user, pass) + if err == nil { + return client, nil + } + fmt.Printf("Connection to %s failed\n", host) + } + return nil, fmt.Errorf("Could not connect to RoboRio on any IP/Hostname") } diff --git a/cmd/test copy.go b/cmd/test copy.go deleted file mode 100644 index 54a02bb..0000000 --- a/cmd/test copy.go +++ /dev/null @@ -1,18 +0,0 @@ -package cmd - -// var test2CMD = &cobra.Command{ -// Use: "test2", -// Short: "test operations", -// Args: cobra.ArbitraryArgs, -// RunE: func(cmd *cobra.Command, args []string) error { - -// allFiles := []string{"asdf", "asdf"} -// _, err := ui.RunFilePicker(allFiles) -// return err -// }, -// } - -// func init() { - -// rootCmd.AddCommand(test2CMD) -// } diff --git a/cmd/test.go b/cmd/test.go deleted file mode 100644 index 82bb440..0000000 --- a/cmd/test.go +++ /dev/null @@ -1,42 +0,0 @@ -package cmd - -import ( - "os" - "rioctl/internal/ui" - - "github.com/spf13/cobra" - - "charm.land/lipgloss/v2" -) - -const ( - padding = 2 - maxWidth = 80 -) - -var helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#626262")).Render - -var testCMD = &cobra.Command{ - Use: "test", - Short: "test operations", - Args: cobra.ArbitraryArgs, - RunE: func(cmd *cobra.Command, args []string) error { - progressChan := make(chan int) - files := []string{"asdf", "qwer", "1234"} - // for i, _ := range files { - // // fmt.Printf("Downloading File %s", file) - // time.Sleep(4 * time.Second) // Pauses for 1 second - // progressChan <- i + 1 - // } - ui.RunProgress1(len(files), files) - - close(progressChan) - os.Exit(0) - return nil - }, -} - -func init() { - - rootCmd.AddCommand(testCMD) -} diff --git a/cmd/usb.go b/cmd/usb.go index bd5ae92..48489f1 100644 --- a/cmd/usb.go +++ b/cmd/usb.go @@ -79,20 +79,12 @@ var formatCmd = &cobra.Command{ } fmt.Println(out) - mountCmdStr := fmt.Sprintf("mount %s /media/sda1", device) - out, err = client.Run(mountCmdStr) + out, err = client.Run("reboot") if err != nil { return err } fmt.Println(out) - out, err = client.Run("RESTART=yes /usr/local/frc/bin/frcKillRobot.sh") - if err != nil { - return err - } - fmt.Println(out) - - fmt.Println(out) return nil }, } diff --git a/internal/sshclient/client.go b/internal/sshclient/client.go index bcdc974..06edac9 100644 --- a/internal/sshclient/client.go +++ b/internal/sshclient/client.go @@ -2,6 +2,7 @@ package sshclient import ( "fmt" + "regexp" "rioctl/internal/utils" "slices" "strconv" @@ -10,6 +11,8 @@ import ( "github.com/melbahja/goph" ) +var fileRE = regexp.MustCompile(`^akit_.*_(\w+)_([peq])\d+\.wpilog$`) + type Client struct { client *goph.Client } @@ -39,7 +42,7 @@ func (c *Client) Close() error { } func (c *Client) ListFiles(dir string) ([]utils.File, error) { - out, err := c.Run(fmt.Sprintf("ls -lh %s | grep .wpilog | awk '{ print $5\",\"$9 }'", dir)) + out, err := c.Run(fmt.Sprintf("ls -l %s | grep .wpilog | awk '{ print $5\",\"$9 }'", dir)) if err != nil { return nil, err } @@ -51,8 +54,22 @@ func (c *Client) ListFiles(dir string) ([]utils.File, error) { if l == "" { continue } + eventCode := "" + matchType := "" stringArr := strings.Split(l, ",") - files = append(files, utils.File{Name: stringArr[1], Size: stringArr[0]}) + name := stringArr[1] + + size, err := strconv.ParseInt(strings.TrimSpace(stringArr[0]), 10, 64) + if err != nil { + continue + } + if fileRE.MatchString(name) { + matches := fileRE.FindStringSubmatch(name) + eventCode = matches[1] + matchType = matches[2] + } + + files = append(files, utils.File{Name: name, Size: size, Event: eventCode, MatchType: matchType}) } slices.Reverse(files) return files, nil diff --git a/internal/ui/filepicker.go b/internal/ui/filepicker.go index adab305..936adb4 100644 --- a/internal/ui/filepicker.go +++ b/internal/ui/filepicker.go @@ -103,7 +103,7 @@ func NewFilePicker(files []utils.File) model { choices := make([]*item, len(files)) for i, f := range files { - it := &item{title: f.Name, size: f.Size} + it := &item{title: f.Name, size: f.HumanizedSize()} items[i] = it choices[i] = it } diff --git a/internal/ui/progress.go b/internal/ui/progress.go index 7e86df6..f79d6ea 100644 --- a/internal/ui/progress.go +++ b/internal/ui/progress.go @@ -64,8 +64,8 @@ func (m progressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case utils.FileUpload: m.currentFileBytes = msg.Current - m.totalFileBytes = msg.Size - m.currentFile = msg.Name + m.totalFileBytes = msg.File.Size + m.currentFile = msg.File.Name if m.currentFileBytes >= m.totalFileBytes { m.completedFiles = append(m.completedFiles, m.currentFile) } @@ -91,7 +91,7 @@ func (m progressModel) View() tea.View { return tea.NewView("\n\n" + a + fmt.Sprintf("Downloading %s (%d/%d)", m.currentFile, m.finished+1, m.total) + "\n\n" + m.progress.ViewAs(current) + "\n\n" + - pad + helpStyle(fmt.Sprintf("%s / %s", humanize(m.currentFileBytes), humanize((m.totalFileBytes))))) + pad + helpStyle(fmt.Sprintf("%s / %s", utils.Humanize(m.currentFileBytes), utils.Humanize((m.totalFileBytes))))) } func RunProgress(total int, current <-chan utils.FileUpload, finished <-chan int) { @@ -111,20 +111,3 @@ func RunProgress(total int, current <-chan utils.FileUpload, finished <-chan int p.Run() } - -func RunProgress1(total int, stuff []string) { - m := NewProgress(total) - p := tea.NewProgram(m) - - go func() { - for u := range stuff { - p.Send(u) - } - }() - - p.Run() -} - -func humanize(b int64) string { - return fmt.Sprintf("%.2f MB", float64(b)/1024/1024) -} diff --git a/internal/utils/file.go b/internal/utils/file.go index 6a3b133..62f0eb4 100644 --- a/internal/utils/file.go +++ b/internal/utils/file.go @@ -1,9 +1,12 @@ package utils +import "fmt" + type FileUpload struct { - Size int64 + File File + // Size int64 Current int64 - Name string + // Name string } func (m FileUpload) UpdateCurrent(current int64) FileUpload { @@ -13,13 +16,25 @@ func (m FileUpload) UpdateCurrent(current int64) FileUpload { func NewFile(size int64, current int64, name string) FileUpload { return FileUpload{ - Name: name, + File: File{ + Name: name, + Size: size, + }, Current: current, - Size: size, } } type File struct { - Size string - Name string + Size int64 + Name string + Event string + MatchType string +} + +func (f File) HumanizedSize() string { + return Humanize(f.Size) +} + +func Humanize(b int64) string { + return fmt.Sprintf("%.2f MB", float64(b)/1024/1024) }