main.go

  1package main
  2
  3import (
  4	"context"
  5	"fmt"
  6	"os"
  7	"runtime/debug"
  8	"strconv"
  9
 10	"github.com/charmbracelet/colorprofile"
 11	"github.com/charmbracelet/log"
 12	"github.com/charmbracelet/soft-serve/cmd/soft/admin"
 13	"github.com/charmbracelet/soft-serve/cmd/soft/browse"
 14	"github.com/charmbracelet/soft-serve/cmd/soft/hook"
 15	"github.com/charmbracelet/soft-serve/cmd/soft/serve"
 16	"github.com/charmbracelet/soft-serve/pkg/config"
 17	logr "github.com/charmbracelet/soft-serve/pkg/log"
 18	"github.com/charmbracelet/soft-serve/pkg/ui/common"
 19	"github.com/charmbracelet/soft-serve/pkg/version"
 20	mcobra "github.com/muesli/mango-cobra"
 21	"github.com/muesli/roff"
 22	"github.com/spf13/cobra"
 23	"go.uber.org/automaxprocs/maxprocs"
 24)
 25
 26var (
 27	// Version contains the application version number. It's set via ldflags
 28	// when building.
 29	Version = ""
 30
 31	// CommitSHA contains the SHA of the commit that this application was built
 32	// against. It's set via ldflags when building.
 33	CommitSHA = ""
 34
 35	// CommitDate contains the date of the commit that this application was
 36	// built against. It's set via ldflags when building.
 37	CommitDate = ""
 38
 39	rootCmd = &cobra.Command{
 40		Use:          "soft",
 41		Short:        "A self-hostable Git server for the command line",
 42		Long:         "Soft Serve is a self-hostable Git server for the command line.",
 43		SilenceUsage: true,
 44		RunE: func(cmd *cobra.Command, args []string) error {
 45			return browse.Command.RunE(cmd, args)
 46		},
 47	}
 48
 49	manCmd = &cobra.Command{
 50		Use:    "man",
 51		Short:  "Generate man pages",
 52		Args:   cobra.NoArgs,
 53		Hidden: true,
 54		RunE: func(_ *cobra.Command, _ []string) error {
 55			manPage, err := mcobra.NewManPage(1, rootCmd) //.
 56			if err != nil {
 57				return err
 58			}
 59
 60			manPage = manPage.WithSection("Copyright", "(C) 2021-2023 Charmbracelet, Inc.\n"+
 61				"Released under MIT license.")
 62			fmt.Println(manPage.Build(roff.NewDocument()))
 63			return nil
 64		},
 65	}
 66)
 67
 68func init() {
 69	if noColor, _ := strconv.ParseBool(os.Getenv("SOFT_SERVE_NO_COLOR")); noColor {
 70		common.DefaultColorProfile = colorprofile.NoTTY
 71	}
 72
 73	rootCmd.AddCommand(
 74		manCmd,
 75		serve.Command,
 76		hook.Command,
 77		admin.Command,
 78		browse.Command,
 79	)
 80	rootCmd.CompletionOptions.HiddenDefaultCmd = true
 81
 82	if len(CommitSHA) >= 7 {
 83		vt := rootCmd.VersionTemplate()
 84		rootCmd.SetVersionTemplate(vt[:len(vt)-1] + " (" + CommitSHA[0:7] + ")\n")
 85	}
 86	if Version == "" {
 87		if info, ok := debug.ReadBuildInfo(); ok && info.Main.Sum != "" {
 88			Version = info.Main.Version
 89		} else {
 90			Version = "unknown (built from source)"
 91		}
 92	}
 93	rootCmd.Version = Version
 94
 95	version.Version = Version
 96	version.CommitSHA = CommitSHA
 97	version.CommitDate = CommitDate
 98}
 99
100func main() {
101	ctx := context.Background()
102	cfg := config.DefaultConfig()
103	if cfg.Exist() {
104		if err := cfg.Parse(); err != nil {
105			log.Fatal(err)
106		}
107	}
108
109	if err := cfg.ParseEnv(); err != nil {
110		log.Fatal(err)
111	}
112
113	ctx = config.WithContext(ctx, cfg)
114	logger, f, err := logr.NewLogger(cfg)
115	if err != nil {
116		log.Errorf("failed to create logger: %v", err)
117	}
118
119	ctx = log.WithContext(ctx, logger)
120	if f != nil {
121		defer f.Close() // nolint: errcheck
122	}
123
124	// Set global logger
125	log.SetDefault(logger)
126
127	var opts []maxprocs.Option
128	if config.IsVerbose() {
129		opts = append(opts, maxprocs.Logger(log.Debugf))
130	}
131
132	// Set the max number of processes to the number of CPUs
133	// This is useful when running soft serve in a container
134	if _, err := maxprocs.Set(opts...); err != nil {
135		log.Warn("couldn't set automaxprocs", "error", err)
136	}
137
138	if err := rootCmd.ExecuteContext(ctx); err != nil {
139		os.Exit(1)
140	}
141}