From d1286319653832d82931f16b1e071dc89b1e8194 Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Wed, 22 Jun 2022 16:25:02 -0400 Subject: [PATCH] feat: generate man pages and completions using mango-cobra --- .gitignore | 4 +- .goreleaser.yml | 8 ++-- Dockerfile | 2 +- cmd/soft/main.go | 110 ---------------------------------------------- cmd/soft/man.go | 29 ++++++++++++ cmd/soft/root.go | 54 +++++++++++++++++++++++ cmd/soft/serve.go | 44 +++++++++++++++++++ go.mod | 11 ++--- go.sum | 27 +++++++----- 9 files changed, 158 insertions(+), 131 deletions(-) delete mode 100644 cmd/soft/main.go create mode 100644 cmd/soft/man.go create mode 100644 cmd/soft/root.go create mode 100644 cmd/soft/serve.go diff --git a/.gitignore b/.gitignore index 0a3b2a832..7f4876717 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ cmd/soft/soft .ssh .repos dist -testdata \ No newline at end of file +testdata +completions/ +manpages/ \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml index 0c59621d7..e986cb5d3 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -1,12 +1,12 @@ includes: - from_url: - url: charmbracelet/meta/main/goreleaser.yaml + url: charmbracelet/meta/main/goreleaser-full.yaml variables: main: "./cmd/soft" binary_name: soft description: "A tasty, self-hostable Git server for the command line🍦" github_url: "https://github.com/charmbracelet/soft-serve" - maintainer: "Christian Rocha " - brew_commit_author_name: "Christian Rocha" - brew_commit_author_email: "christian@charm.sh" + maintainer: "Ayman Bagabas " + brew_commit_author_name: "Ayman Bagabas" + brew_commit_author_email: "ayman@charm.sh" \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 589d64ba9..6b451e96b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,4 +19,4 @@ ENV SOFT_SERVE_REPO_PATH "/soft-serve/repos" EXPOSE 23231/tcp # Set the default command -ENTRYPOINT [ "/usr/local/bin/soft" ] +ENTRYPOINT [ "/usr/local/bin/soft", "serve" ] diff --git a/cmd/soft/main.go b/cmd/soft/main.go deleted file mode 100644 index 160e9c73a..000000000 --- a/cmd/soft/main.go +++ /dev/null @@ -1,110 +0,0 @@ -package main - -import ( - "context" - "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 ( - // Version contains the application version number. It's set via ldflags - // when building. - Version = "" - - // CommitSHA contains the SHA of the commit that this application was built - // against. It's set via ldflags when building. - CommitSHA = "" - - 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() - }, - } - - 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) - - done := make(chan os.Signal, 1) - signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - - log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port) - go func() { - if err := s.Start(); err != nil { - log.Fatalln(err) - } - }() - - <-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) - }, - } - - 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 - } - - manPage = manPage.WithSection("Copyright", "(C) 2021-2022 Charmbracelet, Inc.\n"+ - "Released under MIT license.") - fmt.Println(manPage.Build(roff.NewDocument())) - return nil - }, - } -) - -func init() { - rootCmd.AddCommand( - serveCmd, - manCmd, - ) - rootCmd.CompletionOptions.HiddenDefaultCmd = true - - 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 -} - -func main() { - if err := rootCmd.Execute(); err != nil { - log.Fatalln(err) - } -} diff --git a/cmd/soft/man.go b/cmd/soft/man.go new file mode 100644 index 000000000..ae59fec1b --- /dev/null +++ b/cmd/soft/man.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + + mcobra "github.com/muesli/mango-cobra" + "github.com/muesli/roff" + "github.com/spf13/cobra" +) + +var ( + 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 + } + + manPage = manPage.WithSection("Copyright", "(C) 2021-2022 Charmbracelet, Inc.\n"+ + "Released under MIT license.") + fmt.Println(manPage.Build(roff.NewDocument())) + return nil + }, + } +) diff --git a/cmd/soft/root.go b/cmd/soft/root.go new file mode 100644 index 000000000..6a536f228 --- /dev/null +++ b/cmd/soft/root.go @@ -0,0 +1,54 @@ +package main + +import ( + "log" + "runtime/debug" + + "github.com/spf13/cobra" +) + +var ( + // Version contains the application version number. It's set via ldflags + // when building. + Version = "" + + // CommitSHA contains the SHA of the commit that this application was built + // against. It's set via ldflags when building. + CommitSHA = "" + + 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() + }, + } +) + +func init() { + rootCmd.AddCommand( + serveCmd, + manCmd, + ) + rootCmd.CompletionOptions.HiddenDefaultCmd = true + + 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 +} + +func main() { + if err := rootCmd.Execute(); err != nil { + log.Fatalln(err) + } +} diff --git a/cmd/soft/serve.go b/cmd/soft/serve.go new file mode 100644 index 000000000..ecdd62874 --- /dev/null +++ b/cmd/soft/serve.go @@ -0,0 +1,44 @@ +package main + +import ( + "context" + "log" + "os" + "os/signal" + "syscall" + "time" + + "github.com/charmbracelet/soft-serve/config" + "github.com/charmbracelet/soft-serve/server" + "github.com/spf13/cobra" +) + +var ( + 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) + + done := make(chan os.Signal, 1) + signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + + log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port) + go func() { + if err := s.Start(); err != nil { + log.Fatalln(err) + } + }() + + <-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) + }, + } +) diff --git a/go.mod b/go.mod index 088bc2e67..ffc7aed12 100755 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.17 require ( github.com/alecthomas/chroma v0.10.0 github.com/caarlos0/env/v6 v6.9.1 - github.com/charmbracelet/bubbles v0.10.4-0.20220302223835-88562515cf7b - github.com/charmbracelet/bubbletea v0.20.0 + github.com/charmbracelet/bubbles v0.11.0 + github.com/charmbracelet/bubbletea v0.22.0 github.com/charmbracelet/glamour v0.4.0 - github.com/charmbracelet/lipgloss v0.4.0 + github.com/charmbracelet/lipgloss v0.5.0 github.com/charmbracelet/wish v0.5.0 github.com/dustin/go-humanize v1.0.0 github.com/gliderlabs/ssh v0.3.4 @@ -16,7 +16,7 @@ require ( github.com/go-git/go-git/v5 v5.4.3-0.20210630082519-b4368b2a2ca4 github.com/matryer/is v1.4.0 github.com/muesli/reflow v0.3.0 - github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 + github.com/muesli/termenv v0.12.0 github.com/sergi/go-diff v1.1.0 golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 ) @@ -56,6 +56,7 @@ 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/cancelreader v0.2.1 // 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 @@ -66,7 +67,7 @@ require ( github.com/yuin/goldmark v1.4.4 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect + golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index a5d68d44b..33dfda0d2 100644 --- a/go.sum +++ b/go.sum @@ -24,21 +24,22 @@ github.com/caarlos0/env/v6 v6.9.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Z github.com/caarlos0/sshmarshal v0.0.0-20220308164159-9ddb9f83c6b3/go.mod h1:7Pd/0mmq9x/JCzKauogNjSQEhivBclCQHfr9dlpDIyA= github.com/caarlos0/sshmarshal v0.1.0 h1:zTCZrDORFfWh526Tsb7vCm3+Yg/SfW/Ub8aQDeosk0I= github.com/caarlos0/sshmarshal v0.1.0/go.mod h1:7Pd/0mmq9x/JCzKauogNjSQEhivBclCQHfr9dlpDIyA= -github.com/charmbracelet/bubbles v0.10.4-0.20220302223835-88562515cf7b h1:o+LFpRn1fXtu1hDJLtBFjp7tMZ8AqwSpl84w1TnUj0Y= -github.com/charmbracelet/bubbles v0.10.4-0.20220302223835-88562515cf7b/go.mod h1:jOA+DUF1rjZm7gZHcNyIVW+YrBPALKfpGVdJu8UiJsA= -github.com/charmbracelet/bubbletea v0.19.3/go.mod h1:VuXF2pToRxDUHcBUcPmCRUHRvFATM4Ckb/ql1rBl3KA= -github.com/charmbracelet/bubbletea v0.20.0 h1:/b8LEPgCbNr7WWZ2LuE/BV1/r4t5PyYJtDb+J3vpwxc= +github.com/charmbracelet/bubbles v0.11.0 h1:fBLyY0PvJnd56Vlu5L84JJH6f4axhgIJ9P3NET78f0Q= +github.com/charmbracelet/bubbles v0.11.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= github.com/charmbracelet/bubbletea v0.20.0/go.mod h1:zpkze1Rioo4rJELjRyGlm9T2YNou1Fm4LIJQSa5QMEM= +github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= +github.com/charmbracelet/bubbletea v0.22.0 h1:E1BTNSE3iIrq0G0X6TjGAmrQ32cGCbFDPcIuImikrUc= +github.com/charmbracelet/bubbletea v0.22.0/go.mod h1:aoVIwlNlr5wbCB26KhxfrqAn0bMp4YpJcoOelbxApjs= github.com/charmbracelet/glamour v0.4.0 h1:scR+smyB7WdmrlIaff6IVlm48P48JaNM7JypM/VGl4k= github.com/charmbracelet/glamour v0.4.0/go.mod h1:9ZRtG19AUIzcTm7FGLGbq3D5WKQ5UyZBbQsMQN0XIqc= -github.com/charmbracelet/harmonica v0.1.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= +github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/keygen v0.3.0 h1:mXpsQcH7DDlST5TddmXNXjS0L7ECk4/kLQYyBcsan2Y= github.com/charmbracelet/keygen v0.3.0/go.mod h1:1ukgO8806O25lUZ5s0IrNur+RlwTBERlezdgW71F5rM= -github.com/charmbracelet/lipgloss v0.4.0 h1:768h64EFkGUr8V5yAKV7/Ta0NiVceiPaV+PphaW1K9g= github.com/charmbracelet/lipgloss v0.4.0/go.mod h1:vmdkHvce7UzX6xkyf4cca8WlwdQ5RQr8fzta+xl7BOM= +github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= +github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= github.com/charmbracelet/wish v0.5.0 h1:FkkdNBFqrLABR1ciNrAL2KCxoyWfKhXnIGZw6GfAtPg= github.com/charmbracelet/wish v0.5.0/go.mod h1:5GAn5SrDSZ7cgKjnC+3kDmiIo7I6k4/AYiRzC4+tpCk= -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.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -120,6 +121,9 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/cancelreader v0.2.1 h1:Xzd1B4U5bWQOuSKuN398MyynIGTNT89dxzpEDsalXZs= +github.com/muesli/cancelreader v0.2.1/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 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= @@ -132,8 +136,10 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw= -github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 h1:QANkGiGr39l1EESqrE0gZw0/AJNYzIvoGLhIoVYtluI= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= +github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= +github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= @@ -204,8 +210,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY= -golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210422114643-f5beecf764ed/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=