-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
235 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
staging/src/k8s.io/code-generator/pkg/codegen/helpers/defaulter.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
192 changes: 192 additions & 0 deletions
192
staging/src/k8s.io/code-generator/pkg/codegen/helpers/generic.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} |