...
1
2
3
4
5 package main
6
7 import (
8 "crypto/sha256"
9 "fmt"
10 "log"
11 "os"
12 "path/filepath"
13 )
14
15 func main() {
16 for _, consistentSnapshot := range []bool{false, true} {
17 err := linkifyDir(fmt.Sprintf("consistent-snapshot-%t", consistentSnapshot))
18 if err != nil {
19 log.Fatal(err)
20 }
21 }
22 }
23
24 func linkifyDir(rootDir string) error {
25 stepDirs, err := readStepDirs(rootDir)
26 if err != nil {
27 return err
28 }
29
30 oldDir := stepDirs[0]
31 oldHashes := computeHashes(oldDir)
32
33 for _, dir := range stepDirs[1:] {
34 log.Printf("checking: %s", dir)
35
36 hashes := computeHashes(dir)
37
38 for path, hash := range hashes {
39 if oldHashes[path] == hash {
40 newPath := filepath.Join(dir, path)
41 oldPath := filepath.Join(oldDir, path)
42 if err = linkifyPath(oldPath, newPath); err != nil {
43 return err
44 }
45 }
46 }
47
48 oldDir = dir
49 oldHashes = hashes
50 log.Printf("-----")
51 }
52
53 return nil
54 }
55
56 func readStepDirs(rootDir string) ([]string, error) {
57 dirEntries, err := os.ReadDir(rootDir)
58 if err != nil {
59 return []string{}, err
60 }
61
62
63 var dirs []string
64 for _, dirEntry := range dirEntries {
65 if dirEntry.IsDir() {
66 dirs = append(dirs, filepath.Join(rootDir, dirEntry.Name()))
67 }
68 }
69
70 return dirs, nil
71 }
72
73 func computeHashes(dir string) map[string][32]byte {
74 hashes := make(map[string][32]byte)
75
76 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
77 if info.IsDir() || !info.Mode().IsRegular() {
78 return nil
79 }
80
81 bytes, err := os.ReadFile(path)
82 if err != nil {
83 return err
84 }
85
86 hashes[path[len(dir)+1:]] = sha256.Sum256(bytes)
87
88 return nil
89 })
90 if err != nil {
91 log.Fatalf("failed to linkify: %s", err)
92 }
93
94 return hashes
95 }
96
97 func linkifyPath(oldPath string, newPath string) error {
98 p, err := filepath.Rel(filepath.Dir(newPath), oldPath)
99 if err != nil {
100 return err
101 }
102 log.Printf("symlinking %s to %s", newPath, p)
103
104 if err = os.Remove(newPath); err != nil {
105 return err
106 }
107 if err = os.Symlink(p, newPath); err != nil {
108 return err
109 }
110
111 return nil
112 }
113
View as plain text