cmd.go

 1package internal
 2
 3import (
 4	"context"
 5
 6	"github.com/charmbracelet/soft-serve/server/config"
 7	"github.com/charmbracelet/soft-serve/server/hooks"
 8	"github.com/charmbracelet/ssh"
 9	"github.com/charmbracelet/wish"
10	"github.com/spf13/cobra"
11)
12
13var (
14	hooksCtxKey   = "hooks"
15	sessionCtxKey = "session"
16	configCtxKey  = "config"
17)
18
19// rootCommand is the root command for the server.
20func rootCommand(cfg *config.Config, s ssh.Session) *cobra.Command {
21	rootCmd := &cobra.Command{
22		Short:        "Soft Serve internal API.",
23		SilenceUsage: true,
24	}
25
26	rootCmd.SetIn(s)
27	rootCmd.SetOut(s)
28	rootCmd.SetErr(s)
29	rootCmd.CompletionOptions.DisableDefaultCmd = true
30
31	rootCmd.AddCommand(
32		hookCommand(),
33	)
34
35	return rootCmd
36}
37
38// Middleware returns the middleware for the server.
39func (i *InternalServer) Middleware(hooks hooks.Hooks) wish.Middleware {
40	return func(sh ssh.Handler) ssh.Handler {
41		return func(s ssh.Session) {
42			_, _, active := s.Pty()
43			if active {
44				return
45			}
46
47			// Ignore git server commands.
48			args := s.Command()
49			if len(args) > 0 {
50				if args[0] == "git-receive-pack" ||
51					args[0] == "git-upload-pack" ||
52					args[0] == "git-upload-archive" {
53					return
54				}
55			}
56
57			ctx := context.WithValue(s.Context(), hooksCtxKey, hooks)
58			ctx = context.WithValue(ctx, sessionCtxKey, s)
59			ctx = context.WithValue(ctx, configCtxKey, i.cfg)
60
61			rootCmd := rootCommand(i.cfg, s)
62			rootCmd.SetArgs(args)
63			if len(args) == 0 {
64				// otherwise it'll default to os.Args, which is not what we want.
65				rootCmd.SetArgs([]string{"--help"})
66			}
67			rootCmd.SetIn(s)
68			rootCmd.SetOut(s)
69			rootCmd.CompletionOptions.DisableDefaultCmd = true
70			rootCmd.SetErr(s.Stderr())
71			if err := rootCmd.ExecuteContext(ctx); err != nil {
72				_ = s.Exit(1)
73			}
74			sh(s)
75		}
76	}
77}
78
79func fromContext(cmd *cobra.Command) (*config.Config, ssh.Session) {
80	ctx := cmd.Context()
81	cfg := ctx.Value(configCtxKey).(*config.Config)
82	s := ctx.Value(sessionCtxKey).(ssh.Session)
83	return cfg, s
84}