mirror of
https://github.com/acedanger/shell.git
synced 2025-12-05 22:50:18 -08:00
refactor: Clean up whitespace and improve formatting in backup update logic
This commit is contained in:
124
tui/main.go
124
tui/main.go
@@ -479,10 +479,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if m.backupStatus[msg.service] == nil {
|
||||
m.backupStatus[msg.service] = &BackupStatus{}
|
||||
}
|
||||
|
||||
|
||||
// Create context for this backup
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
||||
m.backupStatus[msg.service].Service = msg.service
|
||||
m.backupStatus[msg.service].Status = "running"
|
||||
m.backupStatus[msg.service].LastRun = time.Now()
|
||||
@@ -490,9 +490,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.backupStatus[msg.service].Progress = 0
|
||||
m.backupStatus[msg.service].Context = ctx
|
||||
m.backupStatus[msg.service].Cancel = cancel
|
||||
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("🚀 Starting backup for %s...\n\nInitializing backup process...\nPress 'x' to cancel if needed.", msg.service))
|
||||
|
||||
|
||||
// Start progress ticker for time-based progress estimation
|
||||
cmds = append(cmds, m.startProgressTicker(msg.service))
|
||||
|
||||
@@ -547,18 +547,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.backupStatus[msg.service].EndTime = time.Now()
|
||||
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
||||
m.backupStatus[msg.service].Progress = 100
|
||||
|
||||
|
||||
// Clean up context
|
||||
if m.backupStatus[msg.service].Cancel != nil {
|
||||
m.backupStatus[msg.service].Cancel()
|
||||
}
|
||||
}
|
||||
delete(m.runningBackups, msg.service)
|
||||
|
||||
|
||||
// Parse output for additional info
|
||||
lines := strings.Split(msg.output, "\n")
|
||||
var summary strings.Builder
|
||||
|
||||
|
||||
// Extract meaningful summary information
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "Total files:") ||
|
||||
@@ -569,18 +569,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
summary.WriteString("📊 " + strings.TrimSpace(line) + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
summaryText := summary.String()
|
||||
if summaryText == "" {
|
||||
summaryText = "📊 Backup completed successfully"
|
||||
}
|
||||
|
||||
|
||||
duration := ""
|
||||
if m.backupStatus[msg.service] != nil {
|
||||
duration = m.backupStatus[msg.service].Duration
|
||||
}
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("✅ Backup completed successfully for %s!\n\nDuration: %s\n\n%s\n\n📋 Full Output:\n%s",
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("✅ Backup completed successfully for %s!\n\nDuration: %s\n\n%s\n\n📋 Full Output:\n%s",
|
||||
msg.service, duration, summaryText, msg.output))
|
||||
|
||||
case backupErrorMsg:
|
||||
@@ -589,19 +589,19 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
m.backupStatus[msg.service].Error = msg.error
|
||||
m.backupStatus[msg.service].EndTime = time.Now()
|
||||
m.backupStatus[msg.service].Duration = m.backupStatus[msg.service].EndTime.Sub(m.backupStatus[msg.service].StartTime).String()
|
||||
|
||||
|
||||
// Clean up context
|
||||
if m.backupStatus[msg.service].Cancel != nil {
|
||||
m.backupStatus[msg.service].Cancel()
|
||||
}
|
||||
}
|
||||
delete(m.runningBackups, msg.service)
|
||||
|
||||
|
||||
duration := ""
|
||||
if m.backupStatus[msg.service] != nil {
|
||||
duration = m.backupStatus[msg.service].Duration
|
||||
}
|
||||
|
||||
|
||||
// Provide helpful error analysis
|
||||
var errorAnalysis string
|
||||
if strings.Contains(msg.error, "permission denied") {
|
||||
@@ -613,8 +613,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
} else if strings.Contains(msg.error, "space") {
|
||||
errorAnalysis = "\n💡 This might be a disk space issue. Check available storage."
|
||||
}
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("❌ Backup failed for %s!\n\nDuration: %s%s\n\n🚨 Error Details:\n%s",
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("❌ Backup failed for %s!\n\nDuration: %s%s\n\n🚨 Error Details:\n%s",
|
||||
msg.service, duration, errorAnalysis, msg.error))
|
||||
|
||||
case spinner.TickMsg:
|
||||
@@ -663,11 +663,11 @@ func (m *Model) updateViewportForRunningService(service string, outputForDisplay
|
||||
totalEstimatedDuration := time.Duration(totalEstimatedRaw)
|
||||
remainingDuration := totalEstimatedDuration - elapsed
|
||||
if remainingDuration > 0 {
|
||||
etaStr = fmt.Sprintf("\\nETA: %s", remainingDuration.Round(time.Second))
|
||||
etaStr = fmt.Sprintf("\nETA: %s", remainingDuration.Round(time.Second))
|
||||
}
|
||||
}
|
||||
|
||||
m.viewport.SetContent(fmt.Sprintf("⏳ Backup in progress for %s...\\n\\n%s %d%%%%\\nElapsed: %s%s\\n\\n📋 Latest output:\\n%s\\n\\nPress 'x' to stop the backup.",
|
||||
m.viewport.SetContent(fmt.Sprintf("⏳ Backup in progress for %s...\n\n%s %d%%\nElapsed: %s%s\n\n📋 Latest output:\n%s\n\nPress 'x' to stop the backup.",
|
||||
service, progressBar, progress, elapsed.Round(time.Second), etaStr, outputForDisplay))
|
||||
}
|
||||
|
||||
@@ -702,7 +702,7 @@ func (m Model) View() string {
|
||||
if m.activePanel == 1 {
|
||||
viewportStyle = viewportStyle.BorderStyle(lipgloss.ThickBorder()).BorderForeground(lipgloss.Color("#7D56F4"))
|
||||
}
|
||||
|
||||
|
||||
// Add view indicator to viewport title
|
||||
viewportTitle := ""
|
||||
switch m.currentView {
|
||||
@@ -715,7 +715,7 @@ func (m Model) View() string {
|
||||
default:
|
||||
viewportTitle = "💻 Output"
|
||||
}
|
||||
|
||||
|
||||
// Layout based on active panel
|
||||
return lipgloss.JoinVertical(lipgloss.Left,
|
||||
titleStyle.Render("🔧 Media & Plex Backup Manager"),
|
||||
@@ -833,7 +833,7 @@ func (m *Model) showStatus() {
|
||||
for _, service := range services {
|
||||
status := m.backupStatus[service]
|
||||
content.WriteString(fmt.Sprintf("🔧 Service: %s\n", strings.ToUpper(service)))
|
||||
|
||||
|
||||
// Status with emoji
|
||||
statusIcon := "⭕"
|
||||
switch status.Status {
|
||||
@@ -847,34 +847,34 @@ func (m *Model) showStatus() {
|
||||
statusIcon = "🛑"
|
||||
}
|
||||
content.WriteString(fmt.Sprintf(" Status: %s %s\n", statusIcon, status.Status))
|
||||
|
||||
|
||||
if !status.LastRun.IsZero() {
|
||||
content.WriteString(fmt.Sprintf(" Last Run: %s\n", status.LastRun.Format("2006-01-02 15:04:05")))
|
||||
}
|
||||
|
||||
|
||||
if status.Duration != "" {
|
||||
content.WriteString(fmt.Sprintf(" Duration: %s\n", status.Duration))
|
||||
}
|
||||
|
||||
|
||||
if status.Progress > 0 && status.Status == "running" {
|
||||
content.WriteString(fmt.Sprintf(" Progress: %d%%\n", status.Progress))
|
||||
}
|
||||
|
||||
|
||||
if status.BackupSize != "" {
|
||||
content.WriteString(fmt.Sprintf(" Size: %s\n", status.BackupSize))
|
||||
}
|
||||
|
||||
|
||||
if status.FilesCount > 0 {
|
||||
content.WriteString(fmt.Sprintf(" Files: %d\n", status.FilesCount))
|
||||
}
|
||||
|
||||
|
||||
if status.Error != "" {
|
||||
content.WriteString(fmt.Sprintf(" Error: %s\n", status.Error[:min(100, len(status.Error))]))
|
||||
}
|
||||
|
||||
|
||||
content.WriteString("\n")
|
||||
}
|
||||
|
||||
|
||||
// Add summary
|
||||
running := 0
|
||||
success := 0
|
||||
@@ -889,7 +889,7 @@ func (m *Model) showStatus() {
|
||||
failed++
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
content.WriteString("📊 SUMMARY:\n")
|
||||
content.WriteString(fmt.Sprintf(" Running: %d | Success: %d | Failed: %d\n", running, success, failed))
|
||||
}
|
||||
@@ -916,7 +916,7 @@ func (m *Model) showConfig() {
|
||||
if len(item.args) > 0 {
|
||||
content.WriteString(fmt.Sprintf(" Args: %s\n", strings.Join(item.args, " ")))
|
||||
}
|
||||
|
||||
|
||||
// Check if script exists
|
||||
if _, err := os.Stat(item.script); os.IsNotExist(err) {
|
||||
content.WriteString(" ⚠️ Status: Script not found\n")
|
||||
@@ -950,10 +950,10 @@ func (m *Model) stopBackup(service string, process *RunningProcess) tea.Cmd {
|
||||
if process.Cancel != nil {
|
||||
process.Cancel()
|
||||
}
|
||||
|
||||
|
||||
// Give process time to shut down gracefully
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
|
||||
// Force kill if still running
|
||||
if process.Cmd != nil && process.Cmd.Process != nil {
|
||||
if process.Cmd.ProcessState == nil || !process.Cmd.ProcessState.Exited() {
|
||||
@@ -977,11 +977,11 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
// Create context for cancellation
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
|
||||
// Execute the backup script with context
|
||||
cmd := exec.CommandContext(ctx, item.script, item.args...)
|
||||
cmd.Dir = m.shellPath
|
||||
|
||||
|
||||
// Create pipes for stdout and stderr
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
@@ -990,7 +990,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
error: fmt.Sprintf("Failed to create stdout pipe: %s", err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stderr, err := cmd.StderrPipe()
|
||||
if err != nil {
|
||||
return backupErrorMsg{
|
||||
@@ -998,7 +998,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
error: fmt.Sprintf("Failed to create stderr pipe: %s", err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Start the command
|
||||
if err := cmd.Start(); err != nil {
|
||||
return backupErrorMsg{
|
||||
@@ -1006,14 +1006,14 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
error: fmt.Sprintf("Failed to start backup: %s", err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var outputBuilder strings.Builder
|
||||
var allOutput []string
|
||||
|
||||
|
||||
// Monitor stdout and stderr in goroutines
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
|
||||
|
||||
// Read stdout
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -1024,7 +1024,7 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
allOutput = append(allOutput, line)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
// Read stderr
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -1035,21 +1035,21 @@ func (m Model) runBackupCommand(item BackupItem) tea.Cmd {
|
||||
allOutput = append(allOutput, "[STDERR] "+line)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
// Wait for the command to complete
|
||||
err = cmd.Wait()
|
||||
|
||||
|
||||
// Wait for output readers to finish
|
||||
wg.Wait()
|
||||
|
||||
|
||||
finalOutput := outputBuilder.String()
|
||||
|
||||
|
||||
if err != nil {
|
||||
// Check if it was cancelled
|
||||
if ctx.Err() == context.Canceled {
|
||||
return backupStopMsg{service: item.service}
|
||||
}
|
||||
|
||||
|
||||
return backupErrorMsg{
|
||||
service: item.service,
|
||||
error: fmt.Sprintf("Backup failed: %s\n\n📋 Output:\n%s", err.Error(), finalOutput),
|
||||
@@ -1068,7 +1068,7 @@ func estimateProgress(output []string, service string) int {
|
||||
if len(output) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
switch service {
|
||||
case "plex":
|
||||
// Plex backup stages: stop service (10%), backup files (60%), verify (20%), archive (10%)
|
||||
@@ -1080,7 +1080,7 @@ func estimateProgress(output []string, service string) int {
|
||||
"archiving": 90,
|
||||
"completed": 100,
|
||||
}
|
||||
|
||||
|
||||
for _, line := range output {
|
||||
line = strings.ToLower(line)
|
||||
for stage, progress := range stages {
|
||||
@@ -1089,7 +1089,7 @@ func estimateProgress(output []string, service string) int {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case "immich":
|
||||
// Immich stages: database dump (50%), uploads backup (40%), upload to B2 (10%)
|
||||
stages := map[string]int{
|
||||
@@ -1099,7 +1099,7 @@ func estimateProgress(output []string, service string) int {
|
||||
"uploading to": 90,
|
||||
"completed": 100,
|
||||
}
|
||||
|
||||
|
||||
for _, line := range output {
|
||||
line = strings.ToLower(line)
|
||||
for stage, progress := range stages {
|
||||
@@ -1108,26 +1108,26 @@ func estimateProgress(output []string, service string) int {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
case "media":
|
||||
// Media services backup: each service adds progress
|
||||
services := []string{"sonarr", "radarr", "prowlarr", "audiobookshelf", "tautulli", "sabnzbd", "jellyseerr"}
|
||||
completed := 0
|
||||
|
||||
|
||||
for _, service := range services {
|
||||
for _, line := range output {
|
||||
if strings.Contains(strings.ToLower(line), service) &&
|
||||
(strings.Contains(strings.ToLower(line), "success") ||
|
||||
if strings.Contains(strings.ToLower(line), service) &&
|
||||
(strings.Contains(strings.ToLower(line), "success") ||
|
||||
strings.Contains(strings.ToLower(line), "completed")) {
|
||||
completed++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (completed * 100) / len(services)
|
||||
}
|
||||
|
||||
|
||||
// Default progress estimation based on line count
|
||||
if len(output) < 10 {
|
||||
return 20
|
||||
@@ -1136,7 +1136,7 @@ func estimateProgress(output []string, service string) int {
|
||||
} else if len(output) < 100 {
|
||||
return 80
|
||||
}
|
||||
|
||||
|
||||
return 90
|
||||
}
|
||||
|
||||
@@ -1248,11 +1248,11 @@ func createProgressBar(progress int) string {
|
||||
if progress > 100 {
|
||||
progress = 100
|
||||
}
|
||||
|
||||
|
||||
const barWidth = 30
|
||||
filled := (progress * barWidth) / 100
|
||||
empty := barWidth - filled
|
||||
|
||||
|
||||
bar := strings.Repeat("█", filled) + strings.Repeat("░", empty)
|
||||
return fmt.Sprintf("[%s]", bar)
|
||||
}
|
||||
@@ -1263,7 +1263,7 @@ func (m Model) startProgressTicker(service string) tea.Cmd {
|
||||
// Check if backup is still running
|
||||
if status, exists := m.backupStatus[service]; exists && status.Status == "running" {
|
||||
elapsed := time.Since(status.StartTime)
|
||||
|
||||
|
||||
// Estimate progress based on typical backup durations
|
||||
var estimatedDuration time.Duration
|
||||
switch service {
|
||||
@@ -1276,13 +1276,13 @@ func (m Model) startProgressTicker(service string) tea.Cmd {
|
||||
default:
|
||||
estimatedDuration = 5 * time.Minute
|
||||
}
|
||||
|
||||
|
||||
// Calculate progress (cap at 95% until actual completion)
|
||||
progress := int((elapsed.Seconds() / estimatedDuration.Seconds()) * 95)
|
||||
if progress > 95 {
|
||||
progress = 95
|
||||
}
|
||||
|
||||
|
||||
return backupProgressMsg{
|
||||
service: service,
|
||||
progress: progress,
|
||||
|
||||
Reference in New Issue
Block a user