Skip to content

Commit

Permalink
updated exec handling, error reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Jeannopoulos committed Aug 4, 2020
1 parent 8791243 commit 74d4433
Show file tree
Hide file tree
Showing 9 changed files with 581 additions and 108 deletions.
252 changes: 218 additions & 34 deletions dbmeta/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"encoding/csv"
"encoding/json"
"fmt"
"github.com/smallnest/gen/utils"
"time"

"go/format"
"io/ioutil"
"os"
Expand All @@ -19,6 +22,7 @@ import (
"github.com/serenize/snaker"
)

// GenTemplate template info struct
type GenTemplate struct {
Name string
Content string
Expand Down Expand Up @@ -111,10 +115,11 @@ func (c *Config) GetTemplate(genTemplate *GenTemplate) (*template.Template, erro
"replace": replace,
"hasField": hasField,
"FmtFieldName": FmtFieldName,
"copy": FileSystemCopy,
"mkdir": Mkdir,
"touch": Touch,
"copy": c.FileSystemCopy,
"mkdir": c.Mkdir,
"touch": c.Touch,
"pwd": Pwd,
"config": c.DisplayConfig,
}

baseName := filepath.Base(genTemplate.Name)
Expand Down Expand Up @@ -376,12 +381,12 @@ func (c *Config) JSONTagOmitEmpty(name string) string {
}

// GenerateTableFile generate file from template using specific table used within templates
func (c *Config) GenerateTableFile(tableInfos map[string]*ModelInfo, tableName, templateFilename, outputDirectory, outputFileName string, formatOutput bool) string {
func (c *Config) GenerateTableFile(tableName, templateFilename, outputDirectory, outputFileName string) string {
buf := bytes.Buffer{}

buf.WriteString(fmt.Sprintf("GenerateTableFile( %s, %s, %s, %s, %t)\n", tableName, templateFilename, outputDirectory, outputFileName, formatOutput))
buf.WriteString(fmt.Sprintf("GenerateTableFile( %s, %s, %s, %)\n", tableName, templateFilename, outputDirectory, outputFileName))

tableInfo, ok := tableInfos[tableName]
tableInfo, ok := c.TableInfos[tableName]
if !ok {
buf.WriteString(fmt.Sprintf("Table: %s - No tableInfo found\n", tableName))
return buf.String()
Expand Down Expand Up @@ -409,7 +414,7 @@ func (c *Config) GenerateTableFile(tableInfos map[string]*ModelInfo, tableName,

outputFile := filepath.Join(fileOutDir, outputFileName)
buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile))
err = c.WriteTemplate(tpl, data, outputFile, formatOutput)
err = c.WriteTemplate(tpl, data, outputFile)
return buf.String()
}

Expand Down Expand Up @@ -458,7 +463,9 @@ func (c *Config) CreateContextForTableFile(tableInfo *ModelInfo) map[string]inte
}

// WriteTemplate write a template out
func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string, formatOutput bool) error {
func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string) error {
//fmt.Printf("WriteTemplate %s\n", outputFile)

if !c.Overwrite && Exists(outputFile) {
fmt.Printf("not overwriting %s\n", outputFile)
return nil
Expand All @@ -468,6 +475,13 @@ func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interfa
data[key] = value
}

dir := filepath.Dir(outputFile)
parent := filepath.Base(dir)

data["File"] = outputFile
data["Dir"] = dir
data["Parent"] = parent

data["DatabaseName"] = c.SQLDatabase
data["module"] = c.Module

Expand All @@ -492,43 +506,50 @@ func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interfa

rt, err := c.GetTemplate(genTemplate)
if err != nil {
return fmt.Errorf("Error in loading %s template, error: %v\n", genTemplate.Name, err)
return fmt.Errorf("error in loading %s template, error: %v", genTemplate.Name, err)
}
var buf bytes.Buffer
err = rt.Execute(&buf, data)
if err != nil {
return fmt.Errorf("Error in rendering %s: %s\n", genTemplate.Name, err.Error())
return fmt.Errorf("error in rendering %s: %s", genTemplate.Name, err.Error())
}

fileContents, err := c.format(genTemplate, buf.Bytes(), outputFile)
if err != nil {
return fmt.Errorf("error writing %s - error: %v", outputFile, err)
}

err = ioutil.WriteFile(outputFile, fileContents, 0777)
if err != nil {
return fmt.Errorf("error writing %s - error: %v", outputFile, err)
}

if formatOutput {
formattedSource, err := format.Source(buf.Bytes())
if c.Verbose {
fmt.Printf("writing %s\n", outputFile)
}
return nil
}

func (c *Config) format(genTemplate *GenTemplate, content []byte, outputFile string) ([]byte, error) {
extension := filepath.Ext(outputFile)
if extension == ".go" {
formattedSource, err := format.Source([]byte(content))
if err != nil {
return fmt.Errorf("Error in formatting template: %s outputfile: %s source: %s\n", genTemplate.Name, outputFile, err.Error())
return nil, fmt.Errorf("error in formatting template: %s outputfile: %s source: %s", genTemplate.Name, outputFile, err.Error())
}

fileContents := NormalizeNewlines(formattedSource)
if c.LineEndingCRLF {
fileContents = CRLFNewlines(formattedSource)
}

err = ioutil.WriteFile(outputFile, fileContents, 0777)
} else {
fileContents := NormalizeNewlines(buf.Bytes())
if c.LineEndingCRLF {
fileContents = CRLFNewlines(fileContents)
}

err = ioutil.WriteFile(outputFile, fileContents, 0777)
return fileContents, nil
}

if err != nil {
return fmt.Errorf("error writing %s - error: %v\n", outputFile, err)
fileContents := NormalizeNewlines([]byte(content))
if c.LineEndingCRLF {
fileContents = CRLFNewlines(fileContents)
}

if c.Verbose {
fmt.Printf("writing %s\n", outputFile)
}
return nil
return fileContents, nil
}

// NormalizeNewlines normalizes \r\n (windows) and \r (mac)
Expand Down Expand Up @@ -559,7 +580,7 @@ func Exists(name string) bool {
}

// GenerateFile generate file from template, non table used within templates
func (c *Config) GenerateFile(templateFilename, outputDirectory, outputFileName string, formatOutput bool, overwrite bool) string {
func (c *Config) GenerateFile(templateFilename, outputDirectory, outputFileName string, overwrite bool) string {
buf := bytes.Buffer{}
buf.WriteString(fmt.Sprintf("GenerateFile( %s, %s, %s)\n", templateFilename, outputDirectory, outputFileName))
fileOutDir := outputDirectory
Expand All @@ -579,13 +600,176 @@ func (c *Config) GenerateFile(templateFilename, outputDirectory, outputFileName

outputFile := filepath.Join(fileOutDir, outputFileName)
buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile))
err = c.WriteTemplate(tpl, data, outputFile, formatOutput)
err = c.WriteTemplate(tpl, data, outputFile)
if err != nil {
buf.WriteString(fmt.Sprintf("Error calling WriteTemplate %s -> %v\n", templateFilename, err))
}
return buf.String()
}

// DisplayConfig display config info
func (c *Config) DisplayConfig() string {

info := fmt.Sprintf(
`DisplayConfig
SQLType : %s
SQLConnStr : %s
SQLDatabase : %s
Module : %s
OutDir : %s
`, c.SQLType, c.SQLConnStr, c.SQLDatabase, c.Module, c.OutDir)

return info
}

// FileSystemCopy template command to copy files, directories and to pass --include XXX and --exclude YYY regular expressions. Files ending in .tmpl will be processed as a template.
// Files ending in .table.tmpl will be processed as a template iterating through all the tables
func (c *Config) FileSystemCopy(src, dst string, options ...string) string {
dstDir := filepath.Join(c.OutDir, dst)
opt := utils.DefaultCopyOptions()
opt.FileHandler = c.handleFile

excludePattern := ""
includePattern := ""

for _, o := range options {
if strings.HasPrefix(o, "--exclude ") {
excludePattern = o[len("--exclude "):]
}
if strings.HasPrefix(o, "--include ") {
includePattern = o[len("--include "):]
}
}

excludeRegex, _ := regexp.Compile(excludePattern)
if excludeRegex != nil {
fmt.Printf("copy excludePattern: [%s]\n", excludePattern)
}
includeRegex, _ := regexp.Compile(includePattern)
if includeRegex != nil {
fmt.Printf("copy includePattern: [%s]\n", includePattern)
}

opt.ShouldCopyDir = func(info os.FileInfo) bool {
name := info.Name()

if includeRegex != nil && includeRegex.Match([]byte(name)) {
return true
}
if excludeRegex != nil && excludeRegex.Match([]byte(name)) {
return false
}
return true
}

result, err := utils.Copy(src, dstDir, opt)
if err != nil {
return fmt.Sprintf("copy returned an error %v", err)
}
return fmt.Sprintf("copy %s %s\n%s\n", src, dstDir, result.String())
}

// Mkdir template command to mkdir under the output directory
func (c *Config) Mkdir(dst string) string {
dstDir := filepath.Join(c.OutDir, dst)

err := os.MkdirAll(dstDir, os.ModePerm)
if err != nil {
return fmt.Sprintf("mkdir returned an error %v", err)

}
return fmt.Sprintf("mkdir %s", dstDir)
}

// Touch template command to touch a file under the output directory
func (c *Config) Touch(dst string) string {
dstDir := filepath.Join(c.OutDir, dst)

_, err := os.Stat(dstDir)
if os.IsNotExist(err) {
file, err := os.Create(dstDir)
if err != nil {
return fmt.Sprintf("touch returned an error %v", err)
}
defer file.Close()
} else {
currentTime := time.Now().Local()
err = os.Chtimes(dstDir, currentTime, currentTime)
if err != nil {
return fmt.Sprintf("touch returned an error %v", err)
}
}
return fmt.Sprintf("touch %s", dstDir)
}

func (c *Config) handleFile(src, dest string, info os.FileInfo) utils.FileHandlerFunc {

if strings.HasSuffix(src, ".table.tmpl") {
//fmt.Printf("@@ HandleTableTemplateFile: src: %s dest: %s Name: %s\n", src, dest, info.Name())
return c.tableFileHandlerFunc
}
if strings.HasSuffix(src, ".tmpl") {
//fmt.Printf("@@ HandleTemplateFile: src: %s dest: %s Name: %s\n", src, dest, info.Name())
return c.fileHandlerFunc
}

return func(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) {
results.Info.WriteString(fmt.Sprintf("CopyFile: %s\n", dest))
return utils.DefaultFileCopy(src, dest, info, opt, results)
}
}

// ".tmpl"
func (c *Config) fileHandlerFunc(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) {
genTemplate := &GenTemplate{
Name: info.Name(),
Content: loadFile(src),
}

data := make(map[string]interface{})

outputFile := dest[0 : len(dest)-5]
results.Info.WriteString(fmt.Sprintf("WriteTemplate %s\n", outputFile))
return c.WriteTemplate(genTemplate, data, outputFile)
}

// ".table.tmpl"
func (c *Config) tableFileHandlerFunc(src, dest string, info os.FileInfo, opt utils.Options, results *utils.Results) (err error) {
genTemplate := &GenTemplate{
Name: info.Name(),
Content: loadFile(src),
}

outputFile := dest[0 : len(dest)-11]

dir := filepath.Dir(outputFile)
tmplateName := filepath.Base(outputFile)
// parent := filepath.Base(dir)

for tableName, tableInfo := range c.TableInfos {
data := c.CreateContextForTableFile(tableInfo)
// fileName := filepath.Join(dir, tableName+name)
name := c.ReplaceFileNamingTemplate(tableName) + filepath.Ext(tmplateName)
fileName := filepath.Join(dir, name)
results.Info.WriteString(fmt.Sprintf("WriteTableTemplate %s\n", fileName))
c.WriteTemplate(genTemplate, data, fileName)
}
return nil
}

func loadFile(src string) string {
// Read entire file content, giving us little control but
// making it very simple. No need to close the file.
content, err := ioutil.ReadFile(src)
if err != nil {
return fmt.Sprintf("error loading %s error: %v", src, err)
}

// Convert []byte to string and print to screen
text := string(content)
return text
}

// SwaggerInfoDetails swagger details
type SwaggerInfoDetails struct {
Version string
Expand Down Expand Up @@ -637,9 +821,9 @@ type Config struct {
FileNamingTemplate string
ModelNamingTemplate string
FieldNamingTemplate string
string
ContextMap map[string]interface{}
TemplateLoader TemplateLoader
ContextMap map[string]interface{}
TemplateLoader TemplateLoader
TableInfos map[string]*ModelInfo
}

// NewConfig create a new code config
Expand Down
Loading

0 comments on commit 74d4433

Please sign in to comment.