mirror of
https://github.com/rclone/rclone.git
synced 2025-03-13 07:35:13 +08:00
124 lines
3.0 KiB
Go
124 lines
3.0 KiB
Go
// This code was copied from:
|
|
// https://github.com/fastly/cli/blob/main/scripts/go-test-cache/main.go
|
|
// which in turn is based on the following script and was generated using AI.
|
|
// https://github.com/airplanedev/blog-examples/blob/main/go-test-caching/update_file_timestamps.py?ref=airplane.ghost.io
|
|
//
|
|
// REFERENCE ARTICLE:
|
|
// https://web.archive.org/web/20240308061717/https://www.airplane.dev/blog/caching-golang-tests-in-ci
|
|
//
|
|
// It updates the mtime of the files to a mtime dervived from the sha1 hash of their contents.
|
|
package main
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
bufSize = 65536
|
|
baseDate = 1684178360
|
|
timeFormat = "2006-01-02 15:04:05"
|
|
)
|
|
|
|
func main() {
|
|
repoRoot := "."
|
|
allDirs := make([]string, 0)
|
|
|
|
err := filepath.Walk(repoRoot, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
dirPath := filepath.Join(repoRoot, path)
|
|
relPath, _ := filepath.Rel(repoRoot, dirPath)
|
|
|
|
if strings.HasPrefix(relPath, ".") {
|
|
return nil
|
|
}
|
|
|
|
allDirs = append(allDirs, dirPath)
|
|
} else {
|
|
filePath := filepath.Join(repoRoot, path)
|
|
relPath, _ := filepath.Rel(repoRoot, filePath)
|
|
|
|
if strings.HasPrefix(relPath, ".") {
|
|
return nil
|
|
}
|
|
|
|
sha1Hash, err := getFileSHA1(filePath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
modTime := getModifiedTime(sha1Hash)
|
|
|
|
log.Printf("Setting modified time of file %s to %s\n", relPath, modTime.Format(timeFormat))
|
|
err = os.Chtimes(filePath, modTime, modTime)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
log.Fatal("Error:", err)
|
|
}
|
|
|
|
sort.Slice(allDirs, func(i, j int) bool {
|
|
return len(allDirs[i]) > len(allDirs[j]) || (len(allDirs[i]) == len(allDirs[j]) && allDirs[i] < allDirs[j])
|
|
})
|
|
|
|
for _, dirPath := range allDirs {
|
|
relPath, _ := filepath.Rel(repoRoot, dirPath)
|
|
|
|
log.Printf("Setting modified time of directory %s to %s\n", relPath, time.Unix(baseDate, 0).Format(timeFormat))
|
|
err := os.Chtimes(dirPath, time.Unix(baseDate, 0), time.Unix(baseDate, 0))
|
|
if err != nil {
|
|
log.Fatal("Error:", err)
|
|
}
|
|
}
|
|
|
|
log.Println("Done")
|
|
}
|
|
|
|
func getFileSHA1(filePath string) (string, error) {
|
|
file, err := os.Open(filePath)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
// G401: Use of weak cryptographic primitive
|
|
// Disabling as the hash is used not for security reasons.
|
|
// The hash is used as a cache key to improve test run times.
|
|
// #nosec
|
|
// nosemgrep: go.lang.security.audit.crypto.use_of_weak_crypto.use-of-sha1
|
|
hash := sha1.New()
|
|
if _, err := io.CopyBuffer(hash, file, make([]byte, bufSize)); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return string(hash.Sum(nil)), nil
|
|
}
|
|
|
|
func getModifiedTime(sha1Hash string) time.Time {
|
|
hashBytes := []byte(sha1Hash)
|
|
lastFiveBytes := hashBytes[:5]
|
|
lastFiveValue := int64(0)
|
|
|
|
for _, b := range lastFiveBytes {
|
|
lastFiveValue = (lastFiveValue << 8) + int64(b)
|
|
}
|
|
|
|
modTime := baseDate - (lastFiveValue % 10000)
|
|
return time.Unix(modTime, 0)
|
|
}
|