Skip to content

Commit 00797dd

Browse files
committed
build: add 'go mod tidy' checker
1 parent d0c6442 commit 00797dd

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ test: all
5858
lint: ## Run linters.
5959
$(GORUN) build/ci.go lint
6060

61+
#? check_tidy: Verify go.mod and go.sum by 'go mod tidy'
62+
check_tidy: ## Run 'go mod tidy'.
63+
$(GORUN) build/ci.go check_tidy
64+
6165
#? clean: Clean go cache, built executables, and the auto generated folder.
6266
clean:
6367
rm -fr build/_workspace/pkg/ $(GOBIN)/*

build/ci.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ Usage: go run build/ci.go <command> <command flags/arguments>
2424
2525
Available commands are:
2626
27+
lint -- runs certain pre-selected linters
28+
check_tidy -- verifies that everything is 'go mod tidy'-ed
29+
2730
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
2831
test [ -coverage ] [ packages... ] -- runs the tests
29-
lint -- runs certain pre-selected linters
3032
importkeys -- imports signing keys from env
3133
xgo [ -alltools ] [ options ] -- cross builds according to options
3234
@@ -89,6 +91,8 @@ func main() {
8991
doTest(os.Args[2:])
9092
case "lint":
9193
doLint(os.Args[2:])
94+
case "check_tidy":
95+
doCheckTidy()
9296
case "xgo":
9397
doXgo(os.Args[2:])
9498
default:
@@ -246,6 +250,26 @@ func doTest(cmdline []string) {
246250
build.MustRun(gotest)
247251
}
248252

253+
// doCheckTidy assets that the Go modules files are tidied already.
254+
func doCheckTidy() {
255+
targets := []string{"go.mod", "go.sum"}
256+
257+
hashes, err := build.HashFiles(targets)
258+
if err != nil {
259+
log.Fatalf("failed to hash go.mod/go.sum: %v", err)
260+
}
261+
build.MustRun(new(build.GoToolchain).Go("mod", "tidy"))
262+
263+
tidied, err := build.HashFiles(targets)
264+
if err != nil {
265+
log.Fatalf("failed to rehash go.mod/go.sum: %v", err)
266+
}
267+
if updates := build.DiffHashes(hashes, tidied); len(updates) > 0 {
268+
log.Fatalf("files changed on running 'go mod tidy': %v", updates)
269+
}
270+
fmt.Println("No untidy module files detected.")
271+
}
272+
249273
// doLint runs golangci-lint on requested packages.
250274
func doLint(cmdline []string) {
251275
var (

internal/build/file.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// Copyright 2024 The go-ethereum Authors
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package build
18+
19+
import (
20+
"crypto/sha256"
21+
"io"
22+
"os"
23+
"path/filepath"
24+
"sort"
25+
"strings"
26+
)
27+
28+
// FileExist checks if a file exists at path.
29+
func FileExist(path string) bool {
30+
_, err := os.Stat(path)
31+
if err != nil && os.IsNotExist(err) {
32+
return false
33+
}
34+
return true
35+
}
36+
37+
// HashFiles iterates the provided set of files, computing the hash of each.
38+
func HashFiles(files []string) (map[string][32]byte, error) {
39+
res := make(map[string][32]byte)
40+
for _, filePath := range files {
41+
f, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
42+
if err != nil {
43+
return nil, err
44+
}
45+
hasher := sha256.New()
46+
if _, err := io.Copy(hasher, f); err != nil {
47+
return nil, err
48+
}
49+
res[filePath] = [32]byte(hasher.Sum(nil))
50+
}
51+
return res, nil
52+
}
53+
54+
// HashFolder iterates all files under the given directory, computing the hash
55+
// of each.
56+
func HashFolder(folder string, exlude []string) (map[string][32]byte, error) {
57+
res := make(map[string][32]byte)
58+
err := filepath.WalkDir(folder, func(path string, d os.DirEntry, _ error) error {
59+
// Skip anything that's exluded or not a regular file
60+
for _, skip := range exlude {
61+
if strings.HasPrefix(path, filepath.FromSlash(skip)) {
62+
return filepath.SkipDir
63+
}
64+
}
65+
if !d.Type().IsRegular() {
66+
return nil
67+
}
68+
// Regular file found, hash it
69+
f, err := os.OpenFile(path, os.O_RDONLY, 0666)
70+
if err != nil {
71+
return err
72+
}
73+
hasher := sha256.New()
74+
if _, err := io.Copy(hasher, f); err != nil {
75+
return err
76+
}
77+
res[path] = [32]byte(hasher.Sum(nil))
78+
return nil
79+
})
80+
if err != nil {
81+
return nil, err
82+
}
83+
return res, nil
84+
}
85+
86+
// DiffHashes compares two maps of file hashes and returns the changed files.
87+
func DiffHashes(a map[string][32]byte, b map[string][32]byte) []string {
88+
var updates []string
89+
90+
for file := range a {
91+
if _, ok := b[file]; !ok || a[file] != b[file] {
92+
updates = append(updates, file)
93+
}
94+
}
95+
for file := range b {
96+
if _, ok := a[file]; !ok {
97+
updates = append(updates, file)
98+
}
99+
}
100+
sort.Strings(updates)
101+
return updates
102+
}

0 commit comments

Comments
 (0)