Skip to content

Commit

Permalink
Helper-gen calls defaulter-gen
Browse files Browse the repository at this point in the history
  • Loading branch information
cardil committed Jan 19, 2024
1 parent 67bcbb0 commit 5b524d1
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 134 deletions.
142 changes: 8 additions & 134 deletions staging/src/k8s.io/code-generator/pkg/codegen/helpers/deepcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
31 changes: 31 additions & 0 deletions staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go
Original file line number Diff line number Diff line change
@@ -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,
},
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,9 @@ func (g *Generator) Generate(args *Args) error {
return err
}

if err := generateDefaulter(args); err != nil {
return err
}

return nil
}
192 changes: 192 additions & 0 deletions staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go
Original file line number Diff line number Diff line change
@@ -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()
}

0 comments on commit 5b524d1

Please sign in to comment.