aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authora <[email protected]>2024-06-18 21:57:46 -0500
committera <[email protected]>2024-06-18 21:57:46 -0500
commit7bc7e1680e79863f97bc60be44d9d0199fdda2a0 (patch)
tree8b04aa06958b704f762b1e9e768c175f6c1a2de0
parentedf4168c8e3e9659612d4e8da71944769dae0391 (diff)
downloadcaddy-7bc7e1680e79863f97bc60be44d9d0199fdda2a0.tar.gz
caddy-7bc7e1680e79863f97bc60be44d9d0199fdda2a0.zip
noot
-rw-r--r--cmd/cobra.go26
-rw-r--r--cmd/commandfactory.go28
-rw-r--r--cmd/commands.go53
-rw-r--r--cmd/main.go15
4 files changed, 76 insertions, 46 deletions
diff --git a/cmd/cobra.go b/cmd/cobra.go
index 1a2509206..5323d2ec5 100644
--- a/cmd/cobra.go
+++ b/cmd/cobra.go
@@ -8,9 +8,10 @@ import (
"github.com/caddyserver/caddy/v2"
)
-var rootCmd = &cobra.Command{
- Use: "caddy",
- Long: `Caddy is an extensible server platform written in Go.
+var defaultFactory = NewRootCommandFactory(func() *cobra.Command {
+ return &cobra.Command{
+ Use: "caddy",
+ Long: `Caddy is an extensible server platform written in Go.
At its core, Caddy merely manages configuration. Modules are plugged
in statically at compile-time to provide useful functionality. Caddy's
@@ -91,23 +92,26 @@ package installers: https://caddyserver.com/docs/install
Instructions for running Caddy in production are also available:
https://caddyserver.com/docs/running
`,
- Example: ` $ caddy run
+ Example: ` $ caddy run
$ caddy run --config caddy.json
$ caddy reload --config caddy.json
$ caddy stop`,
- // kind of annoying to have all the help text printed out if
- // caddy has an error provisioning its modules, for instance...
- SilenceUsage: true,
- Version: onlyVersionText(),
-}
+ // kind of annoying to have all the help text printed out if
+ // caddy has an error provisioning its modules, for instance...
+ SilenceUsage: true,
+ Version: onlyVersionText(),
+ }
+})
const fullDocsFooter = `Full documentation is available at:
https://caddyserver.com/docs/command-line`
func init() {
- rootCmd.SetVersionTemplate("{{.Version}}\n")
- rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
+ defaultFactory.Use(func(cmd *cobra.Command) {
+ cmd.SetVersionTemplate("{{.Version}}\n")
+ cmd.SetHelpTemplate(cmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
+ })
}
func onlyVersionText() string {
diff --git a/cmd/commandfactory.go b/cmd/commandfactory.go
new file mode 100644
index 000000000..49a38a4e1
--- /dev/null
+++ b/cmd/commandfactory.go
@@ -0,0 +1,28 @@
+package caddycmd
+
+import (
+ "github.com/spf13/cobra"
+)
+
+type RootCommandFactory struct {
+ constructor func() *cobra.Command
+ options []func(*cobra.Command)
+}
+
+func NewRootCommandFactory(fn func() *cobra.Command) *RootCommandFactory {
+ return &RootCommandFactory{
+ constructor: fn,
+ }
+}
+
+func (f *RootCommandFactory) Use(fn func(cmd *cobra.Command)) {
+ f.options = append(f.options, fn)
+}
+
+func (f *RootCommandFactory) Build() *cobra.Command {
+ o := f.constructor()
+ for _, v := range f.options {
+ v(o)
+ }
+ return o
+}
diff --git a/cmd/commands.go b/cmd/commands.go
index e5e1265e4..7e7af1c77 100644
--- a/cmd/commands.go
+++ b/cmd/commands.go
@@ -459,7 +459,8 @@ argument of --directory. If the directory does not exist, it will be created.
if err := os.MkdirAll(dir, 0o755); err != nil {
return caddy.ExitCodeFailedQuit, err
}
- if err := doc.GenManTree(rootCmd, &doc.GenManHeader{
+ ccmd := defaultFactory.Build()
+ if err := doc.GenManTree(ccmd, &doc.GenManHeader{
Title: "Caddy",
Section: "8", // https://en.wikipedia.org/wiki/Man_page#Manual_sections
}, dir); err != nil {
@@ -471,10 +472,11 @@ argument of --directory. If the directory does not exist, it will be created.
})
// source: https://github.com/spf13/cobra/blob/main/shell_completions.md
- rootCmd.AddCommand(&cobra.Command{
- Use: "completion [bash|zsh|fish|powershell]",
- Short: "Generate completion script",
- Long: fmt.Sprintf(`To load completions:
+ defaultFactory.Use(func(ccmd *cobra.Command) {
+ ccmd.AddCommand(&cobra.Command{
+ Use: "completion [bash|zsh|fish|powershell]",
+ Short: "Generate completion script",
+ Long: fmt.Sprintf(`To load completions:
Bash:
@@ -512,24 +514,25 @@ argument of --directory. If the directory does not exist, it will be created.
# To load completions for every new session, run:
PS> %[1]s completion powershell > %[1]s.ps1
# and source this file from your PowerShell profile.
- `, rootCmd.Root().Name()),
- DisableFlagsInUseLine: true,
- ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
- Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
- RunE: func(cmd *cobra.Command, args []string) error {
- switch args[0] {
- case "bash":
- return cmd.Root().GenBashCompletion(os.Stdout)
- case "zsh":
- return cmd.Root().GenZshCompletion(os.Stdout)
- case "fish":
- return cmd.Root().GenFishCompletion(os.Stdout, true)
- case "powershell":
- return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
- default:
- return fmt.Errorf("unrecognized shell: %s", args[0])
- }
- },
+ `, defaultFactory.constructor().Name()),
+ DisableFlagsInUseLine: true,
+ ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
+ Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
+ RunE: func(cmd *cobra.Command, args []string) error {
+ switch args[0] {
+ case "bash":
+ return cmd.Root().GenBashCompletion(os.Stdout)
+ case "zsh":
+ return cmd.Root().GenZshCompletion(os.Stdout)
+ case "fish":
+ return cmd.Root().GenFishCompletion(os.Stdout, true)
+ case "powershell":
+ return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
+ default:
+ return fmt.Errorf("unrecognized shell: %s", args[0])
+ }
+ },
+ })
})
}
@@ -563,7 +566,9 @@ func RegisterCommand(cmd Command) {
if !commandNameRegex.MatchString(cmd.Name) {
panic("invalid command name")
}
- rootCmd.AddCommand(caddyCmdToCobra(cmd))
+ defaultFactory.Use(func(ccmd *cobra.Command) {
+ ccmd.AddCommand(caddyCmdToCobra(cmd))
+ })
}
var commandNameRegex = regexp.MustCompile(`^[a-z0-9]$|^([a-z0-9]+-?[a-z0-9]*)+[a-z0-9]$`)
diff --git a/cmd/main.go b/cmd/main.go
index 4526b26b6..6defac756 100644
--- a/cmd/main.go
+++ b/cmd/main.go
@@ -34,7 +34,6 @@ import (
"time"
"github.com/caddyserver/certmagic"
- "github.com/spf13/cobra"
"github.com/spf13/pflag"
"go.uber.org/automaxprocs/maxprocs"
"go.uber.org/zap"
@@ -72,7 +71,7 @@ func Main() {
if err != nil {
caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
}
-
+ rootCmd := defaultFactory.Build()
if err := rootCmd.Execute(); err != nil {
var exitError *exitError
if errors.As(err, &exitError) {
@@ -86,15 +85,9 @@ func Main() {
func MainForTesting(args ...string) error {
// create a root command for testing which will not pollute the global namespace, and does not
// call os.Exit().
- tmpRootCmp := cobra.Command{
- Use: rootCmd.Use,
- Long: rootCmd.Long,
- Example: rootCmd.Example,
- SilenceUsage: rootCmd.SilenceUsage,
- Version: rootCmd.Version,
- }
- tmpRootCmp.SetArgs(args)
- if err := tmpRootCmp.Execute(); err != nil {
+ rootCmd := defaultFactory.Build()
+ rootCmd.SetArgs(args)
+ if err := rootCmd.Execute(); err != nil {
return err
}
return nil