diff --git a/main.go b/main.go index f97e821..6e00962 100755 --- a/main.go +++ b/main.go @@ -1,59 +1,34 @@ package main import ( - "bytes" "fmt" - "io" - "io/ioutil" "local/args" - "local/storage" + "local/lastn/lastn" "log" "os" - "os/exec" "path" "path/filepath" - "sort" - "time" ) -type Config struct { - n int - conf string - rclone string - ns string - root string - store string - cmd string -} - -type LastN struct { - store storage.DB - conf Config -} - func main() { conf := config() log.Println(conf) - storage, err := storage.New(storage.TypeFromString(conf.store), conf.conf, path.Join(conf.rclone+":", conf.ns)) + lastn, err := lastn.New(conf) if err != nil { panic(err) } - lastn := &LastN{ - conf: conf, - store: storage, - } actions := []func() error{} - switch conf.cmd { + switch conf.Cmd { case "backup": - actions = append(actions, lastn.push, lastn.clean) + actions = append(actions, lastn.Push, lastn.Clean) case "list": - actions = append(actions, lastn.list) + actions = append(actions, lastn.List) case "clean": - actions = append(actions, lastn.clean) + actions = append(actions, lastn.Clean) case "restore": - actions = append(actions, lastn.restore) + actions = append(actions, lastn.Restore) default: - panic(fmt.Sprintf("not impl: %s")) + panic(fmt.Sprintf("not impl: %s", conf.Cmd)) } for _, action := range actions { if err := action(); err != nil { @@ -62,7 +37,7 @@ func main() { } } -func config() Config { +func config() lastn.Config { as := args.NewArgSet() as.Append(args.INT, "n", "number of backups to retain", 5) as.Append(args.STRING, "conf", "path to rclone conf", path.Join(os.Getenv("HOME"), "/.config/rclone/rclone.conf")) @@ -78,118 +53,13 @@ func config() Config { if err != nil { panic(err) } - return Config{ - n: as.Get("n").GetInt(), - conf: as.Get("conf").GetString(), - rclone: as.Get("rclone").GetString(), - root: root, - ns: as.Get("ns").GetString(), - store: as.Get("store").GetString(), - cmd: as.Get("cmd").GetString(), + return lastn.Config{ + N: as.Get("n").GetInt(), + Conf: as.Get("conf").GetString(), + Rclone: as.Get("rclone").GetString(), + Root: root, + Ns: as.Get("ns").GetString(), + Store: as.Get("store").GetString(), + Cmd: as.Get("cmd").GetString(), } } - -func (lastN *LastN) push() error { - root := lastN.conf.root - store := lastN.store - root, err := filepath.Abs(root) - if err != nil { - return err - } - archive := path.Join( - os.TempDir(), - fmt.Sprintf( - "%s.tar", - time.Now().Format("2006.01.02.15.04.05"), - ), - ) - cmd := exec.Command( - "tar", - "-czf", - archive, - "-C", - path.Dir(root), - path.Base(root), - ) - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("%v: %s", err, out) - } - b, err := ioutil.ReadFile(archive) - if err != nil { - return err - } - log.Println("Created backup", path.Base(archive)) - return store.Set(path.Base(archive), b) -} - -func (lastN *LastN) clean() error { - n := lastN.conf.n - store := lastN.store - backups, err := store.List(nil) - if err != nil { - return err - } - sort.Strings(backups) - for i := 0; i < len(backups)-n; i++ { - log.Println("Pruning old backup", backups[i]) - err := store.Set(backups[i], nil) - if err != nil { - return err - } - } - return nil -} - -func (lastN *LastN) list() error { - store := lastN.store - backups, err := store.List(nil) - if err != nil { - return err - } - sort.Strings(backups) - for _, backup := range backups { - log.Println(backup) - } - return nil -} - -func (lastN *LastN) restore() error { - root := lastN.conf.root + "-restore" - os.RemoveAll(root) - if err := os.MkdirAll(root, os.ModePerm); err != nil { - return err - } - store := lastN.store - backups, err := store.List(nil) - if err != nil { - return fmt.Errorf("cannot list: %v", err) - } - sort.Strings(backups) - backup := backups[len(backups)-1] - b, err := store.Get(backup) - if err != nil { - return fmt.Errorf("cannot get %s: %v", backup, err) - } - log.Printf("restoring %s (%v) in %s", backup, len(b), root) - cmd := exec.Command( - "tar", - "-C", - root, - "-xzf", - "-", - ) - stdin, err := cmd.StdinPipe() - if err != nil { - return fmt.Errorf("cannot get stdin: %v", err) - } - go func() { - defer stdin.Close() - io.Copy(stdin, bytes.NewReader(b)) - }() - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed tar -xf: %v: %s", err, out) - } - return nil -}