Skip to content

Commit

Permalink
Rename templatesDir to templates, support templates from command line (
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielLiu1123 authored Sep 21, 2024
1 parent f407b0c commit afee959
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 19 deletions.
21 changes: 18 additions & 3 deletions pkg/cmd/generate/generate.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package generate

import (
"errors"
"github.com/DanielLiu1123/gencoder/pkg/handlebars"
"github.com/DanielLiu1123/gencoder/pkg/jsruntime"
"github.com/DanielLiu1123/gencoder/pkg/model"
Expand All @@ -16,8 +17,9 @@ import (

type generateOptions struct {
config string
commandLineProperties map[string]string // properties passed from command line
importHelper string
commandLineProperties map[string]string // properties passed from command line
commandLineTemplates string // templates passed from command line
}

func NewCmdGenerate(globalOptions *model.GlobalOptions) *cobra.Command {
Expand All @@ -38,6 +40,9 @@ func NewCmdGenerate(globalOptions *model.GlobalOptions) *cobra.Command {
# Generate code with custom import helper JavaScript file
$ gencoder generate -f myconfig.yaml --import-helper helpers.js
# Generate boilerplate code from URL with custom properties
$ gencoder generate --templates "https://github.com/DanielLiu1123/gencoder/tree/main/templates" --properties="package=com.example,author=Freeman"
`,
PreRun: func(cmd *cobra.Command, args []string) {
if len(args) > 0 {
Expand Down Expand Up @@ -65,6 +70,7 @@ func NewCmdGenerate(globalOptions *model.GlobalOptions) *cobra.Command {
c.Flags().StringVarP(&opt.config, "config", "f", globalOptions.Config, "Config file to use")
c.Flags().StringVarP(&opt.importHelper, "import-helper", "i", "", "Import helper JavaScript file, can be URL ([http|https]://...) or file path")
c.Flags().StringSliceVarP(&props, "properties", "p", []string{}, "Add properties, will override properties in config file, --properties=\"k1=v1\" --properties=\"k2=v2,k3=v3\"")
c.Flags().StringVarP(&opt.commandLineTemplates, "templates", "t", "", "Override templates directory or URL")

return c
}
Expand Down Expand Up @@ -98,9 +104,18 @@ func registerCustomHelpers(location string) {

func run(_ *cobra.Command, _ []string, opt *generateOptions, _ *model.GlobalOptions) {

cfg := util.ReadConfig(opt.config)
cfg, err := util.ReadConfig(opt.config)
isNotExist := errors.Is(err, os.ErrNotExist)
if isNotExist {
// if is not found, try to read from command line templates
if opt.commandLineTemplates == "" {
log.Fatal(err)
}
} else {
log.Fatal(err)
}

templates, err := util.LoadTemplates(cfg)
templates, err := util.LoadTemplates(cfg, opt.commandLineTemplates)
if err != nil {
log.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewCmdInit(globalOptions *model.GlobalOptions) *cobra.Command {
func run(_ *cobra.Command, _ []string, _ *initOptions, _ *model.GlobalOptions) {

// init gencoder.yaml
gencoderYaml := `templatesDir: templates
gencoderYaml := `templates: templates
databases:
- dsn: 'mysql://root:root@localhost:3306/testdb'
tables:
Expand Down
5 changes: 4 additions & 1 deletion pkg/cmd/introspect/introspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ func NewCmdIntrospect(globalOptions *model.GlobalOptions) *cobra.Command {
func run(_ *cobra.Command, _ []string, opt *introspectOptions, _ *model.GlobalOptions) {

renderContextsFunc := sync.OnceValue(func() []*model.RenderContext {
cfg := util.ReadConfig(opt.config)
cfg, err := util.ReadConfig(opt.config)
if err != nil {
log.Fatalf("failed to read config: %v", err)
}
return util.CollectRenderContexts(cfg, nil)
})

Expand Down
8 changes: 4 additions & 4 deletions pkg/model/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package model

type Config struct {
TemplatesDir string `json:"templatesDir" yaml:"templatesDir"`
Templates string `json:"templates" yaml:"templates"` // Can be a directory or URL
OutputMarker string `json:"outputMarker" yaml:"outputMarker"`
BlockMarker BlockMarker `json:"blockMarker" yaml:"blockMarker"`
Databases []*DatabaseConfig `json:"databases" yaml:"databases"`
Expand All @@ -28,11 +28,11 @@ type BlockMarker struct {
End string `json:"end" yaml:"end"`
}

func (c Config) GetTemplatesDir() string {
if c.TemplatesDir == "" {
func (c Config) GetTemplates() string {
if c.Templates == "" {
return "templates"
}
return c.TemplatesDir
return c.Templates
}

func (c Config) GetOutputMarker() string {
Expand Down
71 changes: 61 additions & 10 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bufio"
"context"
"database/sql"
"fmt"
"github.com/DanielLiu1123/gencoder/pkg/db"
"github.com/DanielLiu1123/gencoder/pkg/handlebars"
"github.com/DanielLiu1123/gencoder/pkg/model"
Expand All @@ -12,32 +13,82 @@ import (
"io/fs"
"log"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
)

// ReadConfig reads the configuration file from the given path
func ReadConfig(configPath string) *model.Config {
func ReadConfig(configPath string) (*model.Config, error) {
var cfg model.Config
file, err := os.ReadFile(configPath)
if err != nil {
log.Fatal(err)
return &cfg, err
}

var cfg model.Config
err = yaml.Unmarshal(file, &cfg)
if err != nil {
log.Fatal(err)
return &cfg, err
}

return &cfg
return &cfg, nil
}

// LoadTemplates loads all templates from the given configuration
func LoadTemplates(cfg *model.Config) ([]*model.Tpl, error) {
// LoadTemplates loads all templates from the given configuration and command line templates
func LoadTemplates(cfg *model.Config, commandLineTemplates string) ([]*model.Tpl, error) {

template := cfg.GetTemplates()
if commandLineTemplates != "" {
template = commandLineTemplates
}

var templates []*model.Tpl

err := filepath.WalkDir(cfg.GetTemplatesDir(), func(path string, d fs.DirEntry, err error) error {
// If url is provided, download templates
isGitUrl, err := regexp.Match(`^.*(github\.com)/.*`, []byte(template))
if err != nil {
return nil, err
}

if isGitUrl {
// Parse GitHub URL to extract the repo and branch (if provided)
re := regexp.MustCompile(`github\.com/([^/]+)/([^/]+)(/tree/([^/]+)/(.*))?`)
matches := re.FindStringSubmatch(template)
if matches == nil {
return nil, fmt.Errorf("invalid GitHub URL format")
}

owner := matches[1]
repo := matches[2]
branch := "main"
if matches[4] != "" {
branch = matches[4]
}
dirInRepo := matches[5]

tmpDir, err := os.MkdirTemp("", "templates")
if err != nil {
return nil, fmt.Errorf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)

cloneUrl := fmt.Sprintf("https://github.com/%s/%s.git", owner, repo)
cmd := exec.Command("git", "clone", "--branch", branch, "--depth", "1", cloneUrl, tmpDir)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to clone repository: %v", err)
}

// If a directory within the repo is specified, update the path
if dirInRepo != "" {
template = filepath.Join(tmpDir, dirInRepo)
} else {
template = tmpDir
}
}

err = filepath.WalkDir(template, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
Expand Down

0 comments on commit afee959

Please sign in to comment.