Refactor codebase for Phase 3

This commit is contained in:
2026-06-08 13:34:53 -05:00
parent 6320f51295
commit c32e08be38
32 changed files with 4718 additions and 3323 deletions
+117
View File
@@ -0,0 +1,117 @@
package backup
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/go-sql-driver/mysql"
"gitocean/internal/model"
)
func Create(cfg model.ServerConfig, file string) error {
tmp, err := os.MkdirTemp("", "gitocean-backup-*")
if err != nil {
return err
}
defer os.RemoveAll(tmp)
metadata := filepath.Join(tmp, "metadata.sql")
mysqlArgs, dbName, err := MySQLCLIArgs(cfg.MySQLDSN)
if err != nil {
return err
}
cmd := exec.Command("mysqldump", append(mysqlArgs, dbName)...)
out, err := cmd.Output()
if err != nil {
return fmt.Errorf("mysqldump failed: %w", err)
}
if err := os.WriteFile(metadata, out, 0600); err != nil {
return err
}
cmd = exec.Command("tar", "-czf", file, "-C", ".", cfg.Storage, "-C", tmp, "metadata.sql")
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
return cmd.Run()
}
func Restore(cfg model.ServerConfig, file string) error {
tmp, err := os.MkdirTemp("", "gitocean-restore-*")
if err != nil {
return err
}
defer os.RemoveAll(tmp)
cmd := exec.Command("tar", "-xzf", file, "-C", tmp)
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
return err
}
mysqlArgs, dbName, err := MySQLCLIArgs(cfg.MySQLDSN)
if err != nil {
return err
}
metadata := filepath.Join(tmp, "metadata.sql")
f, err := os.Open(metadata)
if err != nil {
return err
}
defer f.Close()
cmd = exec.Command("mysql", append(mysqlArgs, dbName)...)
cmd.Stdin = f
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
return err
}
return CopyDir(filepath.Join(tmp, cfg.Storage), cfg.Storage)
}
func MySQLCLIArgs(dsn string) ([]string, string, error) {
cfg, err := mysql.ParseDSN(dsn)
if err != nil {
return nil, "", err
}
args := []string{}
if cfg.User != "" {
args = append(args, "-u"+cfg.User)
}
if cfg.Passwd != "" {
args = append(args, "-p"+cfg.Passwd)
}
if cfg.Net == "tcp" && cfg.Addr != "" {
host, port := cfg.Addr, ""
if strings.Contains(cfg.Addr, ":") {
host, port, _ = strings.Cut(cfg.Addr, ":")
}
if host != "" {
args = append(args, "-h"+host)
}
if port != "" {
args = append(args, "-P"+port)
}
} else if cfg.Net == "unix" && cfg.Addr != "" {
args = append(args, "--socket", cfg.Addr)
}
return args, cfg.DBName, nil
}
func CopyDir(src, dst string) error {
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
rel, err := filepath.Rel(src, path)
if err != nil {
return err
}
to := filepath.Join(dst, rel)
if info.IsDir() {
return os.MkdirAll(to, info.Mode())
}
b, err := os.ReadFile(path)
if err != nil {
return err
}
return os.WriteFile(to, b, info.Mode())
})
}