From 267e40cc67fbb45f44afbfd42f654d24f81a7f93 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Fri, 27 Sep 2024 13:46:10 -0700 Subject: [PATCH] conditionally write generated files (#890) --- Taskfile.yml | 16 +----- cmd/generatego/main-generatego.go | 45 ++++++++++----- cmd/generatets/main-generatets.go | 96 ++++++++++++++++--------------- pkg/util/utilfn/utilfn.go | 12 ++++ 4 files changed, 94 insertions(+), 75 deletions(-) diff --git a/Taskfile.yml b/Taskfile.yml index 2014f91a2..29a37bd42 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -189,20 +189,8 @@ tasks: sources: - "cmd/generatego/*.go" - "cmd/generatets/*.go" - - "pkg/service/**/*.go" - - "pkg/waveobj/*.go" - - "pkg/wconfig/**/*.go" - - "pkg/wstore/*.go" - - "pkg/wshrpc/**/*.go" - - "pkg/tsgen/**/*.go" - - "pkg/gogen/**/*.go" - - "pkg/wconfig/**/*.go" - - "pkg/eventbus/eventbus.go" - generates: - - frontend/types/gotypes.d.ts - - pkg/wshrpc/wshclient/wshclient.go - - frontend/app/store/services.ts - - frontend/app/store/wshserver.ts + - "pkg/**/*.go" + # don't add generates key (otherwise will always execute) version: desc: Get the current package version, or bump version if args are present. To pass args to `version.cjs`, add them after `--`. See `version.cjs` for usage definitions for the arguments. diff --git a/cmd/generatego/main-generatego.go b/cmd/generatego/main-generatego.go index 9c4a172f8..a409b7e31 100644 --- a/cmd/generatego/main-generatego.go +++ b/cmd/generatego/main-generatego.go @@ -20,7 +20,7 @@ const WshClientFileName = "pkg/wshrpc/wshclient/wshclient.go" const WaveObjMetaConstsFileName = "pkg/waveobj/metaconsts.go" const SettingsMetaConstsFileName = "pkg/wconfig/metaconsts.go" -func GenerateWshClient() { +func GenerateWshClient() error { fmt.Fprintf(os.Stderr, "generating wshclient file to %s\n", WshClientFileName) var buf strings.Builder gogen.GenerateBoilerplate(&buf, "wshclient", []string{ @@ -42,38 +42,53 @@ func GenerateWshClient() { } } buf.WriteString("\n") - err := os.WriteFile(WshClientFileName, []byte(buf.String()), 0644) - if err != nil { - panic(err) + written, err := utilfn.WriteFileIfDifferent(WshClientFileName, []byte(buf.String())) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", WshClientFileName) } + return err } -func GenerateWaveObjMetaConsts() { +func GenerateWaveObjMetaConsts() error { fmt.Fprintf(os.Stderr, "generating waveobj meta consts file to %s\n", WaveObjMetaConstsFileName) var buf strings.Builder gogen.GenerateBoilerplate(&buf, "waveobj", []string{}) gogen.GenerateMetaMapConsts(&buf, "MetaKey_", reflect.TypeOf(waveobj.MetaTSType{})) buf.WriteString("\n") - err := os.WriteFile(WaveObjMetaConstsFileName, []byte(buf.String()), 0644) - if err != nil { - panic(err) + written, err := utilfn.WriteFileIfDifferent(WaveObjMetaConstsFileName, []byte(buf.String())) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", WaveObjMetaConstsFileName) } + return err } -func GenerateSettingsMetaConsts() { +func GenerateSettingsMetaConsts() error { fmt.Fprintf(os.Stderr, "generating settings meta consts file to %s\n", SettingsMetaConstsFileName) var buf strings.Builder gogen.GenerateBoilerplate(&buf, "wconfig", []string{}) gogen.GenerateMetaMapConsts(&buf, "ConfigKey_", reflect.TypeOf(wconfig.SettingsType{})) buf.WriteString("\n") - err := os.WriteFile(SettingsMetaConstsFileName, []byte(buf.String()), 0644) - if err != nil { - panic(err) + written, err := utilfn.WriteFileIfDifferent(SettingsMetaConstsFileName, []byte(buf.String())) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", SettingsMetaConstsFileName) } + return err } func main() { - GenerateWshClient() - GenerateWaveObjMetaConsts() - GenerateSettingsMetaConsts() + err := GenerateWshClient() + if err != nil { + fmt.Fprintf(os.Stderr, "error generating wshclient: %v\n", err) + return + } + err = GenerateWaveObjMetaConsts() + if err != nil { + fmt.Fprintf(os.Stderr, "error generating waveobj meta consts: %v\n", err) + return + } + err = GenerateSettingsMetaConsts() + if err != nil { + fmt.Fprintf(os.Stderr, "error generating settings meta consts: %v\n", err) + return + } } diff --git a/cmd/generatets/main-generatets.go b/cmd/generatets/main-generatets.go index 446312adc..948ef853a 100644 --- a/cmd/generatets/main-generatets.go +++ b/cmd/generatets/main-generatets.go @@ -4,6 +4,7 @@ package main import ( + "bytes" "fmt" "os" "reflect" @@ -17,14 +18,10 @@ import ( ) func generateTypesFile(tsTypesMap map[reflect.Type]string) error { - fd, err := os.Create("frontend/types/gotypes.d.ts") - if err != nil { - return err - } - defer fd.Close() - fmt.Fprintf(os.Stderr, "generating types file to %s\n", fd.Name()) + fileName := "frontend/types/gotypes.d.ts" + fmt.Fprintf(os.Stderr, "generating types file to %s\n", fileName) tsgen.GenerateWaveObjTypes(tsTypesMap) - err = tsgen.GenerateServiceTypes(tsTypesMap) + err := tsgen.GenerateServiceTypes(tsTypesMap) if err != nil { fmt.Fprintf(os.Stderr, "Error generating service types: %v\n", err) os.Exit(1) @@ -33,10 +30,11 @@ func generateTypesFile(tsTypesMap map[reflect.Type]string) error { if err != nil { return fmt.Errorf("error generating wsh server types: %w", err) } - fmt.Fprintf(fd, "// Copyright 2024, Command Line Inc.\n") - fmt.Fprintf(fd, "// SPDX-License-Identifier: Apache-2.0\n\n") - fmt.Fprintf(fd, "// generated by cmd/generate/main-generatets.go\n\n") - fmt.Fprintf(fd, "declare global {\n\n") + var buf bytes.Buffer + fmt.Fprintf(&buf, "// Copyright 2024, Command Line Inc.\n") + fmt.Fprintf(&buf, "// SPDX-License-Identifier: Apache-2.0\n\n") + fmt.Fprintf(&buf, "// generated by cmd/generate/main-generatets.go\n\n") + fmt.Fprintf(&buf, "declare global {\n\n") var keys []reflect.Type for key := range tsTypesMap { keys = append(keys, key) @@ -48,63 +46,69 @@ func generateTypesFile(tsTypesMap map[reflect.Type]string) error { }) for _, key := range keys { // don't output generic types - if strings.Index(key.Name(), "[") != -1 { + if strings.Contains(key.Name(), "[") { continue } tsCode := tsTypesMap[key] istr := utilfn.IndentString(" ", tsCode) - fmt.Fprint(fd, istr) + fmt.Fprint(&buf, istr) } - fmt.Fprintf(fd, "}\n\n") - fmt.Fprintf(fd, "export {}\n") - return nil + fmt.Fprintf(&buf, "}\n\n") + fmt.Fprintf(&buf, "export {}\n") + written, err := utilfn.WriteFileIfDifferent(fileName, buf.Bytes()) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", fileName) + } + return err } func generateServicesFile(tsTypesMap map[reflect.Type]string) error { - fd, err := os.Create("frontend/app/store/services.ts") - if err != nil { - return err - } - defer fd.Close() - fmt.Fprintf(os.Stderr, "generating services file to %s\n", fd.Name()) - fmt.Fprintf(fd, "// Copyright 2024, Command Line Inc.\n") - fmt.Fprintf(fd, "// SPDX-License-Identifier: Apache-2.0\n\n") - fmt.Fprintf(fd, "// generated by cmd/generate/main-generatets.go\n\n") - fmt.Fprintf(fd, "import * as WOS from \"./wos\";\n\n") + fileName := "frontend/app/store/services.ts" + var buf bytes.Buffer + fmt.Fprintf(os.Stderr, "generating services file to %s\n", fileName) + fmt.Fprintf(&buf, "// Copyright 2024, Command Line Inc.\n") + fmt.Fprintf(&buf, "// SPDX-License-Identifier: Apache-2.0\n\n") + fmt.Fprintf(&buf, "// generated by cmd/generate/main-generatets.go\n\n") + fmt.Fprintf(&buf, "import * as WOS from \"./wos\";\n\n") orderedKeys := utilfn.GetOrderedMapKeys(service.ServiceMap) for _, serviceName := range orderedKeys { serviceObj := service.ServiceMap[serviceName] svcStr := tsgen.GenerateServiceClass(serviceName, serviceObj, tsTypesMap) - fmt.Fprint(fd, svcStr) - fmt.Fprint(fd, "\n") + fmt.Fprint(&buf, svcStr) + fmt.Fprint(&buf, "\n") } - return nil + written, err := utilfn.WriteFileIfDifferent(fileName, buf.Bytes()) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", fileName) + } + return err } func generateWshClientApiFile(tsTypeMap map[reflect.Type]string) error { - fd, err := os.Create("frontend/app/store/wshclientapi.ts") - if err != nil { - return err - } - defer fd.Close() + fileName := "frontend/app/store/wshclientapi.ts" + var buf bytes.Buffer declMap := wshrpc.GenerateWshCommandDeclMap() - fmt.Fprintf(os.Stderr, "generating wshclientapi file to %s\n", fd.Name()) - fmt.Fprintf(fd, "// Copyright 2024, Command Line Inc.\n") - fmt.Fprintf(fd, "// SPDX-License-Identifier: Apache-2.0\n\n") - fmt.Fprintf(fd, "// generated by cmd/generate/main-generatets.go\n\n") - fmt.Fprintf(fd, "import { WshClient } from \"./wshclient\";\n\n") + fmt.Fprintf(os.Stderr, "generating wshclientapi file to %s\n", fileName) + fmt.Fprintf(&buf, "// Copyright 2024, Command Line Inc.\n") + fmt.Fprintf(&buf, "// SPDX-License-Identifier: Apache-2.0\n\n") + fmt.Fprintf(&buf, "// generated by cmd/generate/main-generatets.go\n\n") + fmt.Fprintf(&buf, "import { WshClient } from \"./wshclient\";\n\n") orderedKeys := utilfn.GetOrderedMapKeys(declMap) - fmt.Fprintf(fd, "// WshServerCommandToDeclMap\n") - fmt.Fprintf(fd, "class RpcApiType {\n") + fmt.Fprintf(&buf, "// WshServerCommandToDeclMap\n") + fmt.Fprintf(&buf, "class RpcApiType {\n") for _, methodDecl := range orderedKeys { methodDecl := declMap[methodDecl] methodStr := tsgen.GenerateWshClientApiMethod(methodDecl, tsTypeMap) - fmt.Fprint(fd, methodStr) - fmt.Fprintf(fd, "\n") + fmt.Fprint(&buf, methodStr) + fmt.Fprintf(&buf, "\n") } - fmt.Fprintf(fd, "}\n\n") - fmt.Fprintf(fd, "export const RpcApi = new RpcApiType();\n") - return nil + fmt.Fprintf(&buf, "}\n\n") + fmt.Fprintf(&buf, "export const RpcApi = new RpcApiType();\n") + written, err := utilfn.WriteFileIfDifferent(fileName, buf.Bytes()) + if !written { + fmt.Fprintf(os.Stderr, "no changes to %s\n", fileName) + } + return err } func main() { diff --git a/pkg/util/utilfn/utilfn.go b/pkg/util/utilfn/utilfn.go index 1f854d8ff..8aacd94b9 100644 --- a/pkg/util/utilfn/utilfn.go +++ b/pkg/util/utilfn/utilfn.go @@ -920,3 +920,15 @@ func GetJsonTag(field reflect.StructField) string { } return jsonTag } + +func WriteFileIfDifferent(fileName string, contents []byte) (bool, error) { + oldContents, err := os.ReadFile(fileName) + if err == nil && bytes.Equal(oldContents, contents) { + return false, nil + } + err = os.WriteFile(fileName, contents, 0644) + if err != nil { + return false, err + } + return true, nil +}