main.go

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