From 5b524d10b8a4179739eccd2a3d9251a2013389b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 6 Dec 2023 20:18:03 +0100 Subject: [PATCH] Helper-gen calls defaulter-gen --- .../pkg/codegen/helpers/deepcopy.go | 142 +------------ .../pkg/codegen/helpers/defaulter.go | 31 +++ .../codegen/helpers/{gen.go => generator.go} | 4 + .../pkg/codegen/helpers/generic.go | 192 ++++++++++++++++++ 4 files changed, 235 insertions(+), 134 deletions(-) create mode 100644 staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go rename staging/src/k8s.io/code-generator/pkg/codegen/helpers/{gen.go => generator.go} (93%) create mode 100644 staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go diff --git a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/deepcopy.go b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/deepcopy.go index 850f01171f608..db1dfc74c82d4 100644 --- a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/deepcopy.go +++ b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/deepcopy.go @@ -17,143 +17,17 @@ package helpers import ( - goflag "flag" - "fmt" - "github.com/spf13/pflag" "k8s.io/code-generator/cmd/deepcopy-gen/gen" - "k8s.io/code-generator/pkg/osbin/git" - "k8s.io/code-generator/pkg/osbin/golang" - "k8s.io/klog/v2" - "os" - "path" ) func generateDeepCopy(args *Args) error { - pkgs, err := collectDeepCopyPackages(args) - if err != nil { - return err - } - klog.V(2).Infof("Found %d packages with deepcopy-gen tags", - len(pkgs)) - if len(pkgs) >= 0 { - if err = deleteDeepCopyHelpers(args); err != nil { - return err - } - } - return generateDeepCopyHelpers(args, pkgs) -} - -func deleteDeepCopyHelpers(args *Args) error { - pathspec := fmt.Sprintf(":(glob)%s/**/zz_generated.deepcopy.go", args.root) - if genFiles, err := git.Find(pathspec); err != nil { - return err - } else { - klog.V(2).Infof("Deleting %d existing deepcopy helpers", - len(genFiles)) - for _, file := range genFiles { - if _, oserr := os.Stat(file); oserr != nil && os.IsNotExist(oserr) { - continue - } - klog.V(4).Infof("Deleting %s", file) - if err = os.Remove(file); err != nil { - return err - } - } - } - return nil -} - -func generateDeepCopyHelpers(args *Args, pkgs []string) error { - if len(pkgs) == 0 { - return nil - } - klog.V(2).Infof("Generating deepcopy helpers for %d packages", len(pkgs)) - - klog.V(2) - dcargs := []string{ - "-O", "zz_generated.deepcopy", - "--output-base", args.OutputBase, - "--go-header-file", args.Boilerplate, - } - for _, pkg := range pkgs { - dcargs = append(dcargs, "--input-dirs", pkg) - } - fs := pflag.NewFlagSet("deepcopy-gen", pflag.ContinueOnError) - fs.AddGoFlagSet(goflag.CommandLine) // make sure we get the klog flags - klog.V(2).Infof("Running deepcopy-gen with args %q", dcargs) - return withinDirectory(args.root, func() error { - return asBinary("deepcopy-gen", func() error { - return gen.DeepCopy(fs, dcargs) - }) + return generateGen(args, genConf{ + name: "deepcopy", + fileSuffix: "deepcopy", + genFn: gen.DeepCopy, + search: searchConf{ + pattern: "+k8s:deepcopy-gen=", + pathspecFn: golangPathspec, + }, }) } - -func collectDeepCopyPackages(args *Args) ([]string, error) { - var inputPkgs = make(map[string]bool, 1) - if files, err := git.Grep( - "+k8s:deepcopy-gen=", - fmt.Sprintf(":(glob)%s/**/*.go", args.root), - git.WithList, - ); err != nil { - return nil, err - } else { - klog.V(3).Infof("Found %d files with deepcopy-gen tags", - len(files)) - - for _, file := range files { - if p, errr := resolvePackage(file); errr != nil { - klog.Errorf("Error finding package for %s: %s", file, errr) - return nil, errr - } else { - klog.V(4).Infof("Found package %s", p) - inputPkgs[p] = true - } - } - } - var pkgs []string - for p := range inputPkgs { - pkgs = append(pkgs, p) - } - return pkgs, nil -} - -func resolvePackage(file string) (string, error) { - dir := path.Dir(file) - var foundPkg string - if err := withinDirectory(dir, func() error { - if p, err := golang.PackageOf("."); err != nil { - klog.Errorf("Error finding package for %s: %s", dir, err) - return err - } else { - klog.V(4).Infof("Found %s", p) - foundPkg = p - return nil - } - }); err != nil { - return "", err - } - return foundPkg, nil -} - -func withinDirectory(dir string, fn func() error) error { - if wd, err := os.Getwd(); err != nil { - return err - } else { - defer func() { - _ = os.Chdir(wd) - }() - } - if err := os.Chdir(dir); err != nil { - return err - } - return fn() -} - -func asBinary(binName string, fn func() error) error { - curr := os.Args[0] - defer func() { - os.Args[0] = curr - }() - os.Args[0] = binName - return fn() -} diff --git a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go new file mode 100644 index 0000000000000..395d03eb16aa8 --- /dev/null +++ b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go @@ -0,0 +1,31 @@ +/* + Copyright 2023 The Kubernetes Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except In compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to In writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package helpers + +import "k8s.io/code-generator/cmd/defaulter-gen/gen" + +func generateDefaulter(args *Args) error { + return generateGen(args, genConf{ + name: "defaulter", + fileSuffix: "defaults", + genFn: gen.Defaulter, + search: searchConf{ + pattern: "+k8s:defaulter-gen=", + pathspecFn: golangPathspec, + }, + }) +} diff --git a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/gen.go b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/generator.go similarity index 93% rename from staging/src/k8s.io/code-generator/pkg/codegen/helpers/gen.go rename to staging/src/k8s.io/code-generator/pkg/codegen/helpers/generator.go index 2828aa12d92c0..4674cde3b95ff 100644 --- a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/gen.go +++ b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/generator.go @@ -35,5 +35,9 @@ func (g *Generator) Generate(args *Args) error { return err } + if err := generateDefaulter(args); err != nil { + return err + } + return nil } diff --git a/staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go new file mode 100644 index 0000000000000..de70f02d06922 --- /dev/null +++ b/staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go @@ -0,0 +1,192 @@ +/* + Copyright 2023 The Kubernetes Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except In compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to In writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package helpers + +import ( + goflag "flag" + "fmt" + "github.com/spf13/pflag" + "k8s.io/code-generator/pkg/osbin/git" + "k8s.io/code-generator/pkg/osbin/golang" + "k8s.io/klog/v2" + "os" + "path" +) + +type genFn func(fs *pflag.FlagSet, args []string) error + +type genConf struct { + name string + fileSuffix string + genFn + search searchConf +} + +type pathspecFn func(*Args) string + +func globPathspec(globFmt string) pathspecFn { + return func(args *Args) string { + return fmt.Sprintf(globFmt, args.root) + } +} + +func golangPathspec(args *Args) string { + return globPathspec(":(glob)%s/**/*.go")(args) +} + +func zzGeneratedPathspec(name string) pathspecFn { + return globPathspec( + fmt.Sprintf(":(glob)%%s/**/zz_generated.%s.go", name), + ) +} + +type searchConf struct { + pattern string + pathspecFn +} + +func generateGen(args *Args, gc genConf) error { + pkgs, err := collectPackages(args, gc) + if err != nil { + return err + } + klog.V(2).Infof("Found %d packages with %s-gen tags", + len(pkgs), gc.name) + if len(pkgs) >= 0 { + if err = deleteGenerated(args, gc); err != nil { + return err + } + } + return generatePackages(args, gc, pkgs) +} + +func collectPackages(args *Args, conf genConf) ([]string, error) { + var inputPkgs = make(map[string]bool, 1) + if files, err := git.Grep( + conf.search.pattern, + conf.search.pathspecFn(args), + git.WithList, + ); err != nil { + return nil, err + } else { + klog.V(3).Infof("Found %d files with %s-gen tags", + len(files), conf.name) + + for _, file := range files { + if p, errr := resolvePackage(file); errr != nil { + klog.Errorf("Error finding package for %s: %s", file, errr) + return nil, errr + } else { + klog.V(4).Infof("Found package %s", p) + inputPkgs[p] = true + } + } + } + var pkgs []string + for p := range inputPkgs { + pkgs = append(pkgs, p) + } + return pkgs, nil +} + +func deleteGenerated(args *Args, gc genConf) error { + pathspec := zzGeneratedPathspec(gc.fileSuffix)(args) + if genFiles, err := git.Find(pathspec); err != nil { + return err + } else { + klog.V(2).Infof("Deleting %d existing %s helpers", + len(genFiles), gc.name) + for _, file := range genFiles { + if _, oserr := os.Stat(file); oserr != nil && os.IsNotExist(oserr) { + continue + } + klog.V(4).Infof("Deleting %s", file) + if err = os.Remove(file); err != nil { + return err + } + } + } + return nil +} + +func generatePackages(args *Args, gc genConf, pkgs []string) error { + if len(pkgs) == 0 { + return nil + } + klog.V(2).Infof("Generating %s code for %d packages", + gc.name, len(pkgs)) + + dcargs := []string{ + "-O", fmt.Sprintf("zz_generated.%s", gc.fileSuffix), + "--output-base", args.OutputBase, + "--go-header-file", args.Boilerplate, + } + for _, pkg := range pkgs { + dcargs = append(dcargs, "--input-dirs", pkg) + } + genName := gc.name + "-gen" + fs := pflag.NewFlagSet(genName, pflag.ContinueOnError) + fs.AddGoFlagSet(goflag.CommandLine) // make sure we get the klog flags + klog.V(2).Infof("Running %s with args %q", + genName, dcargs) + return withinDirectory(args.root, func() error { + return asBinary(genName, func() error { + return gc.genFn(fs, dcargs) + }) + }) +} + +func resolvePackage(file string) (string, error) { + dir := path.Dir(file) + var foundPkg string + if err := withinDirectory(dir, func() error { + if p, err := golang.PackageOf("."); err != nil { + klog.Errorf("Error finding package for %s: %s", dir, err) + return err + } else { + klog.V(4).Infof("Found %s", p) + foundPkg = p + return nil + } + }); err != nil { + return "", err + } + return foundPkg, nil +} + +func withinDirectory(dir string, fn func() error) error { + if wd, err := os.Getwd(); err != nil { + return err + } else { + defer func() { + _ = os.Chdir(wd) + }() + } + if err := os.Chdir(dir); err != nil { + return err + } + return fn() +} + +func asBinary(binName string, fn func() error) error { + curr := os.Args[0] + defer func() { + os.Args[0] = curr + }() + os.Args[0] = binName + return fn() +}