Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / k8s.io / gengo / args / args.go
1 /*
2 Copyright 2015 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 // Package args has common command-line flags for generation programs.
18 package args
19
20 import (
21         "bytes"
22         goflag "flag"
23         "fmt"
24         "io/ioutil"
25         "os"
26         "path"
27         "path/filepath"
28         "strconv"
29         "strings"
30         "time"
31
32         "k8s.io/gengo/generator"
33         "k8s.io/gengo/namer"
34         "k8s.io/gengo/parser"
35         "k8s.io/gengo/types"
36
37         "github.com/spf13/pflag"
38 )
39
40 // Default returns a defaulted GeneratorArgs. You may change the defaults
41 // before calling AddFlags.
42 func Default() *GeneratorArgs {
43         return &GeneratorArgs{
44                 OutputBase:                 DefaultSourceTree(),
45                 GoHeaderFilePath:           filepath.Join(DefaultSourceTree(), "k8s.io/gengo/boilerplate/boilerplate.go.txt"),
46                 GeneratedBuildTag:          "ignore_autogenerated",
47                 GeneratedByCommentTemplate: "// Code generated by GENERATOR_NAME. DO NOT EDIT.",
48                 defaultCommandLineFlags:    true,
49         }
50 }
51
52 // GeneratorArgs has arguments that are passed to generators.
53 type GeneratorArgs struct {
54         // Which directories to parse.
55         InputDirs []string
56
57         // Source tree to write results to.
58         OutputBase string
59
60         // Package path within the source tree.
61         OutputPackagePath string
62
63         // Output file name.
64         OutputFileBaseName string
65
66         // Where to get copyright header text.
67         GoHeaderFilePath string
68
69         // If GeneratedByCommentTemplate is set, generate a "Code generated by" comment
70         // below the bloilerplate, of the format defined by this string.
71         // Any instances of "GENERATOR_NAME" will be replaced with the name of the code generator.
72         GeneratedByCommentTemplate string
73
74         // If true, only verify, don't write anything.
75         VerifyOnly bool
76
77         // GeneratedBuildTag is the tag used to identify code generated by execution
78         // of this type. Each generator should use a different tag, and different
79         // groups of generators (external API that depends on Kube generations) should
80         // keep tags distinct as well.
81         GeneratedBuildTag string
82
83         // Any custom arguments go here
84         CustomArgs interface{}
85
86         // Whether to use default command line flags
87         defaultCommandLineFlags bool
88 }
89
90 // WithoutDefaultFlagParsing disables implicit addition of command line flags and parsing.
91 func (g *GeneratorArgs) WithoutDefaultFlagParsing() *GeneratorArgs {
92         g.defaultCommandLineFlags = false
93         return g
94 }
95
96 func (g *GeneratorArgs) AddFlags(fs *pflag.FlagSet) {
97         fs.StringSliceVarP(&g.InputDirs, "input-dirs", "i", g.InputDirs, "Comma-separated list of import paths to get input types from.")
98         fs.StringVarP(&g.OutputBase, "output-base", "o", g.OutputBase, "Output base; defaults to $GOPATH/src/ or ./ if $GOPATH is not set.")
99         fs.StringVarP(&g.OutputPackagePath, "output-package", "p", g.OutputPackagePath, "Base package path.")
100         fs.StringVarP(&g.OutputFileBaseName, "output-file-base", "O", g.OutputFileBaseName, "Base name (without .go suffix) for output files.")
101         fs.StringVarP(&g.GoHeaderFilePath, "go-header-file", "h", g.GoHeaderFilePath, "File containing boilerplate header text. The string YEAR will be replaced with the current 4-digit year.")
102         fs.BoolVar(&g.VerifyOnly, "verify-only", g.VerifyOnly, "If true, only verify existing output, do not write anything.")
103         fs.StringVar(&g.GeneratedBuildTag, "build-tag", g.GeneratedBuildTag, "A Go build tag to use to identify files generated by this command. Should be unique.")
104 }
105
106 // LoadGoBoilerplate loads the boilerplate file passed to --go-header-file.
107 func (g *GeneratorArgs) LoadGoBoilerplate() ([]byte, error) {
108         b, err := ioutil.ReadFile(g.GoHeaderFilePath)
109         if err != nil {
110                 return nil, err
111         }
112         b = bytes.Replace(b, []byte("YEAR"), []byte(strconv.Itoa(time.Now().Year())), -1)
113
114         if g.GeneratedByCommentTemplate != "" {
115                 if len(b) != 0 {
116                         b = append(b, byte('\n'))
117                 }
118                 generatorName := path.Base(os.Args[0])
119                 generatedByComment := strings.Replace(g.GeneratedByCommentTemplate, "GENERATOR_NAME", generatorName, -1)
120                 s := fmt.Sprintf("%s\n\n", generatedByComment)
121                 b = append(b, []byte(s)...)
122         }
123         return b, nil
124 }
125
126 // NewBuilder makes a new parser.Builder and populates it with the input
127 // directories.
128 func (g *GeneratorArgs) NewBuilder() (*parser.Builder, error) {
129         b := parser.New()
130         // Ignore all auto-generated files.
131         b.AddBuildTags(g.GeneratedBuildTag)
132
133         for _, d := range g.InputDirs {
134                 var err error
135                 if strings.HasSuffix(d, "/...") {
136                         err = b.AddDirRecursive(strings.TrimSuffix(d, "/..."))
137                 } else {
138                         err = b.AddDir(d)
139                 }
140                 if err != nil {
141                         return nil, fmt.Errorf("unable to add directory %q: %v", d, err)
142                 }
143         }
144         return b, nil
145 }
146
147 // InputIncludes returns true if the given package is a (sub) package of one of
148 // the InputDirs.
149 func (g *GeneratorArgs) InputIncludes(p *types.Package) bool {
150         for _, dir := range g.InputDirs {
151                 d := dir
152                 if strings.HasSuffix(d, "...") {
153                         d = strings.TrimSuffix(d, "...")
154                 }
155                 if strings.HasPrefix(p.Path, d) {
156                         return true
157                 }
158         }
159         return false
160 }
161
162 // DefaultSourceTree returns the /src directory of the first entry in $GOPATH.
163 // If $GOPATH is empty, it returns "./". Useful as a default output location.
164 func DefaultSourceTree() string {
165         paths := strings.Split(os.Getenv("GOPATH"), string(filepath.ListSeparator))
166         if len(paths) > 0 && len(paths[0]) > 0 {
167                 return filepath.Join(paths[0], "src")
168         }
169         return "./"
170 }
171
172 // Execute implements main().
173 // If you don't need any non-default behavior, use as:
174 // args.Default().Execute(...)
175 func (g *GeneratorArgs) Execute(nameSystems namer.NameSystems, defaultSystem string, pkgs func(*generator.Context, *GeneratorArgs) generator.Packages) error {
176         if g.defaultCommandLineFlags {
177                 g.AddFlags(pflag.CommandLine)
178                 pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
179                 pflag.Parse()
180         }
181
182         b, err := g.NewBuilder()
183         if err != nil {
184                 return fmt.Errorf("Failed making a parser: %v", err)
185         }
186
187         c, err := generator.NewContext(b, nameSystems, defaultSystem)
188         if err != nil {
189                 return fmt.Errorf("Failed making a context: %v", err)
190         }
191
192         c.Verify = g.VerifyOnly
193         packages := pkgs(c, g)
194         if err := c.ExecutePackages(g.OutputBase, packages); err != nil {
195                 return fmt.Errorf("Failed executing generator: %v", err)
196         }
197
198         return nil
199 }