From add06c6e31130855c2119f9efdda3f88ee27051f Mon Sep 17 00:00:00 2001 From: Dustin Deus Date: Thu, 25 Jan 2018 23:33:02 +0100 Subject: [PATCH] clean up, update docs --- README.md | 1 + commands/template/template.go | 124 ++++++++++++++++++++-------------- docs/debugging.md | 7 ++ main.go | 53 +++++++++++---- 4 files changed, 121 insertions(+), 64 deletions(-) create mode 100644 docs/debugging.md diff --git a/README.md b/README.md index a0dbd85..3a6fbe9 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ When you create a project template you can create a [`Survey`](/docs/templateSur * Template Surveys * Template Syntax * Git Hooks +* Debugging * Commands ## Commands diff --git a/commands/template/template.go b/commands/template/template.go index 42cf403..f1c26a0 100644 --- a/commands/template/template.go +++ b/commands/template/template.go @@ -80,6 +80,20 @@ func New(options ...Option) *Templating { ch: make(chan func(), runtime.NumCPU()), } + v.templateFuncMap = template.FuncMap{ + "toCamelCase": casee.ToCamelCase, + "toPascalCase": casee.ToPascalCase, + "toSnakeCase": casee.ToSnakeCase, + "join": strings.Join, + "uuid": func() (string, error) { + ui, err := uuid.NewV4() + if err != nil { + return "", err + } + return ui.String(), nil + }, + } + for _, o := range options { o(v) } @@ -115,6 +129,13 @@ func WithCommandData(cd *CommandData) Option { } } +// WithTemplateSurveyResults option. +func WithTemplateSurveyResults(sr map[string]interface{}) Option { + return func(t *Templating) { + t.surveyResult = sr + } +} + // cloneRepo clone a repo to the dst func (t *Templating) cloneRepo(repoURL string, dest string) error { _, err := git.PlainClone(dest, false, &git.CloneOptions{ @@ -230,6 +251,7 @@ func (t *Templating) StartCommandSurvey() error { // start command prompts err := survey.Ask(t.getQuestions(), cd) if err != nil { + logy.WithError(err).Error("command survey") return err } @@ -238,28 +260,21 @@ func (t *Templating) StartCommandSurvey() error { return nil } -func (t *Templating) startTemplateSurvey(path string) error { - surveyResults := make(map[string]interface{}) - surveys, err := ReadSurveyConfig(path) - if err == nil { - questions, err := BuildSurveys(surveys) - if err != nil { - logy.WithError(err).Error("build surveys") - return err - } - - err = survey.Ask(questions, &surveyResults) - - if err != nil { - logy.WithError(err).Error("start survey") - return err - } +func (t *Templating) startTemplateSurvey(surveys *Survey) error { + questions, err := BuildSurveys(surveys) + if err != nil { + logy.WithError(err).Error("build surveys") + return err } - t.surveys = surveys - t.surveyResult = surveyResults + t.surveyResult = map[string]interface{}{} + err = survey.Ask(questions, &t.surveyResult) + if err != nil { + logy.WithError(err).Error("start template survey") + return err + } - logy.Debugf("Survey results %+v", surveyResults) + logy.Debugf("Survey results %+v", t.surveyResult) return nil } @@ -307,24 +322,14 @@ func (t *Templating) runSurveyTemplateHooks() { // generateTempFuncs create helper funcs and getters based on the survey result func (t *Templating) generateTempFuncs() { - utilFuncMap := template.FuncMap{ - "toCamelCase": casee.ToCamelCase, - "toPascalCase": casee.ToPascalCase, - "toSnakeCase": casee.ToSnakeCase, - "join": strings.Join, - } - - utilFuncMap["uuid"] = func() (string, error) { - ui, err := uuid.NewV4() - if err != nil { - return "", err - } - return ui.String(), nil + if t.surveyResult == nil { + logy.Debug("could not generate getter functions due to empty survey results") + return } // create getter functions for the survey results for easier access for key, val := range t.surveyResult { - utilFuncMap["get"+casee.ToPascalCase(key)] = (func(v interface{}) func() interface{} { + t.templateFuncMap["get"+casee.ToPascalCase(key)] = (func(v interface{}) func() interface{} { return func() interface{} { return v } @@ -333,14 +338,13 @@ func (t *Templating) generateTempFuncs() { // create getter functions for the survey options for easier access for _, question := range t.surveys.Questions { - utilFuncMap["get"+casee.ToPascalCase(question.Name+"Question")] = (func(v Question) func() interface{} { + t.templateFuncMap["get"+casee.ToPascalCase(question.Name+"Question")] = (func(v Question) func() interface{} { return func() interface{} { return question } })(question) } - t.templateFuncMap = utilFuncMap } // Run the command @@ -360,6 +364,7 @@ func (t *Templating) Run() error { cloneSpinner.Stop() if err != nil { + logy.WithError(err).Error("clone") return err } @@ -368,9 +373,18 @@ func (t *Templating) Run() error { "path": surveyFile, }) - err = t.startTemplateSurvey(surveyFile) + surveys, err := ReadSurveyConfig(surveyFile) + if err != nil { + ctx.WithError(err).Error("read survey config") + return err + } + t.surveys = surveys + + err = t.startTemplateSurvey(surveys) if err != nil { + ctx.WithError(err).Error("start template survey") return err + } // spinner progress @@ -398,7 +412,14 @@ func (t *Templating) Run() error { walkDirErr := filepath.Walk( t.CommandData.Path, func(path string, info os.FileInfo, err error) error { + ctx := logy.WithFields(logy.Fields{ + "path": path, + "size": info.Size(), + "dir": info.IsDir(), + }) + if err != nil { + ctx.WithError(err).Error("inside walk") return err } @@ -415,12 +436,6 @@ func (t *Templating) Run() error { return skipDirErr } - ctx := logy.WithFields(logy.Fields{ - "path": path, - "size": info.Size(), - "dir": info.IsDir(), - }) - defer func() { if r := recover(); r != nil { ctx.Error("directory templating error") @@ -435,12 +450,14 @@ func (t *Templating) Run() error { if err != nil { ctx.WithError(err).Error("create template for directory") + return err } var dirNameBuffer bytes.Buffer err = tplDir.Execute(&dirNameBuffer, t.TemplateData) if err != nil { ctx.WithError(err).Error("execute template for directory") + return err } newDirectory := dirNameBuffer.String() @@ -458,6 +475,7 @@ func (t *Templating) Run() error { }) if walkDirErr != nil { + logy.WithError(walkDirErr).Error("walk dir") return walkDirErr } @@ -475,7 +493,14 @@ func (t *Templating) Run() error { // iterate through all files walkErr := filepath.Walk(t.CommandData.Path, func(path string, info os.FileInfo, err error) error { + ctx := logy.WithFields(logy.Fields{ + "path": path, + "size": info.Size(), + "dir": info.IsDir(), + }) + if err != nil { + ctx.WithError(err).Error("inside walk") return err } @@ -494,15 +519,8 @@ func (t *Templating) Run() error { return nil } - ctx := logy.WithFields(logy.Fields{ - "path": path, - "size": info.Size(), - "dir": info.IsDir(), - }) - // template file t.ch <- func() { - defer func() { if r := recover(); r != nil { ctx.Error("templating error") @@ -610,8 +628,12 @@ func (t *Templating) Run() error { logy.Debug("execute template hooks") startTimeHooks := time.Now() - // run template after hooks - t.runSurveyTemplateHooks() + + if t.surveyResult != nil { + t.runSurveyTemplateHooks() + } else { + logy.Debug("skip template survey") + } // print summary totalCloneDuration := time.Since(startTimeClone).Seconds() diff --git a/docs/debugging.md b/docs/debugging.md new file mode 100644 index 0000000..8a726b4 --- /dev/null +++ b/docs/debugging.md @@ -0,0 +1,7 @@ +# Butler debugging + +Enable different log level (debug, info, warn, error): + +``` +$ butler --logLevel=info ui +``` \ No newline at end of file diff --git a/main.go b/main.go index 2dcbc01..341250d 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "runtime" + "sort" logy "github.com/apex/log" "github.com/netzkern/butler/commands/githook" @@ -103,32 +104,41 @@ func interactiveCliMode() { } } -// WIP func cliMode() { + + type surveyResult map[string]interface{} + app := cli.NewApp() app.Name = appName app.Usage = "your personal assistent to scaffold new projects." app.Author = author app.Version = version app.Description = appDesc + + app.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "logLevel", + Value: "info", + Usage: "Log level", + EnvVar: "BUTLER_LOG_LEVEL", + }, + } app.Commands = []cli.Command{ { - Name: "template", - Aliases: []string{"t"}, - Usage: "options for task templates", - Subcommands: []cli.Command{ - { - Name: "create", - Usage: "checkout a new template", - Action: func(c *cli.Context) error { - fmt.Println("new task template: ", c.Args().First()) - return nil - }, - }, + Name: "interactive", + Aliases: []string{"ui"}, + Usage: "Enable interactive cli", + Action: func(c *cli.Context) error { + setLogLevel(c.GlobalString("logLevel")) + interactiveCliMode() + return nil }, }, } + sort.Sort(cli.FlagsByName(app.Flags)) + sort.Sort(cli.CommandsByName(app.Commands)) + app.Run(os.Args) } @@ -140,3 +150,20 @@ func main() { interactiveCliMode() } + +func setLogLevel(level string) { + switch level { + case "info": + logy.SetLevel(logy.InfoLevel) + case "debug": + logy.SetLevel(logy.DebugLevel) + case "fatal": + logy.SetLevel(logy.FatalLevel) + case "error": + logy.SetLevel(logy.ErrorLevel) + case "warn": + logy.SetLevel(logy.WarnLevel) + default: + logy.Fatalf("Invalid log level '%s'", level) + } +}