// CheckVersion returns an error if the ver is empty, contains an incorrect value or // a version number that is not compatible with the version of this repo. func CheckVersion(ver string) error { compat, err := version.Compatible(ver) if err != nil { return err } if !compat { return fmt.Errorf("version mismatch: using goagen %s to generate code that compiles with goa %s", ver, version.String()) } return nil }
// WriteHeader writes the generic generated code header. func (f *SourceFile) WriteHeader(title, pack string, imports []*ImportSpec) error { ctx := map[string]interface{}{ "Title": title, "ToolVersion": version.String(), "Pkg": pack, "Imports": imports, } if err := headerTmpl.Execute(f, ctx); err != nil { return fmt.Errorf("failed to generate contexts: %s", err) } return nil }
// spawn runs the compiled generator using the arguments initialized by Kingpin // when parsing the command line. func (m *Generator) spawn(genbin string) ([]string, error) { args := make([]string, len(m.Flags)) i := 0 for k, v := range m.Flags { args[i] = fmt.Sprintf("--%s=%s", k, v) i++ } sort.Strings(args) args = append(args, "--version="+version.String()) cmd := exec.Command(genbin, args...) out, err := cmd.CombinedOutput() if err != nil { return nil, fmt.Errorf("%s\n%s", err, string(out)) } res := strings.Split(string(out), "\n") for (len(res) > 0) && (res[len(res)-1] == "") { res = res[:len(res)-1] } return res, nil }
// spawn runs the compiled generator using the arguments initialized by Kingpin // when parsing the command line. func (m *Generator) spawn(genbin string) ([]string, error) { var args []string for k, v := range m.Flags { if k == "debug" { continue } args = append(args, fmt.Sprintf("--%s=%s", k, v)) } sort.Strings(args) args = append(args, "--version="+version.String()) args = append(args, m.CustomFlags...) cmd := exec.Command(genbin, args...) out, err := cmd.CombinedOutput() if err != nil { return nil, fmt.Errorf("%s\n%s", err, string(out)) } res := strings.Split(string(out), "\n") for (len(res) > 0) && (res[len(res)-1] == "") { res = res[:len(res)-1] } return res, nil }
. "github.com/onsi/gomega" ) var _ = Describe("Generate", func() { const testgenPackagePath = "github.com/goadesign/goa/goagen/gen_app/test_" var outDir string var files []string var genErr error BeforeEach(func() { gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] outDir = filepath.Join(gopath, "src", testgenPackagePath) err := os.MkdirAll(outDir, 0777) Ω(err).ShouldNot(HaveOccurred()) os.Args = []string{"goagen", "--out=" + outDir, "--design=foo", "--version=" + version.String()} design.GeneratedMediaTypes = make(design.MediaTypeRoot) design.ProjectedMediaTypes = make(design.MediaTypeRoot) }) JustBeforeEach(func() { files, genErr = genapp.Generate() }) AfterEach(func() { os.RemoveAll(outDir) delete(codegen.Reserved, "app") }) Context("with notest flag", func() { BeforeEach(func() {
. "github.com/onsi/gomega" ) var _ = Describe("Generate", func() { const testgenPackagePath = "github.com/goadesign/goa/goagen/gen_js/test_" var outDir string var files []string var genErr error BeforeEach(func() { gopath := filepath.SplitList(os.Getenv("GOPATH"))[0] outDir = filepath.Join(gopath, "src", testgenPackagePath) err := os.MkdirAll(outDir, 0777) Ω(err).ShouldNot(HaveOccurred()) os.Args = []string{"goagen", "--out=" + outDir, "--design=foo", "--host=baz", "--version=" + version.String()} }) JustBeforeEach(func() { files, genErr = genjs.Generate() }) AfterEach(func() { os.RemoveAll(outDir) }) Context("with a dummy API", func() { BeforeEach(func() { design.Design = &design.APIDefinition{ Name: "testapi", Title: "dummy API with no resource",
. "github.com/onsi/gomega" ) var _ = Describe("Generate", func() { var files []string var genErr error var workspace *codegen.Workspace var testPkg *codegen.Package BeforeEach(func() { var err error workspace, err = codegen.NewWorkspace("test") Ω(err).ShouldNot(HaveOccurred()) testPkg, err = workspace.NewPackage("schematest") Ω(err).ShouldNot(HaveOccurred()) os.Args = []string{"goagen", "--out=" + testPkg.Abs(), "--design=foo", "--version=" + version.String()} }) JustBeforeEach(func() { files, genErr = genschema.Generate() }) AfterEach(func() { workspace.Delete() }) Context("with a dummy API", func() { BeforeEach(func() { dslengine.Reset() apidsl.API("test api", func() { apidsl.Title("dummy API with no resource")
) var _ = Describe("version", func() { var ver string var build, oldBuild string BeforeEach(func() { build = "" }) JustBeforeEach(func() { oldBuild = version.Build if build != "" { version.Build = build } ver = version.String() version.Build = oldBuild }) Context("with the default build number", func() { It("should be properly formatted", func() { Ω(ver).Should(HavePrefix("v")) }) It("returns the default version", func() { Ω(ver).Should(HaveSuffix(".0-dirty")) }) }) Context("with an overridden build number", func() { BeforeEach(func() {
. "github.com/onsi/gomega" ) var _ = Describe("Generate", func() { var workspace *codegen.Workspace var outDir string var files []string var genErr error BeforeEach(func() { var err error workspace, err = codegen.NewWorkspace("test") Ω(err).ShouldNot(HaveOccurred()) outDir, err = ioutil.TempDir(filepath.Join(workspace.Path, "src"), "") Ω(err).ShouldNot(HaveOccurred()) os.Args = []string{"goagen", "--out=" + outDir, "--design=foo", "--version=" + version.String()} }) JustBeforeEach(func() { design.GeneratedMediaTypes = make(design.MediaTypeRoot) design.ProjectedMediaTypes = make(design.MediaTypeRoot) files, genErr = genapp.Generate() }) AfterEach(func() { workspace.Delete() delete(codegen.Reserved, "app") }) Context("with a dummy API", func() { BeforeEach(func() {
func main() { var ( files []string err error terminatedByUser bool ) // rootCmd is the base command used when goagen is called with no argument. rootCmd := &cobra.Command{ Use: "goagen", Short: "goa code generation tool", Long: `The goagen tool generates artifacts from a goa service design package. Each command supported by the tool produces a specific type of artifacts. For example the "app" command generates the code that supports the service controllers. The "bootstrap" command runs the "app", "main", "client" and "swagger" commands generating the controllers supporting code and main skeleton code (if not already present) as well as a client package and tool and the Swagger specification for the API. `} var ( designPkg string debug bool ) rootCmd.PersistentFlags().StringP("out", "o", ".", "output directory") rootCmd.PersistentFlags().StringVarP(&designPkg, "design", "d", "", "design package import path") rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enable debug mode, does not cleanup temporary files.") // versionCmd implements the "version" command versionCmd := &cobra.Command{ Use: "version", Short: "Print the version number of goagen", Run: func(cmd *cobra.Command, args []string) { fmt.Println("goagen " + version.String() + "\nThe goa generation tool.") }, } rootCmd.AddCommand(versionCmd) // appCmd implements the "app" command. var ( pkg string notest bool ) appCmd := &cobra.Command{ Use: "app", Short: "Generate application code", Run: func(c *cobra.Command, _ []string) { files, err = run("genapp", c) }, } appCmd.Flags().StringVar(&pkg, "pkg", "app", "Name of generated Go package containing controllers supporting code (contexts, media types, user types etc.)") appCmd.Flags().BoolVar(¬est, "notest", false, "Prevent generation of test helpers") rootCmd.AddCommand(appCmd) // mainCmd implements the "main" command. var ( force bool ) mainCmd := &cobra.Command{ Use: "main", Short: "Generate application scaffolding", Run: func(c *cobra.Command, _ []string) { files, err = run("genmain", c) }, } mainCmd.Flags().BoolVar(&force, "force", false, "overwrite existing files") rootCmd.AddCommand(mainCmd) // clientCmd implements the "client" command. var ( toolDir, tool string notool bool ) clientCmd := &cobra.Command{ Use: "client", Short: "Generate client package and tool", Run: func(c *cobra.Command, _ []string) { files, err = run("genclient", c) }, } clientCmd.Flags().StringVar(&pkg, "pkg", "client", "Name of generated client Go package") clientCmd.Flags().StringVar(&toolDir, "tooldir", "tool", "Name of generated tool directory") clientCmd.Flags().StringVar(&tool, "tool", "[API-name]-cli", "Name of generated tool") clientCmd.Flags().BoolVar(¬ool, "notool", false, "Prevent generation of cli tool") rootCmd.AddCommand(clientCmd) // swaggerCmd implements the "swagger" command. swaggerCmd := &cobra.Command{ Use: "swagger", Short: "Generate Swagger", Run: func(c *cobra.Command, _ []string) { files, err = run("genswagger", c) }, } rootCmd.AddCommand(swaggerCmd) // jsCmd implements the "js" command. var ( timeout = time.Duration(20) * time.Second scheme, host string noexample bool ) jsCmd := &cobra.Command{ Use: "js", Short: "Generate JavaScript client", Run: func(c *cobra.Command, _ []string) { files, err = run("genjs", c) }, } jsCmd.Flags().DurationVar(&timeout, "timeout", timeout, `the duration before the request times out.`) jsCmd.Flags().StringVar(&scheme, "scheme", "", `the URL scheme used to make requests to the API, defaults to the scheme defined in the API design if any.`) jsCmd.Flags().StringVar(&host, "host", "", `the API hostname, defaults to the hostname defined in the API design if any`) jsCmd.Flags().BoolVar(&noexample, "noexample", false, `Skip generation of example HTML and controller`) rootCmd.AddCommand(jsCmd) // schemaCmd implements the "schema" command. schemaCmd := &cobra.Command{ Use: "schema", Short: "Generate JSON Schema", Run: func(c *cobra.Command, _ []string) { files, err = run("genschema", c) }, } rootCmd.AddCommand(schemaCmd) // genCmd implements the "gen" command. var ( pkgPath string ) genCmd := &cobra.Command{ Use: "gen", Short: "Run third-party generator", Run: func(c *cobra.Command, _ []string) { files, err = runGen(c) }, } genCmd.Flags().StringVar(&pkgPath, "pkg-path", "", "Package import path of generator. The package must implement the Generate global function.") rootCmd.AddCommand(genCmd) // boostrapCmd implements the "bootstrap" command. bootCmd := &cobra.Command{ Use: "bootstrap", Short: `Equivalent to running the "app", "main", "client" and "swagger" commands.`, Run: func(c *cobra.Command, a []string) { appCmd.Run(c, a) if err != nil { return } prev := files mainCmd.Run(c, a) if err != nil { return } prev = append(prev, files...) clientCmd.Run(c, a) if err != nil { return } prev = append(prev, files...) swaggerCmd.Run(c, a) files = append(prev, files...) }, } bootCmd.Flags().AddFlagSet(appCmd.Flags()) bootCmd.Flags().AddFlagSet(mainCmd.Flags()) bootCmd.Flags().AddFlagSet(clientCmd.Flags()) bootCmd.Flags().AddFlagSet(swaggerCmd.Flags()) rootCmd.AddCommand(bootCmd) // cmdsCmd implements the commands command // It lists all the commands and flags in JSON to enable shell integrations. cmdsCmd := &cobra.Command{ Use: "commands", Short: "Lists all commands and flags in JSON", Run: func(c *cobra.Command, _ []string) { runCommands(rootCmd) }, } rootCmd.AddCommand(cmdsCmd) // Now proceed with code generation cleanup := func() { for _, f := range files { os.RemoveAll(f) } } go utils.Catch(nil, func() { terminatedByUser = true }) rootCmd.Execute() if terminatedByUser { cleanup() return } if err != nil { cleanup() fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } rels := make([]string, len(files)) cd, _ := os.Getwd() for i, f := range files { r, err := filepath.Rel(cd, f) if err == nil { rels[i] = r } else { rels[i] = f } } fmt.Println(strings.Join(rels, "\n")) }