@marcel91200 / caddy Mirror · read-only / commits / 8ccfedf2
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 12, 09:30 UTC

cmd: Use a factory to create the caddy root command (#6533)

Co-authored-by: Francis Lavoie <lavofr@gmail.com>

a committed Aug 21, 2024 at 22:29 UTC 8ccfedf2bb0a1759aa68d4989f05d9a52ba41a34
4 files changed +97 -61
cmd/cobra.go
+15 -11
@@ -8,9 +8,10 @@ import (
8 "github.com/caddyserver/caddy/v2"
9 )
10
11 -var rootCmd = &cobra.Command{
12 - Use: "caddy",
13 - Long: `Caddy is an extensible server platform written in Go.
11 +var defaultFactory = newRootCommandFactory(func() *cobra.Command {
12 + return &cobra.Command{
13 + Use: "caddy",
14 + Long: `Caddy is an extensible server platform written in Go.
15
16 At its core, Caddy merely manages configuration. Modules are plugged
17 in statically at compile-time to provide useful functionality. Caddy's
@@ -91,23 +92,26 @@ package installers: https://caddyserver.com/docs/install
92 Instructions for running Caddy in production are also available:
93 https://caddyserver.com/docs/running
94 `,
94 - Example: ` $ caddy run
95 + Example: ` $ caddy run
96 $ caddy run --config caddy.json
97 $ caddy reload --config caddy.json
98 $ caddy stop`,
99
99 - // kind of annoying to have all the help text printed out if
100 - // caddy has an error provisioning its modules, for instance...
101 - SilenceUsage: true,
102 - Version: onlyVersionText(),
103 -}
100 + // kind of annoying to have all the help text printed out if
101 + // caddy has an error provisioning its modules, for instance...
102 + SilenceUsage: true,
103 + Version: onlyVersionText(),
104 + }
105 +})
106
107 const fullDocsFooter = `Full documentation is available at:
108 https://caddyserver.com/docs/command-line`
109
110 func init() {
109 - rootCmd.SetVersionTemplate("{{.Version}}\n")
110 - rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
111 + defaultFactory.Use(func(rootCmd *cobra.Command) {
112 + rootCmd.SetVersionTemplate("{{.Version}}\n")
113 + rootCmd.SetHelpTemplate(rootCmd.HelpTemplate() + "\n" + fullDocsFooter + "\n")
114 + })
115 }
116
117 func onlyVersionText() string {
cmd/commandfactory.go new
+28
@@ -0,0 +1,28 @@
1 +package caddycmd
2 +
3 +import (
4 + "github.com/spf13/cobra"
5 +)
6 +
7 +type rootCommandFactory struct {
8 + constructor func() *cobra.Command
9 + options []func(*cobra.Command)
10 +}
11 +
12 +func newRootCommandFactory(fn func() *cobra.Command) *rootCommandFactory {
13 + return &rootCommandFactory{
14 + constructor: fn,
15 + }
16 +}
17 +
18 +func (f *rootCommandFactory) Use(fn func(cmd *cobra.Command)) {
19 + f.options = append(f.options, fn)
20 +}
21 +
22 +func (f *rootCommandFactory) Build() *cobra.Command {
23 + o := f.constructor()
24 + for _, v := range f.options {
25 + v(o)
26 + }
27 + return o
28 +}
cmd/commands.go
+53 -49
@@ -438,43 +438,44 @@ EXPERIMENTAL: May be changed or removed.
438 },
439 })
440
441 - RegisterCommand(Command{
442 - Name: "manpage",
443 - Usage: "--directory <path>",
444 - Short: "Generates the manual pages for Caddy commands",
445 - Long: `
441 + defaultFactory.Use(func(rootCmd *cobra.Command) {
442 + RegisterCommand(Command{
443 + Name: "manpage",
444 + Usage: "--directory <path>",
445 + Short: "Generates the manual pages for Caddy commands",
446 + Long: `
447 Generates the manual pages for Caddy commands into the designated directory
448 tagged into section 8 (System Administration).
449
450 The manual page files are generated into the directory specified by the
451 argument of --directory. If the directory does not exist, it will be created.
452 `,
452 - CobraFunc: func(cmd *cobra.Command) {
453 - cmd.Flags().StringP("directory", "o", "", "The output directory where the manpages are generated")
454 - cmd.RunE = WrapCommandFuncForCobra(func(fl Flags) (int, error) {
455 - dir := strings.TrimSpace(fl.String("directory"))
456 - if dir == "" {
457 - return caddy.ExitCodeFailedQuit, fmt.Errorf("designated output directory and specified section are required")
458 - }
459 - if err := os.MkdirAll(dir, 0o755); err != nil {
460 - return caddy.ExitCodeFailedQuit, err
461 - }
462 - if err := doc.GenManTree(rootCmd, &doc.GenManHeader{
463 - Title: "Caddy",
464 - Section: "8", // https://en.wikipedia.org/wiki/Man_page#Manual_sections
465 - }, dir); err != nil {
466 - return caddy.ExitCodeFailedQuit, err
467 - }
468 - return caddy.ExitCodeSuccess, nil
469 - })
470 - },
471 - })
472 -
473 - // source: https://github.com/spf13/cobra/blob/main/shell_completions.md
474 - rootCmd.AddCommand(&cobra.Command{
475 - Use: "completion [bash|zsh|fish|powershell]",
476 - Short: "Generate completion script",
477 - Long: fmt.Sprintf(`To load completions:
453 + CobraFunc: func(cmd *cobra.Command) {
454 + cmd.Flags().StringP("directory", "o", "", "The output directory where the manpages are generated")
455 + cmd.RunE = WrapCommandFuncForCobra(func(fl Flags) (int, error) {
456 + dir := strings.TrimSpace(fl.String("directory"))
457 + if dir == "" {
458 + return caddy.ExitCodeFailedQuit, fmt.Errorf("designated output directory and specified section are required")
459 + }
460 + if err := os.MkdirAll(dir, 0o755); err != nil {
461 + return caddy.ExitCodeFailedQuit, err
462 + }
463 + if err := doc.GenManTree(rootCmd, &doc.GenManHeader{
464 + Title: "Caddy",
465 + Section: "8", // https://en.wikipedia.org/wiki/Man_page#Manual_sections
466 + }, dir); err != nil {
467 + return caddy.ExitCodeFailedQuit, err
468 + }
469 + return caddy.ExitCodeSuccess, nil
470 + })
471 + },
472 + })
473 +
474 + // source: https://github.com/spf13/cobra/blob/main/shell_completions.md
475 + rootCmd.AddCommand(&cobra.Command{
476 + Use: "completion [bash|zsh|fish|powershell]",
477 + Short: "Generate completion script",
478 + Long: fmt.Sprintf(`To load completions:
479
480 Bash:
481
@@ -513,23 +514,24 @@ argument of --directory. If the directory does not exist, it will be created.
514 PS> %[1]s completion powershell > %[1]s.ps1
515 # and source this file from your PowerShell profile.
516 `, rootCmd.Root().Name()),
516 - DisableFlagsInUseLine: true,
517 - ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
518 - Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
519 - RunE: func(cmd *cobra.Command, args []string) error {
520 - switch args[0] {
521 - case "bash":
522 - return cmd.Root().GenBashCompletion(os.Stdout)
523 - case "zsh":
524 - return cmd.Root().GenZshCompletion(os.Stdout)
525 - case "fish":
526 - return cmd.Root().GenFishCompletion(os.Stdout, true)
527 - case "powershell":
528 - return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
529 - default:
530 - return fmt.Errorf("unrecognized shell: %s", args[0])
531 - }
532 - },
517 + DisableFlagsInUseLine: true,
518 + ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
519 + Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
520 + RunE: func(cmd *cobra.Command, args []string) error {
521 + switch args[0] {
522 + case "bash":
523 + return cmd.Root().GenBashCompletion(os.Stdout)
524 + case "zsh":
525 + return cmd.Root().GenZshCompletion(os.Stdout)
526 + case "fish":
527 + return cmd.Root().GenFishCompletion(os.Stdout, true)
528 + case "powershell":
529 + return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
530 + default:
531 + return fmt.Errorf("unrecognized shell: %s", args[0])
532 + }
533 + },
534 + })
535 })
536 }
537
@@ -563,7 +565,9 @@ func RegisterCommand(cmd Command) {
565 if !commandNameRegex.MatchString(cmd.Name) {
566 panic("invalid command name")
567 }
566 - rootCmd.AddCommand(caddyCmdToCobra(cmd))
568 + defaultFactory.Use(func(rootCmd *cobra.Command) {
569 + rootCmd.AddCommand(caddyCmdToCobra(cmd))
570 + })
571 }
572
573 var commandNameRegex = regexp.MustCompile(`^[a-z0-9]$|^([a-z0-9]+-?[a-z0-9]*)+[a-z0-9]$`)
cmd/main.go
+1 -1
@@ -72,7 +72,7 @@ func Main() {
72 caddy.Log().Warn("failed to set GOMAXPROCS", zap.Error(err))
73 }
74
75 - if err := rootCmd.Execute(); err != nil {
75 + if err := defaultFactory.Build().Execute(); err != nil {
76 var exitError *exitError
77 if errors.As(err, &exitError) {
78 os.Exit(exitError.ExitCode)