Added folder flag and import flag

* Generates files into specified folder
* Changed the order in which things are generated
This commit is contained in:
Patrick O'brien 2016-03-02 00:20:13 +10:00
parent 7539febd22
commit 9eb087be80
4 changed files with 103 additions and 62 deletions

View file

@ -44,9 +44,19 @@ func boilRun(cmd *cobra.Command, args []string) {
// Prepend "struct" command to templateNames slice so it sits at top of sort // Prepend "struct" command to templateNames slice so it sits at top of sort
templateNames = append([]string{"struct"}, templateNames...) templateNames = append([]string{"struct"}, templateNames...)
for i := 0; i < len(cmdData.TablesInfo); i++ {
data := tplData{
TableName: cmdData.TableNames[i],
TableData: cmdData.TablesInfo[i],
}
var out [][]byte
// Loop through and generate every command template (excluding skipTemplates) // Loop through and generate every command template (excluding skipTemplates)
for _, n := range templateNames { for _, n := range templateNames {
err := outHandler(generateTemplate(n)) out = append(out, generateTemplate(n, &data))
}
err := outHandler(out, &data)
if err != nil { if err != nil {
errorQuit(err) errorQuit(err)
} }

View file

@ -18,8 +18,9 @@ type CobraRunFunc func(cmd *cobra.Command, args []string)
type CmdData struct { type CmdData struct {
TablesInfo [][]dbdrivers.DBTable TablesInfo [][]dbdrivers.DBTable
TableNames []string TableNames []string
PkgName string
OutFolder string
DBDriver dbdrivers.DBDriver DBDriver dbdrivers.DBDriver
OutFile *os.File
} }
// tplData is used to pass data to the template // tplData is used to pass data to the template
@ -37,30 +38,56 @@ func errorQuit(err error) {
// defaultRun is the default function passed to the commands cobra.Command.Run. // defaultRun is the default function passed to the commands cobra.Command.Run.
// It will generate the specific commands template and send it to outHandler for output. // It will generate the specific commands template and send it to outHandler for output.
func defaultRun(cmd *cobra.Command, args []string) { func defaultRun(cmd *cobra.Command, args []string) {
err := outHandler(generateTemplate(cmd.Name())) // Generate the template for every table
for i := 0; i < len(cmdData.TablesInfo); i++ {
data := tplData{
TableName: cmdData.TableNames[i],
TableData: cmdData.TablesInfo[i],
}
// outHandler takes a slice of byte slices, so append the Template
// execution output to a [][]byte before sending it to outHandler.
out := [][]byte{
0: generateTemplate(cmd.Name(), &data),
}
err := outHandler(out, &data)
if err != nil { if err != nil {
errorQuit(fmt.Errorf("Unable to generate the template for command %s: %s", cmd.Name(), err)) errorQuit(fmt.Errorf("Unable to generate the template for command %s: %s", cmd.Name(), err))
} }
} }
}
// outHandler loops over the slice of byte slices, outputting them to either // outHandler loops over the slice of byte slices, outputting them to either
// the OutFile if it is specified with a flag, or to Stdout if no flag is specified. // the OutFile if it is specified with a flag, or to Stdout if no flag is specified.
func outHandler(data [][]byte) error { func outHandler(output [][]byte, data *tplData) error {
nl := []byte{'\n'} nl := []byte{'\n'}
// Use stdout if no outfile is specified if cmdData.OutFolder == "" {
var out *os.File for _, v := range output {
if cmdData.OutFile == nil { if _, err := os.Stdout.Write(v); err != nil {
out = os.Stdout
} else {
out = cmdData.OutFile
}
for _, v := range data {
if _, err := out.Write(v); err != nil {
return err return err
} }
if _, err := out.Write(nl); err != nil {
if _, err := os.Stdout.Write(nl); err != nil {
return err
}
}
} else { // If not using stdout, attempt to create the model file.
path := cmdData.OutFolder + "/" + data.TableName + ".go"
out, err := os.Create(path)
if err != nil {
errorQuit(fmt.Errorf("Unable to create output file %s: %s", path, err))
}
// Combine the slice of slice into a single byte slice.
var newOutput []byte
for _, v := range output {
newOutput = append(newOutput, v...)
newOutput = append(newOutput, nl...)
}
if _, err := out.Write(newOutput); err != nil {
return err return err
} }
} }

View file

@ -35,7 +35,8 @@ var SQLBoiler = &cobra.Command{
func init() { func init() {
SQLBoiler.PersistentFlags().StringP("driver", "d", "", "The name of the driver in your config.toml (mandatory)") SQLBoiler.PersistentFlags().StringP("driver", "d", "", "The name of the driver in your config.toml (mandatory)")
SQLBoiler.PersistentFlags().StringP("table", "t", "", "A comma seperated list of table names") SQLBoiler.PersistentFlags().StringP("table", "t", "", "A comma seperated list of table names")
SQLBoiler.PersistentFlags().StringP("out", "o", "", "The name of the output file") SQLBoiler.PersistentFlags().StringP("folder", "f", "", "The name of the output folder. If not specified will output to stdout")
SQLBoiler.PersistentFlags().StringP("pkgname", "p", "model", "The name you wish to assign to your generated package")
SQLBoiler.PersistentPreRun = sqlBoilerPreRun SQLBoiler.PersistentPreRun = sqlBoilerPreRun
SQLBoiler.PersistentPostRun = sqlBoilerPostRun SQLBoiler.PersistentPostRun = sqlBoilerPostRun
@ -46,7 +47,6 @@ func init() {
// sqlBoilerPostRun cleans up the output file and database connection once // sqlBoilerPostRun cleans up the output file and database connection once
// all commands are finished running. // all commands are finished running.
func sqlBoilerPostRun(cmd *cobra.Command, args []string) { func sqlBoilerPostRun(cmd *cobra.Command, args []string) {
cmdData.OutFile.Close()
cmdData.DBDriver.Close() cmdData.DBDriver.Close()
} }
@ -74,8 +74,11 @@ func sqlBoilerPreRun(cmd *cobra.Command, args []string) {
// Initialize the cmdData.TablesInfo // Initialize the cmdData.TablesInfo
initTablesInfo() initTablesInfo()
// Initialize the package name
initPkgName()
// Initialize the cmdData.OutFile // Initialize the cmdData.OutFile
initOutFile() initOutFolder()
// Initialize the templates // Initialize the templates
templates, err = initTemplates() templates, err = initTemplates()
@ -153,18 +156,23 @@ func initTablesInfo() {
} }
} }
// Initialize the package name provided by the flag
func initPkgName() {
cmdData.PkgName = SQLBoiler.PersistentFlags().Lookup("pkgname").Value.String()
}
// initOutFile opens a file handle to the file name specified by the out flag. // initOutFile opens a file handle to the file name specified by the out flag.
// If no file name is provided, out will remain nil and future output will be // If no file name is provided, out will remain nil and future output will be
// piped to Stdout instead of to a file. // piped to Stdout instead of to a file.
func initOutFile() { func initOutFolder() {
// open the out file filehandle // open the out file filehandle
outf := SQLBoiler.PersistentFlags().Lookup("out").Value.String() cmdData.OutFolder = SQLBoiler.PersistentFlags().Lookup("folder").Value.String()
if outf != "" { if cmdData.OutFolder == "" {
var err error return
cmdData.OutFile, err = os.Create(outf)
if err != nil {
errorQuit(fmt.Errorf("Unable to obtain output file handle: %s", err))
} }
if err := os.MkdirAll(cmdData.OutFolder, os.ModePerm); err != nil {
errorQuit(fmt.Errorf("Unable to make output folder: %s", err))
} }
} }

View file

@ -11,53 +11,49 @@ import (
) )
// generateTemplate generates the template associated to the passed in command name. // generateTemplate generates the template associated to the passed in command name.
func generateTemplate(commandName string) [][]byte { func generateTemplate(commandName string, data *tplData) []byte {
var template *template.Template template := getTemplate(commandName)
// Find the template that matches the passed in command name
for _, t := range templates {
if t.Name() == commandName+".tpl" {
template = t
break
}
}
if template == nil { if template == nil {
errorQuit(fmt.Errorf("Unable to find the template: %s", commandName+".tpl")) errorQuit(fmt.Errorf("Unable to find the template: %s", commandName+".tpl"))
} }
outputs, err := processTemplate(template) output, err := processTemplate(template, data)
if err != nil { if err != nil {
errorQuit(fmt.Errorf("Unable to process the template: %s", err)) errorQuit(fmt.Errorf("Unable to process the template: %s", err))
} }
return outputs return output
} }
// processTemplate takes a template and returns a slice of byte slices. // getTemplate returns a pointer to the template matching the passed in name
// Each byte slice in the slice of bytes is the output of the template execution. func getTemplate(name string) *template.Template {
func processTemplate(t *template.Template) ([][]byte, error) { var tpl *template.Template
var outputs [][]byte
for i := 0; i < len(cmdData.TablesInfo); i++ { // Find the template that matches the passed in template name
data := tplData{ for _, t := range templates {
TableName: cmdData.TableNames[i], if t.Name() == name+".tpl" {
TableData: cmdData.TablesInfo[i], tpl = t
break
}
} }
return tpl
}
// processTemplate takes a template and returns the output of the template execution.
func processTemplate(t *template.Template, data *tplData) ([]byte, error) {
var buf bytes.Buffer var buf bytes.Buffer
if err := t.Execute(&buf, data); err != nil { if err := t.Execute(&buf, data); err != nil {
return nil, err return nil, err
} }
out, err := format.Source(buf.Bytes()) output, err := format.Source(buf.Bytes())
if err != nil { if err != nil {
return nil, err return nil, err
} }
outputs = append(outputs, out) return output, nil
}
return outputs, nil
} }
// it into a go styled object variable name of "ColumnName". // it into a go styled object variable name of "ColumnName".