blob: 0ccd3a4a9f69f83059aee2da51c60fa81df7c495 [file] [log] [blame]
// This helper command identifies duplicated metadata across multiple test
// stages, and replaces them with symlinks in order to make changes to them
// easier to read.
package main
import (
"crypto/sha256"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
)
func main() {
for _, consistentSnapshot := range []bool{false, true} {
err := linkifyDir(fmt.Sprintf("consistent-snapshot-%t", consistentSnapshot))
if err != nil {
log.Fatal(err)
}
}
}
func linkifyDir(rootDir string) error {
stepDirs, err := readStepDirs(rootDir)
if err != nil {
return err
}
oldDir := stepDirs[0]
oldHashes := computeHashes(oldDir)
for _, dir := range stepDirs[1:] {
log.Printf("checking: %s", dir)
hashes := computeHashes(dir)
for path, hash := range hashes {
if oldHashes[path] == hash {
newPath := filepath.Join(dir, path)
oldPath := filepath.Join(oldDir, path)
if err = linkifyPath(oldPath, newPath); err != nil {
return err
}
}
}
oldDir = dir
oldHashes = hashes
log.Printf("-----")
}
return nil
}
func readStepDirs(rootDir string) ([]string, error) {
dirEntries, err := ioutil.ReadDir(rootDir)
if err != nil {
return []string{}, err
}
// We only want to consider linkifying directories.
var dirs []string
for _, dirEntry := range dirEntries {
if dirEntry.IsDir() {
dirs = append(dirs, filepath.Join(rootDir, dirEntry.Name()))
}
}
return dirs, nil
}
func computeHashes(dir string) map[string][32]byte {
hashes := make(map[string][32]byte)
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if info.IsDir() || !info.Mode().IsRegular() {
return nil
}
bytes, err := ioutil.ReadFile(path)
if err != nil {
return err
}
hashes[path[len(dir)+1:]] = sha256.Sum256(bytes)
return nil
})
if err != nil {
log.Fatalf("failed to linkify: %s", err)
}
return hashes
}
func linkifyPath(oldPath string, newPath string) error {
p, err := filepath.Rel(filepath.Dir(newPath), oldPath)
if err != nil {
return err
}
log.Printf("symlinking %s to %s", newPath, p)
if err = os.Remove(newPath); err != nil {
return err
}
if err = os.Symlink(p, newPath); err != nil {
return err
}
return nil
}