First commit of golang CLI.
This commit is contained in:
288
wild-cli/internal/external/restic.go
vendored
Normal file
288
wild-cli/internal/external/restic.go
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
package external
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ResticTool wraps restic backup operations
|
||||
type ResticTool struct {
|
||||
*BaseTool
|
||||
repository string
|
||||
password string
|
||||
}
|
||||
|
||||
// NewResticTool creates a new restic tool wrapper
|
||||
func NewResticTool() *ResticTool {
|
||||
return &ResticTool{
|
||||
BaseTool: NewBaseTool("restic", "restic"),
|
||||
}
|
||||
}
|
||||
|
||||
// SetRepository sets the restic repository
|
||||
func (r *ResticTool) SetRepository(repo string) {
|
||||
r.repository = repo
|
||||
}
|
||||
|
||||
// SetPassword sets the restic password
|
||||
func (r *ResticTool) SetPassword(password string) {
|
||||
r.password = password
|
||||
}
|
||||
|
||||
// InitRepository initializes a new restic repository
|
||||
func (r *ResticTool) InitRepository(ctx context.Context) error {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"init"}
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
_, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing repository: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Backup creates a backup
|
||||
func (r *ResticTool) Backup(ctx context.Context, paths []string, excludes []string, tags []string) error {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"backup"}
|
||||
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
// Add paths
|
||||
args = append(args, paths...)
|
||||
|
||||
// Add excludes
|
||||
for _, exclude := range excludes {
|
||||
args = append(args, "--exclude", exclude)
|
||||
}
|
||||
|
||||
// Add tags
|
||||
for _, tag := range tags {
|
||||
args = append(args, "--tag", tag)
|
||||
}
|
||||
|
||||
_, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating backup: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Restore restores from backup
|
||||
func (r *ResticTool) Restore(ctx context.Context, snapshotID, target string) error {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"restore", snapshotID, "--target", target}
|
||||
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
_, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("restoring backup: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListSnapshots lists available snapshots
|
||||
func (r *ResticTool) ListSnapshots(ctx context.Context, tags []string) ([]byte, error) {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"snapshots", "--json"}
|
||||
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
// Add tag filters
|
||||
for _, tag := range tags {
|
||||
args = append(args, "--tag", tag)
|
||||
}
|
||||
|
||||
output, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listing snapshots: %w", err)
|
||||
}
|
||||
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// Check verifies repository integrity
|
||||
func (r *ResticTool) Check(ctx context.Context) error {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"check"}
|
||||
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
_, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("checking repository: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Forget removes snapshots
|
||||
func (r *ResticTool) Forget(ctx context.Context, keepLast int, keepDaily int, keepWeekly int, keepMonthly int, prune bool) error {
|
||||
env := r.getEnvironment()
|
||||
|
||||
cmd := r.BaseTool
|
||||
originalEnv := os.Environ()
|
||||
defer func() {
|
||||
os.Clearenv()
|
||||
for _, kv := range originalEnv {
|
||||
if k, v, found := strings.Cut(kv, "="); found {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables
|
||||
for k, v := range env {
|
||||
_ = os.Setenv(k, v)
|
||||
}
|
||||
|
||||
args := []string{"forget"}
|
||||
|
||||
if r.repository != "" {
|
||||
args = append(args, "--repo", r.repository)
|
||||
}
|
||||
|
||||
if keepLast > 0 {
|
||||
args = append(args, "--keep-last", fmt.Sprintf("%d", keepLast))
|
||||
}
|
||||
|
||||
if keepDaily > 0 {
|
||||
args = append(args, "--keep-daily", fmt.Sprintf("%d", keepDaily))
|
||||
}
|
||||
|
||||
if keepWeekly > 0 {
|
||||
args = append(args, "--keep-weekly", fmt.Sprintf("%d", keepWeekly))
|
||||
}
|
||||
|
||||
if keepMonthly > 0 {
|
||||
args = append(args, "--keep-monthly", fmt.Sprintf("%d", keepMonthly))
|
||||
}
|
||||
|
||||
if prune {
|
||||
args = append(args, "--prune")
|
||||
}
|
||||
|
||||
_, err := cmd.Execute(ctx, args...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("forgetting snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getEnvironment returns environment variables for restic
|
||||
func (r *ResticTool) getEnvironment() map[string]string {
|
||||
env := make(map[string]string)
|
||||
|
||||
if r.repository != "" {
|
||||
env["RESTIC_REPOSITORY"] = r.repository
|
||||
}
|
||||
|
||||
if r.password != "" {
|
||||
env["RESTIC_PASSWORD"] = r.password
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
Reference in New Issue
Block a user