mirror of
https://github.com/KDE/kde-linux.git
synced 2026-04-23 08:01:08 -04:00
give dirs a stable time
with file mtimes stabilized, we now have dirs lighting up like a christmas tree in my diff scripts. give them a stable mtime to get consistency between builds. the idea here is that if we set the mtime of all dirs to their latest content's mtime we'll implicitly stabilize the dirs through stabilizing the files somewhat unfortunately we need to do this in a single thread because otherwise we'd have to segment deep trees and I really don't want to venture there for such an otherwise simple program a future option might be to also put dirs in our json but realistically that only makes a difference for empty dirs (since they have no content from which to derive the mtime). so let's see where we get with this. we can always add dir records in the json later
This commit is contained in:
@@ -14,11 +14,18 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type DirInfo struct {
|
||||
absPath string
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
SHA256 string `json:"sha256"`
|
||||
MTime int64 `json:"mtime"`
|
||||
@@ -89,6 +96,39 @@ func analyze(input Analysis) Analysis {
|
||||
return input
|
||||
}
|
||||
|
||||
func updateDir(dir DirInfo) {
|
||||
entries, err := os.ReadDir(dir.absPath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
dir.info, err = os.Stat(dir.absPath) // Refresh in case it changed
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
latest := dir.info.ModTime()
|
||||
for _, entry := range entries {
|
||||
if entry.Type()&os.ModeSymlink != 0 {
|
||||
continue
|
||||
}
|
||||
entryInfo, err := entry.Info()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if entryInfo.ModTime().After(latest) {
|
||||
latest = entryInfo.ModTime()
|
||||
}
|
||||
}
|
||||
|
||||
if latest.After(dir.info.ModTime()) {
|
||||
log.Println("Restoring mtime for directory", dir.absPath)
|
||||
if err := os.Chtimes(dir.absPath, latest, latest); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
root := flag.String("root", "", "rootfs to operate on")
|
||||
jsonPath := flag.String("json", "", "json file to read and write")
|
||||
@@ -110,12 +150,19 @@ func main() {
|
||||
Files: map[string]FileInfo{},
|
||||
}
|
||||
|
||||
// We also collect all directories so we might chmod them later.
|
||||
dirs := []DirInfo{}
|
||||
|
||||
toAnalyze := []Analysis{}
|
||||
err = filepath.Walk(*root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() || info.Mode()&os.ModeSymlink != 0 {
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
return nil
|
||||
}
|
||||
if info.IsDir() {
|
||||
dirs = append(dirs, DirInfo{absPath: path, info: info})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -162,6 +209,12 @@ func main() {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
g.Go(func() error {
|
||||
// Sort directories by depth, deepest first.
|
||||
// Be mindful that we change dirs in-place. This is not thread safe and relies on our errgroup waiting!
|
||||
sort.Slice(dirs, func(i, j int) bool { return strings.Count(dirs[i].absPath, "/") > strings.Count(dirs[j].absPath, "/") })
|
||||
return nil
|
||||
})
|
||||
if err := g.Wait(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -170,6 +223,14 @@ func main() {
|
||||
newBlob.Files[result.relPath] = result.info
|
||||
}
|
||||
|
||||
// Now let's chtimes the directories to the latest mtime of their contents.
|
||||
// This could be more efficient but makes for somewhat complicated code.
|
||||
// Instead we run the directories in a single thread.
|
||||
// Unfortunate but it is what it is.
|
||||
for _, dir := range dirs {
|
||||
updateDir(dir)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(newBlob)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
Reference in New Issue
Block a user