-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
137 lines (121 loc) · 3.13 KB
/
Copy pathmain.go
File metadata and controls
137 lines (121 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Command pgflow is a terminal UI for backing up and restoring PostgreSQL
// databases — a Bubble Tea front-end for the pg_dump / pg_restore workflow.
package main
import (
"encoding/json"
"fmt"
"os"
tea "github.com/charmbracelet/bubbletea"
"github.com/ander0code/pgflow/internal/backups"
"github.com/ander0code/pgflow/internal/config"
"github.com/ander0code/pgflow/internal/tui"
)
// version is injected at build time via -ldflags "-X main.version=...".
var version = "dev"
func main() {
listOnly, jsonOut := false, false
for _, a := range os.Args[1:] {
switch a {
case "--version", "-v":
fmt.Printf("pgflow %s\n", version)
return
case "--help", "-h":
printHelp()
return
case "--list":
listOnly = true
case "--json":
jsonOut = true
default:
fmt.Fprintf(os.Stderr, "pgflow: flag desconocida %q\n", a)
fmt.Fprintln(os.Stderr, "usa `pgflow --help`")
os.Exit(2)
}
}
if listOnly {
runList(jsonOut)
return
}
p := tea.NewProgram(tui.New(), tea.WithAltScreen())
if _, err := p.Run(); err != nil {
fmt.Fprintf(os.Stderr, "pgflow: %v\n", err)
os.Exit(1)
}
}
func runList(jsonOut bool) {
cfg := config.Load()
folders, err := backups.Scan(cfg.BackupDir)
if err != nil {
fmt.Fprintln(os.Stderr, "scan error:", err)
os.Exit(1)
}
if jsonOut {
type dumpOut struct {
Folder string `json:"folder"`
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size_bytes"`
Objects int `json:"objects"`
Valid bool `json:"valid"`
Created string `json:"created"`
}
out := make([]dumpOut, 0)
for _, f := range folders {
for _, d := range f.Dumps {
out = append(out, dumpOut{
Folder: f.Name, Name: d.Name, Path: d.Path,
Size: d.SizeBytes, Objects: d.Objects, Valid: d.Valid,
Created: d.ModTime.Format("2006-01-02 15:04:05"),
})
}
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
_ = enc.Encode(out)
return
}
fmt.Printf("%d backup(s) en %s\n", backups.Total(folders), cfg.BackupDir)
for _, f := range folders {
fmt.Printf("\n%s (%d)\n", f.Name, len(f.Dumps))
for _, d := range f.Dumps {
mark := "✓"
if !d.Valid {
mark = "✗"
}
fmt.Printf(" %s %-44s %8s %s\n",
mark, d.Name, human(d.SizeBytes), d.ModTime.Format("2006-01-02 15:04"))
}
}
}
func human(b int64) string {
const u = 1024
if b < u {
return fmt.Sprintf("%dB", b)
}
div, exp := int64(u), 0
for n := b / u; n >= u; n /= u {
div *= u
exp++
}
return fmt.Sprintf("%.1f%cB", float64(b)/float64(div), "KMGTPE"[exp])
}
func printHelp() {
fmt.Println(`pgflow — backup & restore de PostgreSQL (TUI)
Uso:
pgflow abre la interfaz (TUI)
pgflow --list lista los backups (texto)
pgflow --list --json lista los backups (JSON)
pgflow --version versión
pgflow --help esta ayuda
Dentro de la TUI:
↑/↓ j/k navegar
b backup de producción
r restaurar a local
v verificar un dump
d borrar un dump
t abrir / cerrar el túnel SSH
c configurar conexiones
^r refrescar
q salir
Config: ~/.pgflow.conf`)
}