ref: 2aab6dee850517533683504a6158e0ef0a3ffc57
parent: f3775877c61c11ab7c8fd1fc3e15470bf5da4820
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Apr 13 04:42:29 EDT 2018
commands: Fix handling of persistent CLI flags See #4607
--- a/commands/benchmark.go
+++ b/commands/benchmark.go
@@ -31,7 +31,7 @@
*baseBuilderCmd
}
-func newBenchmarkCmd() *benchmarkCmd {
+func (b *commandsBuilder) newBenchmarkCmd() *benchmarkCmd {
cmd := &cobra.Command{
Use: "benchmark",
Short: "Benchmark Hugo by building a site a number of times.",
@@ -39,7 +39,7 @@
creating a benchmark.`,
}
- c := &benchmarkCmd{baseBuilderCmd: newBuilderCmd(cmd)}
+ c := &benchmarkCmd{baseBuilderCmd: b.newBuilderCmd(cmd)}
cmd.Flags().StringVar(&c.cpuProfileFile, "cpuprofile", "", "path/filename for the CPU profile file")
cmd.Flags().StringVar(&c.memProfileFile, "memprofile", "", "path/filename for the memory profile file")
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -21,23 +21,29 @@
"github.com/spf13/nitro"
)
-// newHugoCompleteCmd builds the complete set of Hugo CLI commands.
-func newHugoCompleteCmd() *hugoCmd {
- h := newHugoCmd()
- addAllCommands(h.getCommand())
- return h
+type commandsBuilder struct {
+ hugoBuilderCommon
+
+ commands []cmder
}
-// addAllCommands adds child commands to the root command HugoCmd.
-func addAllCommands(root *cobra.Command) {
- addCommands(
- root,
- newServerCmd(),
+func newCommandsBuilder() *commandsBuilder {
+ return &commandsBuilder{}
+}
+
+func (b *commandsBuilder) addCommands(commands ...cmder) *commandsBuilder {
+ b.commands = append(b.commands, commands...)
+ return b
+}
+
+func (b *commandsBuilder) addAll() *commandsBuilder {
+ b.addCommands(
+ b.newServerCmd(),
newVersionCmd(),
newEnvCmd(),
newConfigCmd(),
newCheckCmd(),
- newBenchmarkCmd(),
+ b.newBenchmarkCmd(),
newConvertCmd(),
newNewCmd(),
newListCmd(),
@@ -44,8 +50,16 @@
newImportCmd(),
newGenCmd(),
)
+
+ return b
}
+func (b *commandsBuilder) build() *hugoCmd {
+ h := b.newHugoCmd()
+ addCommands(h.getCommand(), b.commands...)
+ return h
+}
+
func addCommands(root *cobra.Command, commands ...cmder) {
for _, command := range commands {
root.AddCommand(command.getCommand())
@@ -56,11 +70,21 @@
cmd *cobra.Command
}
+var _ commandsBuilderGetter = (*baseBuilderCmd)(nil)
+
+// Used in tests.
+type commandsBuilderGetter interface {
+ getCmmandsBuilder() *commandsBuilder
+}
type baseBuilderCmd struct {
- hugoBuilderCommon
*baseCmd
+ *commandsBuilder
}
+func (b *baseBuilderCmd) getCmmandsBuilder() *commandsBuilder {
+ return b.commandsBuilder
+}
+
func (c *baseCmd) getCommand() *cobra.Command {
return c.cmd
}
@@ -69,8 +93,8 @@
return &baseCmd{cmd: cmd}
}
-func newBuilderCmd(cmd *cobra.Command) *baseBuilderCmd {
- bcmd := &baseBuilderCmd{baseCmd: &baseCmd{cmd: cmd}}
+func (b *commandsBuilder) newBuilderCmd(cmd *cobra.Command) *baseBuilderCmd {
+ bcmd := &baseBuilderCmd{commandsBuilder: b, baseCmd: &baseCmd{cmd: cmd}}
bcmd.hugoBuilderCommon.handleFlags(cmd)
return bcmd
}
@@ -86,10 +110,10 @@
c *commandeer
}
-func newHugoCmd() *hugoCmd {
+func (b *commandsBuilder) newHugoCmd() *hugoCmd {
cc := &hugoCmd{}
- cc.baseBuilderCmd = newBuilderCmd(&cobra.Command{
+ cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{
Use: "hugo",
Short: "hugo builds your site",
Long: `hugo is the main command, used to build your Hugo site.
--- a/commands/commands_test.go
+++ b/commands/commands_test.go
@@ -20,6 +20,8 @@
"path/filepath"
"testing"
+ "github.com/spf13/cobra"
+
"github.com/stretchr/testify/require"
)
@@ -41,8 +43,45 @@
assert.True(len(result.Sites[0].RegularPages) == 1)
}
-func TestCommands(t *testing.T) {
+func TestCommandsPersistentFlags(t *testing.T) {
+ assert := require.New(t)
+ noOpRunE := func(cmd *cobra.Command, args []string) error {
+ return nil
+ }
+
+ tests := []struct {
+ args []string
+ check func(command []cmder)
+ }{{[]string{"server", "--config=myconfig.toml", "-b=https://example.com/b/", "--source=mysource"}, func(commands []cmder) {
+ for _, command := range commands {
+ if b, ok := command.(commandsBuilderGetter); ok {
+ v := b.getCmmandsBuilder().hugoBuilderCommon
+ assert.Equal("myconfig.toml", v.cfgFile)
+ assert.Equal("mysource", v.source)
+ assert.Equal("https://example.com/b/", v.baseURL)
+ }
+ }
+ }}}
+
+ for _, test := range tests {
+ b := newCommandsBuilder()
+ root := b.addAll().build()
+
+ for _, c := range b.commands {
+ // We are only intereseted in the flag handling here.
+ c.getCommand().RunE = noOpRunE
+ }
+ rootCmd := root.getCommand()
+ rootCmd.SetArgs(test.args)
+ assert.NoError(rootCmd.Execute())
+ test.check(b.commands)
+ }
+
+}
+
+func TestCommandsExecute(t *testing.T) {
+
assert := require.New(t)
dir, err := createSimpleTestSite(t)
@@ -90,7 +129,7 @@
for _, test := range tests {
- hugoCmd := newHugoCompleteCmd().getCommand()
+ hugoCmd := newCommandsBuilder().addAll().build().getCommand()
test.flags = append(test.flags, "--quiet")
hugoCmd.SetArgs(append(test.commands, test.flags...))
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -70,7 +70,7 @@
// Execute adds all child commands to the root command HugoCmd and sets flags appropriately.
// The args are usually filled with os.Args[1:].
func Execute(args []string) Response {
- hugoCmd := newHugoCompleteCmd()
+ hugoCmd := newCommandsBuilder().addAll().build()
cmd := hugoCmd.getCommand()
cmd.SetArgs(args)
--- a/commands/server.go
+++ b/commands/server.go
@@ -57,14 +57,14 @@
*baseBuilderCmd
}
-func newServerCmd() *serverCmd {
- return newServerCmdSignaled(nil)
+func (b *commandsBuilder) newServerCmd() *serverCmd {
+ return b.newServerCmdSignaled(nil)
}
-func newServerCmdSignaled(stop <-chan bool) *serverCmd {
+func (b *commandsBuilder) newServerCmdSignaled(stop <-chan bool) *serverCmd {
cc := &serverCmd{stop: stop}
- cc.baseBuilderCmd = newBuilderCmd(&cobra.Command{
+ cc.baseBuilderCmd = b.newBuilderCmd(&cobra.Command{
Use: "server",
Aliases: []string{"serve"},
Short: "A high performance webserver",
@@ -463,7 +463,8 @@
}
func memStats() error {
- sc := newServerCmd().getCommand()
+ b := newCommandsBuilder()
+ sc := b.newServerCmd().getCommand()
memstats := sc.Flags().Lookup("memstats").Value.String()
if memstats != "" {
interval, err := time.ParseDuration(sc.Flags().Lookup("meminterval").Value.String())
--- a/commands/server_test.go
+++ b/commands/server_test.go
@@ -40,7 +40,8 @@
stop := make(chan bool)
- scmd := newServerCmdSignaled(stop)
+ b := newCommandsBuilder()
+ scmd := b.newServerCmdSignaled(stop)
cmd := scmd.getCommand()
cmd.SetArgs([]string{"-s=" + dir, fmt.Sprintf("-p=%d", port)})
@@ -90,7 +91,8 @@
}
for i, test := range tests {
- s := newServerCmd()
+ b := newCommandsBuilder()
+ s := b.newServerCmd()
v := viper.New()
baseURL := test.CLIBaseURL
v.Set("baseURL", test.CfgBaseURL)