feat: use spf13/cobra

Ayman Bagabas created

Change summary

cmd/soft/main.go | 109 +++++++++++++++++++++++++++++++++----------------
cmd/soft/man.go  |  25 -----------
go.mod           |   6 +
go.sum           |  10 +++-
4 files changed, 83 insertions(+), 67 deletions(-)

Detailed changes

cmd/soft/main.go 🔗

@@ -2,16 +2,19 @@ package main
 
 import (
 	"context"
-	"flag"
 	"fmt"
 	"log"
 	"os"
 	"os/signal"
+	"runtime/debug"
 	"syscall"
 	"time"
 
 	"github.com/charmbracelet/soft-serve/config"
 	"github.com/charmbracelet/soft-serve/server"
+	mcobra "github.com/muesli/mango-cobra"
+	"github.com/muesli/roff"
+	"github.com/spf13/cobra"
 )
 
 var (
@@ -23,53 +26,85 @@ var (
 	// against. It's set via ldflags when building.
 	CommitSHA = ""
 
-	version = flag.Bool("version", false, "display version")
-)
-
-func main() {
-	flag.Usage = func() {
-		fmt.Fprintf(os.Stderr, "Soft Serve, a self-hostable Git server for the command line.\n\n")
-		flag.PrintDefaults()
+	rootCmd = &cobra.Command{
+		Use:   "soft",
+		Short: "A self-hostable Git server for the command line",
+		Long:  "Soft Serve is a self-hostable Git server for the command line.",
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return cmd.Help()
+		},
 	}
 
-	flag.Parse()
+	serveCmd = &cobra.Command{
+		Use:   "serve",
+		Short: "Start the server",
+		Long:  "Start the server",
+		Args:  cobra.NoArgs,
+		RunE: func(cmd *cobra.Command, args []string) error {
+			cfg := config.DefaultConfig()
+			s := server.NewServer(cfg)
 
-	if *version {
-		if len(CommitSHA) > 7 {
-			CommitSHA = CommitSHA[:7]
-		}
-		if Version == "" {
-			Version = "(built from source)"
-		}
+			done := make(chan os.Signal, 1)
+			signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
 
-		fmt.Printf("Soft Serve %s", Version)
-		if len(CommitSHA) > 0 {
-			fmt.Printf(" (%s)", CommitSHA)
-		}
+			log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port)
+			go func() {
+				if err := s.Start(); err != nil {
+					log.Fatalln(err)
+				}
+			}()
 
-		fmt.Println()
-		os.Exit(0)
+			<-done
+
+			log.Printf("Stopping SSH server on %s:%d", cfg.BindAddr, cfg.Port)
+			ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+			defer func() { cancel() }()
+			return s.Shutdown(ctx)
+		},
 	}
 
-	cfg := config.DefaultConfig()
-	s := server.NewServer(cfg)
+	manCmd = &cobra.Command{
+		Use:    "man",
+		Short:  "Generate man pages",
+		Args:   cobra.NoArgs,
+		Hidden: true,
+		RunE: func(cmd *cobra.Command, args []string) error {
+			manPage, err := mcobra.NewManPage(1, rootCmd) //.
+			if err != nil {
+				return err
+			}
 
-	done := make(chan os.Signal, 1)
-	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
+			manPage = manPage.WithSection("Copyright", "(C) 2021-2022 Charmbracelet, Inc.\n"+
+				"Released under MIT license.")
+			fmt.Println(manPage.Build(roff.NewDocument()))
+			return nil
+		},
+	}
+)
 
-	log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port)
-	go func() {
-		if err := s.Start(); err != nil {
-			log.Fatalln(err)
-		}
-	}()
+func init() {
+	rootCmd.AddCommand(
+		serveCmd,
+		manCmd,
+	)
+	rootCmd.CompletionOptions.HiddenDefaultCmd = true
 
-	<-done
+	if len(CommitSHA) >= 7 {
+		vt := rootCmd.VersionTemplate()
+		rootCmd.SetVersionTemplate(vt[:len(vt)-1] + " (" + CommitSHA[0:7] + ")\n")
+	}
+	if Version == "" {
+		if info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != "" {
+			Version = info.Main.Version
+		} else {
+			Version = "unknown (built from source)"
+		}
+	}
+	rootCmd.Version = Version
+}
 
-	log.Printf("Stopping SSH server on %s:%d", cfg.BindAddr, cfg.Port)
-	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
-	defer func() { cancel() }()
-	if err := s.Shutdown(ctx); err != nil {
+func main() {
+	if err := rootCmd.Execute(); err != nil {
 		log.Fatalln(err)
 	}
 }

cmd/soft/man.go 🔗

@@ -1,25 +0,0 @@
-//go:build mango
-// +build mango
-
-package main
-
-import (
-	"flag"
-	"fmt"
-	"os"
-
-	"github.com/muesli/mango"
-	"github.com/muesli/mango/mflag"
-	"github.com/muesli/roff"
-)
-
-func init() {
-	manPage := mango.NewManPage(1, "soft", "A self-hostable Git server for the command line").
-		WithLongDescription("Soft Serve is a self-hostable Git server for the command line.").
-		WithSection("Copyright", "(C) 2021-2022 Charmbracelet, Inc.\n"+
-			"Released under MIT license.")
-
-	flag.VisitAll(mflag.FlagVisitor(manPage))
-	fmt.Println(manPage.Build(roff.NewDocument()))
-	os.Exit(0)
-}

go.mod 🔗

@@ -26,9 +26,9 @@ require (
 	github.com/gobwas/glob v0.2.3
 	github.com/gogs/git-module v1.6.1
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
-	github.com/muesli/mango v0.1.0
+	github.com/muesli/mango-cobra v1.2.0
 	github.com/muesli/roff v0.1.0
-	github.com/spf13/cobra v1.4.0
+	github.com/spf13/cobra v1.5.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -56,6 +56,8 @@ require (
 	github.com/microcosm-cc/bluemonday v1.0.17 // indirect
 	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 // indirect
+	github.com/muesli/mango v0.1.0 // indirect
+	github.com/muesli/mango-pflag v0.1.0 // indirect
 	github.com/olekukonko/tablewriter v0.0.5 // indirect
 	github.com/rivo/uniseg v0.2.0 // indirect
 	github.com/sahilm/fuzzy v0.1.0 // indirect

go.sum 🔗

@@ -41,7 +41,7 @@ github.com/charmbracelet/wish v0.5.0/go.mod h1:5GAn5SrDSZ7cgKjnC+3kDmiIo7I6k4/AY
 github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=
 github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
 github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -122,6 +122,10 @@ github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPw
 github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
 github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
 github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
+github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg=
+github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA=
+github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=
+github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
 github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
 github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
 github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
@@ -148,8 +152,8 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
-github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
+github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
+github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=