1package main
2
3import (
4 "context"
5 "fmt"
6 "log"
7 "os"
8 "os/signal"
9 "runtime/debug"
10 "syscall"
11 "time"
12
13 "github.com/charmbracelet/soft-serve/config"
14 "github.com/charmbracelet/soft-serve/server"
15 mcobra "github.com/muesli/mango-cobra"
16 "github.com/muesli/roff"
17 "github.com/spf13/cobra"
18)
19
20var (
21 // Version contains the application version number. It's set via ldflags
22 // when building.
23 Version = ""
24
25 // CommitSHA contains the SHA of the commit that this application was built
26 // against. It's set via ldflags when building.
27 CommitSHA = ""
28
29 rootCmd = &cobra.Command{
30 Use: "soft",
31 Short: "A self-hostable Git server for the command line",
32 Long: "Soft Serve is a self-hostable Git server for the command line.",
33 RunE: func(cmd *cobra.Command, args []string) error {
34 return cmd.Help()
35 },
36 }
37
38 serveCmd = &cobra.Command{
39 Use: "serve",
40 Short: "Start the server",
41 Long: "Start the server",
42 Args: cobra.NoArgs,
43 RunE: func(cmd *cobra.Command, args []string) error {
44 cfg := config.DefaultConfig()
45 s := server.NewServer(cfg)
46
47 done := make(chan os.Signal, 1)
48 signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
49
50 log.Printf("Starting SSH server on %s:%d", cfg.BindAddr, cfg.Port)
51 go func() {
52 if err := s.Start(); err != nil {
53 log.Fatalln(err)
54 }
55 }()
56
57 <-done
58
59 log.Printf("Stopping SSH server on %s:%d", cfg.BindAddr, cfg.Port)
60 ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
61 defer func() { cancel() }()
62 return s.Shutdown(ctx)
63 },
64 }
65
66 manCmd = &cobra.Command{
67 Use: "man",
68 Short: "Generate man pages",
69 Args: cobra.NoArgs,
70 Hidden: true,
71 RunE: func(cmd *cobra.Command, args []string) error {
72 manPage, err := mcobra.NewManPage(1, rootCmd) //.
73 if err != nil {
74 return err
75 }
76
77 manPage = manPage.WithSection("Copyright", "(C) 2021-2022 Charmbracelet, Inc.\n"+
78 "Released under MIT license.")
79 fmt.Println(manPage.Build(roff.NewDocument()))
80 return nil
81 },
82 }
83)
84
85func init() {
86 rootCmd.AddCommand(
87 serveCmd,
88 manCmd,
89 )
90 rootCmd.CompletionOptions.HiddenDefaultCmd = true
91
92 if len(CommitSHA) >= 7 {
93 vt := rootCmd.VersionTemplate()
94 rootCmd.SetVersionTemplate(vt[:len(vt)-1] + " (" + CommitSHA[0:7] + ")\n")
95 }
96 if Version == "" {
97 if info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != "" {
98 Version = info.Main.Version
99 } else {
100 Version = "unknown (built from source)"
101 }
102 }
103 rootCmd.Version = Version
104}
105
106func main() {
107 if err := rootCmd.Execute(); err != nil {
108 log.Fatalln(err)
109 }
110}