diff --git a/github/gen-accessors.go b/github/gen-accessors.go index 9b47ce0e197..aa63bfc16ab 100644 --- a/github/gen-accessors.go +++ b/github/gen-accessors.go @@ -21,12 +21,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "slices" @@ -39,6 +41,7 @@ const ( ) var ( + check = flag.Bool("check", false, "Check whether generated files are up to date") verbose = flag.Bool("v", false, "Print verbose log messages") sourceTmpl = template.Must(template.New("source").Parse(source)) @@ -67,6 +70,10 @@ var ( } ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func logf(fmt string, args ...any) { if *verbose { log.Printf(fmt, args...) @@ -233,6 +240,22 @@ func (t *templateData) dump() error { return fmt.Errorf("format.Source:\n%v\n%v", buf.String(), err) } + if isCheck() { + logf("Checking %v...", filename) + old, err := os.ReadFile(filename) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Missing file: %v\n", filename) + } + return err + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil + } + logf("Writing %v...", filename) if err := os.Chmod(filename, 0o644); err != nil { return fmt.Errorf("os.Chmod(%q, 0644): %v", filename, err) diff --git a/github/gen-iterators.go b/github/gen-iterators.go index 8460c091d5b..5830f97ddae 100644 --- a/github/gen-iterators.go +++ b/github/gen-iterators.go @@ -14,12 +14,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "reflect" @@ -34,6 +36,7 @@ const ( ) var ( + check = flag.Bool("check", false, "Check whether generated files are up to date") verbose = flag.Bool("v", false, "Print verbose log messages") sourceTmpl = template.Must(template.New("source").Funcs(template.FuncMap{ @@ -43,6 +46,10 @@ var ( testTmpl = template.Must(template.New("test").Parse(test)) ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func logf(fmt string, args ...any) { if *verbose { log.Printf(fmt, args...) @@ -599,6 +606,22 @@ func (t *templateData) dump() error { if err != nil { return fmt.Errorf("format.Source: %v\n%s", err, buf.String()) } + if isCheck() { + logf("Checking %v...", filename) + old, err := os.ReadFile(filename) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Missing file: %v\n", filename) + } + return err + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil + } + logf("Writing %v...", filename) return os.WriteFile(filename, clean, 0o644) } diff --git a/github/gen-stringify-test.go b/github/gen-stringify-test.go index 3f31caf8a92..ebaea533dfc 100644 --- a/github/gen-stringify-test.go +++ b/github/gen-stringify-test.go @@ -17,12 +17,14 @@ package main import ( "bytes" + "errors" "flag" "fmt" "go/ast" "go/format" "go/parser" "go/token" + "io/fs" "log" "os" "strings" @@ -36,6 +38,7 @@ const ( ) var ( + check = flag.Bool("check", false, "Check whether generated files are up to date") verbose = flag.Bool("v", false, "Print verbose log messages") // skipStructMethods lists "struct.method" combos to skip. @@ -83,6 +86,10 @@ var ( sourceTmpl = template.Must(template.New("source").Funcs(funcMap).Parse(source)) ) +func isCheck() bool { + return *check || os.Getenv("CHECK") == "1" +} + func main() { flag.Parse() fset := token.NewFileSet() @@ -353,6 +360,22 @@ func (t *templateData) dump() error { return err } + if isCheck() { + logf("Checking %v...", t.filename) + old, err := os.ReadFile(t.filename) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return fmt.Errorf("Missing file: %v\n", t.filename) + } + return err + } + + if !bytes.Equal(old, clean) { + return fmt.Errorf("Generated files are out of date. Please run go generate ./... and commit the results") + } + return nil + } + logf("Writing %v...", t.filename) if err := os.Chmod(t.filename, 0o644); err != nil { return fmt.Errorf("os.Chmod(%q, 0644): %v", t.filename, err) diff --git a/script/generate.sh b/script/generate.sh index 2c34e002337..9408ac052b9 100755 --- a/script/generate.sh +++ b/script/generate.sh @@ -1,5 +1,5 @@ #!/bin/sh -#/ `script/generate.sh` runs `go generate` on all modules in this repo. +#/ `script/generate.sh` runs `go generate` on repo. #/ It also runs `script/run-check-structfield-settings.sh -fix` to keep linter #/ exceptions in `.golangci.yml` up to date. #/ `script/generate.sh --check` checks that the generated files are up to date. @@ -8,47 +8,28 @@ set -e CDPATH="" cd -- "$(dirname -- "$0")/.." +CHECK_MODE=0 if [ "$1" = "--check" ]; then - GENTEMP="$(mktemp -d)" - git worktree add -q --detach "$GENTEMP" - trap 'git worktree remove -f "$GENTEMP"; rm -rf "$GENTEMP"' EXIT - git diff --name-only --diff-filter=D --no-renames HEAD | while read -r f; do - rm -f "$GENTEMP/$f" - done - git ls-files -com --exclude-standard | while read -r f; do - target="$GENTEMP/$f" - mkdir -p "$(dirname -- "$target")" - cp "$f" "$target" - done - if [ -f "$(pwd)"/bin ]; then - ln -s "$(pwd)"/bin "$GENTEMP"/bin - fi - ( - cd "$GENTEMP" - git add . - git -c user.name='bot' -c user.email='bot@localhost' -c commit.gpgsign=false commit -m "generate" -q --allow-empty - script/generate.sh - [ -z "$(git status --porcelain)" ] || { - msg="Generated files are out of date. Please run script/generate.sh and commit the results" - if [ -n "$GITHUB_ACTIONS" ]; then - echo "::error ::$msg" - else - echo "$msg" 1>&2 - fi - git diff - exit 1 - } - ) - exit 0 + export CHECK=1 + CHECK_MODE=1 fi +go generate ./... + MOD_DIRS="$(git ls-files '*go.mod' | xargs dirname | sort)" for dir in $MOD_DIRS; do ( cd "$dir" - go generate ./... - go mod tidy + if [ "$CHECK_MODE" = "1" ]; then + if ! go mod tidy -diff; then + echo "go.mod/go.sum are out of date in $dir" + exit 1 + fi + else + go mod tidy + fi ) done + script/run-check-structfield-settings.sh -fix