From 96689a5c319f720368491226f034d0ff9585217c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 11 Apr 2018 20:17:28 +0200 Subject: [PATCH] commands: Make commands.Execute return a Response object We have no global `Hugo` object no more (yay!), and there are some external tools that depends on that value. These tools need to use get that value from `Response.Result`. Note that `commands.Execute` now also takes the arguments as a string slice. This should also make it easier to use, not having to modify `os.Args`. This commit also wraps up this particular issue. Phew! Test coverage in /commands before: 14.4% Now: 53.5% Still work to do, now it is at least possible. Closes #4598 --- commands/commands.go | 12 ++++++---- commands/commands_test.go | 20 +++++++++++++++- commands/hugo.go | 50 ++++++++++++++++++++++++++++++++------- main.go | 15 +++++------- 4 files changed, 75 insertions(+), 22 deletions(-) diff --git a/commands/commands.go b/commands/commands.go index aad47abcd..86486d2a4 100644 --- a/commands/commands.go +++ b/commands/commands.go @@ -22,10 +22,10 @@ import ( ) // newHugoCompleteCmd builds the complete set of Hugo CLI commands. -func newHugoCompleteCmd() *cobra.Command { - hugoCmd := newHugoCmd().getCommand() - addAllCommands(hugoCmd) - return hugoCmd +func newHugoCompleteCmd() *hugoCmd { + h := newHugoCmd() + addAllCommands(h.getCommand()) + return h } // addAllCommands adds child commands to the root command HugoCmd. @@ -81,6 +81,9 @@ func (c *baseCmd) flagsToConfig(cfg config.Provider) { type hugoCmd struct { *baseBuilderCmd + + // Need to get the sites once built. + c *commandeer } func newHugoCmd() *hugoCmd { @@ -107,6 +110,7 @@ Complete documentation is available at http://gohugo.io/.`, if err != nil { return err } + cc.c = c return c.build() }, diff --git a/commands/commands_test.go b/commands/commands_test.go index 7e590bea0..ea9d3f74d 100644 --- a/commands/commands_test.go +++ b/commands/commands_test.go @@ -23,6 +23,24 @@ import ( "github.com/stretchr/testify/require" ) +func TestExecute(t *testing.T) { + + assert := require.New(t) + + dir, err := createSimpleTestSite(t) + assert.NoError(err) + + defer func() { + os.RemoveAll(dir) + }() + + resp := Execute([]string{"-s=" + dir}) + assert.NoError(resp.Err) + result := resp.Result + assert.True(len(result.Sites) == 1) + assert.True(len(result.Sites[0].RegularPages) == 1) +} + func TestCommands(t *testing.T) { assert := require.New(t) @@ -72,7 +90,7 @@ func TestCommands(t *testing.T) { for _, test := range tests { - hugoCmd := newHugoCompleteCmd() + hugoCmd := newHugoCompleteCmd().getCommand() test.flags = append(test.flags, "--quiet") hugoCmd.SetArgs(append(test.commands, test.flags...)) diff --git a/commands/hugo.go b/commands/hugo.go index 4639c0f3b..c1cf9833f 100644 --- a/commands/hugo.go +++ b/commands/hugo.go @@ -51,20 +51,55 @@ import ( jww "github.com/spf13/jwalterweatherman" ) -// TODO(bep) cli refactor consider a exported Hugo() method to fix the API +// The Response value from Execute. +type Response struct { + // The build Result will only be set in the hugo build command. + Result *hugolib.HugoSites + + // Err is set when the command failed to execute. + Err error + + // The command that was executed. + Cmd *cobra.Command +} + +func (r Response) IsUserError() bool { + return r.Err != nil && isUserError(r.Err) +} // Execute adds all child commands to the root command HugoCmd and sets flags appropriately. -func Execute() { +// The args are usually filled with os.Args[1:]. +func Execute(args []string) Response { hugoCmd := newHugoCompleteCmd() + cmd := hugoCmd.getCommand() + cmd.SetArgs(args) - if c, err := hugoCmd.ExecuteC(); err != nil { - if isUserError(err) { - c.Println("") - c.Println(c.UsageString()) + c, err := cmd.ExecuteC() + + var resp Response + + if c == cmd && hugoCmd.c != nil { + // Root command executed + resp.Result = hugoCmd.c.hugo + } + + if err == nil { + errCount := jww.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError) + if errCount > 0 { + err = fmt.Errorf("logged %d errors", errCount) + } else if resp.Result != nil { + errCount = resp.Result.Log.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError) + if errCount > 0 { + err = fmt.Errorf("logged %d errors", errCount) + } } - os.Exit(-1) } + + resp.Err = err + resp.Cmd = c + + return resp } // InitializeConfig initializes a config file with sensible default configuration flags. @@ -612,7 +647,6 @@ func (c *commandeer) resetAndBuildSites() (err error) { func (c *commandeer) initSites() error { if c.hugo != nil { - // TODO(bep) cli refactor check c.hugo.Cfg = c.Cfg c.hugo.Log.ResetLogCounters() return nil diff --git a/main.go b/main.go index 3baf6c275..d04012111 100644 --- a/main.go +++ b/main.go @@ -19,22 +19,19 @@ import ( "os" "github.com/gohugoio/hugo/commands" - jww "github.com/spf13/jwalterweatherman" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) - commands.Execute() + resp := commands.Execute(os.Args[1:]) - if jww.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError) > 0 { + if resp.Err != nil { + if resp.IsUserError() { + resp.Cmd.Println("") + resp.Cmd.Println(resp.Cmd.UsageString()) + } os.Exit(-1) } - // TODO(bep) cli refactor - /*if commands.Hugo != nil { - if commands.Hugo.Log.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError) > 0 { - os.Exit(-1) - } - }*/ }