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
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)
for _, n := range templateNames {
err := outHandler(generateTemplate(n))
out = append(out, generateTemplate(n, &data))
}
err := outHandler(out, &data)
if err != nil {
errorQuit(err)
}

View file

@ -18,8 +18,9 @@ type CobraRunFunc func(cmd *cobra.Command, args []string)
type CmdData struct {
TablesInfo [][]dbdrivers.DBTable
TableNames []string
PkgName string
OutFolder string
DBDriver dbdrivers.DBDriver
OutFile *os.File
}
// 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.
// It will generate the specific commands template and send it to outHandler for output.
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 {
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
// 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'}
// Use stdout if no outfile is specified
var out *os.File
if cmdData.OutFile == nil {
out = os.Stdout
} else {
out = cmdData.OutFile
}
for _, v := range data {
if _, err := out.Write(v); err != nil {
if cmdData.OutFolder == "" {
for _, v := range output {
if _, err := os.Stdout.Write(v); err != nil {
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
}
}

View file

@ -35,7 +35,8 @@ var SQLBoiler = &cobra.Command{
func init() {
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("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.PersistentPostRun = sqlBoilerPostRun
@ -46,7 +47,6 @@ func init() {
// sqlBoilerPostRun cleans up the output file and database connection once
// all commands are finished running.
func sqlBoilerPostRun(cmd *cobra.Command, args []string) {
cmdData.OutFile.Close()
cmdData.DBDriver.Close()
}
@ -74,8 +74,11 @@ func sqlBoilerPreRun(cmd *cobra.Command, args []string) {
// Initialize the cmdData.TablesInfo
initTablesInfo()
// Initialize the package name
initPkgName()
// Initialize the cmdData.OutFile
initOutFile()
initOutFolder()
// Initialize the templates
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.
// If no file name is provided, out will remain nil and future output will be
// piped to Stdout instead of to a file.
func initOutFile() {
func initOutFolder() {
// open the out file filehandle
outf := SQLBoiler.PersistentFlags().Lookup("out").Value.String()
if outf != "" {
var err error
cmdData.OutFile, err = os.Create(outf)
if err != nil {
errorQuit(fmt.Errorf("Unable to obtain output file handle: %s", err))
cmdData.OutFolder = SQLBoiler.PersistentFlags().Lookup("folder").Value.String()
if cmdData.OutFolder == "" {
return
}
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.
func generateTemplate(commandName string) [][]byte {
var template *template.Template
// Find the template that matches the passed in command name
for _, t := range templates {
if t.Name() == commandName+".tpl" {
template = t
break
}
}
func generateTemplate(commandName string, data *tplData) []byte {
template := getTemplate(commandName)
if template == nil {
errorQuit(fmt.Errorf("Unable to find the template: %s", commandName+".tpl"))
}
outputs, err := processTemplate(template)
output, err := processTemplate(template, data)
if err != nil {
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.
// Each byte slice in the slice of bytes is the output of the template execution.
func processTemplate(t *template.Template) ([][]byte, error) {
var outputs [][]byte
for i := 0; i < len(cmdData.TablesInfo); i++ {
data := tplData{
TableName: cmdData.TableNames[i],
TableData: cmdData.TablesInfo[i],
// getTemplate returns a pointer to the template matching the passed in name
func getTemplate(name string) *template.Template {
var tpl *template.Template
// Find the template that matches the passed in template name
for _, t := range templates {
if t.Name() == name+".tpl" {
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
if err := t.Execute(&buf, data); err != nil {
return nil, err
}
out, err := format.Source(buf.Bytes())
output, err := format.Source(buf.Bytes())
if err != nil {
return nil, err
}
outputs = append(outputs, out)
}
return outputs, nil
return output, nil
}
// it into a go styled object variable name of "ColumnName".