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
This commit is contained in:
Bjørn Erik Pedersen 2018-04-11 20:17:28 +02:00
parent e7010c1b62
commit 96689a5c31
No known key found for this signature in database
GPG key ID: 330E6E2BD4859D8F
4 changed files with 75 additions and 22 deletions

View file

@ -22,10 +22,10 @@ import (
) )
// newHugoCompleteCmd builds the complete set of Hugo CLI commands. // newHugoCompleteCmd builds the complete set of Hugo CLI commands.
func newHugoCompleteCmd() *cobra.Command { func newHugoCompleteCmd() *hugoCmd {
hugoCmd := newHugoCmd().getCommand() h := newHugoCmd()
addAllCommands(hugoCmd) addAllCommands(h.getCommand())
return hugoCmd return h
} }
// addAllCommands adds child commands to the root command HugoCmd. // addAllCommands adds child commands to the root command HugoCmd.
@ -81,6 +81,9 @@ func (c *baseCmd) flagsToConfig(cfg config.Provider) {
type hugoCmd struct { type hugoCmd struct {
*baseBuilderCmd *baseBuilderCmd
// Need to get the sites once built.
c *commandeer
} }
func newHugoCmd() *hugoCmd { func newHugoCmd() *hugoCmd {
@ -107,6 +110,7 @@ Complete documentation is available at http://gohugo.io/.`,
if err != nil { if err != nil {
return err return err
} }
cc.c = c
return c.build() return c.build()
}, },

View file

@ -23,6 +23,24 @@ import (
"github.com/stretchr/testify/require" "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) { func TestCommands(t *testing.T) {
assert := require.New(t) assert := require.New(t)
@ -72,7 +90,7 @@ func TestCommands(t *testing.T) {
for _, test := range tests { for _, test := range tests {
hugoCmd := newHugoCompleteCmd() hugoCmd := newHugoCompleteCmd().getCommand()
test.flags = append(test.flags, "--quiet") test.flags = append(test.flags, "--quiet")
hugoCmd.SetArgs(append(test.commands, test.flags...)) hugoCmd.SetArgs(append(test.commands, test.flags...))

View file

@ -51,20 +51,55 @@ import (
jww "github.com/spf13/jwalterweatherman" 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. // 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() hugoCmd := newHugoCompleteCmd()
cmd := hugoCmd.getCommand()
cmd.SetArgs(args)
if c, err := hugoCmd.ExecuteC(); err != nil { c, err := cmd.ExecuteC()
if isUserError(err) {
c.Println("") var resp Response
c.Println(c.UsageString())
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. // 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 { func (c *commandeer) initSites() error {
if c.hugo != nil { if c.hugo != nil {
// TODO(bep) cli refactor check
c.hugo.Cfg = c.Cfg c.hugo.Cfg = c.Cfg
c.hugo.Log.ResetLogCounters() c.hugo.Log.ResetLogCounters()
return nil return nil

15
main.go
View file

@ -19,22 +19,19 @@ import (
"os" "os"
"github.com/gohugoio/hugo/commands" "github.com/gohugoio/hugo/commands"
jww "github.com/spf13/jwalterweatherman"
) )
func main() { func main() {
runtime.GOMAXPROCS(runtime.NumCPU()) 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) os.Exit(-1)
} }
// TODO(bep) cli refactor
/*if commands.Hugo != nil {
if commands.Hugo.Log.LogCountForLevelsGreaterThanorEqualTo(jww.LevelError) > 0 {
os.Exit(-1)
}
}*/
} }