summaryrefslogtreecommitdiff
path: root/restore.go
diff options
context:
space:
mode:
Diffstat (limited to 'restore.go')
-rw-r--r--restore.go75
1 files changed, 75 insertions, 0 deletions
diff --git a/restore.go b/restore.go
new file mode 100644
index 0000000..f99196a
--- /dev/null
+++ b/restore.go
@@ -0,0 +1,75 @@
+/* Restore from a series of restic snapshots. */
+package main
+
+import (
+ "fmt"
+ "os"
+ "io"
+ "log"
+ "strings"
+ "slices"
+)
+
+type Snapshot struct {
+ id string
+ dirs []string
+}
+
+func main() {
+ body, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ var shots []Snapshot
+ var current Snapshot
+
+ lines := strings.Split(string(body), "\n")
+ for _, s := range lines[2:len(lines) - 3] {
+ split := strings.Split(s, " ")
+ if len(s) == 0 {
+ shots = append(shots, current)
+ // Old snapshot is garbage collected.
+ current = Snapshot{}
+ } else if s[0] == ' ' {
+ // Directory at the end of line.
+ current.dirs = append(current.dirs, split[len(split) - 1])
+ } else {
+ // New snapshot.
+ current.id = split[0]
+ current.dirs = []string{split[len(split) - 1]}
+ }
+ }
+
+ // Last not followed by blank line.
+ shots = append(shots, current)
+
+ /*
+ for _, shot := range shots {
+ fmt.Println(shot.id)
+ for _, dir := range shot.dirs {
+ fmt.Println("\t" + dir)
+ }
+ } */
+
+ /* Traverse through the snapshots in reverse order.
+ The earlier entries covered by current are removed. */
+ seen := []string{}
+ list := make(map[string]string)
+ for i := len(shots) - 1; i >= 0; i-- {
+ for _, dir := range(shots[i].dirs) {
+ if !slices.Contains(seen, dir) {
+ seen = append(seen, dir)
+ list[shots[i].id] += dir + ","
+ }
+ }
+ }
+
+ for id, paths := range list {
+ for _, dir := range strings.Split(paths, ",") {
+ if dir != "" {
+ fmt.Println("restic restore " + id + ":" + dir + " --overwrite=if-newer --target=" + dir)
+ }
+ }
+ }
+}