0e77ee9bf8d8ceb7021b47f2f475e9778c9da9d4

Author
Ayman Bagabas <ayman.bagabas@gmail.com>
Committer
Ayman Bagabas <ayman.bagabas@gmail.com>
Date

Message

fix(ssh): allocate pty and use the latest tea middleware

Diff

This diff is truncated to protect this page.

  1diff --git a/pkg/ssh/middleware.go b/pkg/ssh/middleware.go
  2index 285a980a754e839199c7b6dd5f041b150d53a333..5fbbaa6631fa072feb3a26d7b93a65aa61ed127a 100644
  3--- a/pkg/ssh/middleware.go
  4+++ b/pkg/ssh/middleware.go
  5@@ -78,67 +78,65 @@ var cliCommandCounter = promauto.NewCounterVec(prometheus.CounterOpts{
  6 // This middleware must be run after the ContextMiddleware.
  7 func CommandMiddleware(sh ssh.Handler) ssh.Handler {
  8 	return func(s ssh.Session) {
  9-		func() {
 10-			_, _, ptyReq := s.Pty()
 11-			if ptyReq {
 12-				return
 13-			}
 14-
 15-			ctx := s.Context()
 16-			cfg := config.FromContext(ctx)
 17+		_, _, ptyReq := s.Pty()
 18+		if ptyReq {
 19+			sh(s)
 20+			return
 21+		}
 22 
 23-			args := s.Command()
 24-			cliCommandCounter.WithLabelValues(cmd.CommandName(args)).Inc()
 25-			rootCmd := &cobra.Command{
 26-				Short:        "Soft Serve is a self-hostable Git server for the command line.",
 27-				SilenceUsage: true,
 28-			}
 29-			rootCmd.CompletionOptions.DisableDefaultCmd = true
 30+		ctx := s.Context()
 31+		cfg := config.FromContext(ctx)
 32 
 33-			rootCmd.SetUsageTemplate(cmd.UsageTemplate)
 34-			rootCmd.SetUsageFunc(cmd.UsageFunc)
 35+		args := s.Command()
 36+		cliCommandCounter.WithLabelValues(cmd.CommandName(args)).Inc()
 37+		rootCmd := &cobra.Command{
 38+			Short:        "Soft Serve is a self-hostable Git server for the command line.",
 39+			SilenceUsage: true,
 40+		}
 41+		rootCmd.CompletionOptions.DisableDefaultCmd = true
 42+
 43+		rootCmd.SetUsageTemplate(cmd.UsageTemplate)
 44+		rootCmd.SetUsageFunc(cmd.UsageFunc)
 45+		rootCmd.AddCommand(
 46+			cmd.GitUploadPackCommand(),
 47+			cmd.GitUploadArchiveCommand(),
 48+			cmd.GitReceivePackCommand(),
 49+			cmd.RepoCommand(),
 50+			cmd.SettingsCommand(),
 51+			cmd.UserCommand(),
 52+			cmd.InfoCommand(),
 53+			cmd.PubkeyCommand(),
 54+			cmd.SetUsernameCommand(),
 55+			cmd.JWTCommand(),
 56+			cmd.TokenCommand(),
 57+		)
 58+
 59+		if cfg.LFS.Enabled {
 60 			rootCmd.AddCommand(
 61-				cmd.GitUploadPackCommand(),
 62-				cmd.GitUploadArchiveCommand(),
 63-				cmd.GitReceivePackCommand(),
 64-				cmd.RepoCommand(),
 65-				cmd.SettingsCommand(),
 66-				cmd.UserCommand(),
 67-				cmd.InfoCommand(),
 68-				cmd.PubkeyCommand(),
 69-				cmd.SetUsernameCommand(),
 70-				cmd.JWTCommand(),
 71-				cmd.TokenCommand(),
 72+				cmd.GitLFSAuthenticateCommand(),
 73 			)
 74 
 75-			if cfg.LFS.Enabled {
 76+			if cfg.LFS.SSHEnabled {
 77 				rootCmd.AddCommand(
 78-					cmd.GitLFSAuthenticateCommand(),
 79+					cmd.GitLFSTransfer(),
 80 				)
 81-
 82-				if cfg.LFS.SSHEnabled {
 83-					rootCmd.AddCommand(
 84-						cmd.GitLFSTransfer(),
 85-					)
 86-				}
 87 			}
 88+		}
 89 
 90-			rootCmd.SetArgs(args)
 91-			if len(args) == 0 {
 92-				// otherwise it'll default to os.Args, which is not what we want.
 93-				rootCmd.SetArgs([]string{"--help"})
 94-			}
 95-			rootCmd.SetIn(s)
 96-			rootCmd.SetOut(s)
 97-			rootCmd.SetErr(s.Stderr())
 98-			rootCmd.SetContext(ctx)
 99-
100-			if err := rootCmd.ExecuteContext(ctx); err != nil {
101-				s.Exit(1) // nolint: errcheck
102-				return
103-			}
104-		}()
105diff --git a/pkg/ssh/session.go b/pkg/ssh/session.go
106index 99c8489eff56380b0d3b910b4856dc04cc5c11ec..9907649725434cea3ae675527be6a3c91228059e 100644
107--- a/pkg/ssh/session.go
108+++ b/pkg/ssh/session.go
109@@ -1,11 +1,9 @@
110 package ssh
111 
112 import (
113-	"strings"
114 	"time"
115 
116 	tea "github.com/charmbracelet/bubbletea"
117-	"github.com/charmbracelet/lipgloss"
118 	"github.com/charmbracelet/soft-serve/pkg/access"
119 	"github.com/charmbracelet/soft-serve/pkg/backend"
120 	"github.com/charmbracelet/soft-serve/pkg/config"
121@@ -13,7 +11,7 @@ import (
122 	"github.com/charmbracelet/soft-serve/pkg/ui/common"
123 	"github.com/charmbracelet/ssh"
124 	"github.com/charmbracelet/wish"
125-	"github.com/muesli/termenv"
126+	bm "github.com/charmbracelet/wish/bubbletea"
127 	"github.com/prometheus/client_golang/prometheus"
128 	"github.com/prometheus/client_golang/prometheus/promauto"
129 )
130@@ -54,19 +52,18 @@ func SessionHandler(s ssh.Session) *tea.Program {
131 		}
132 	}
133 
134-	envs := &sessionEnv{s}
135-	output := lipgloss.NewRenderer(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs))
136+	output := bm.MakeRenderer(s)
137 	c := common.NewCommon(ctx, output, pty.Window.Width, pty.Window.Height)
138 	c.SetValue(common.ConfigKey, cfg)
139 	m := NewUI(c, initialRepo)
140-	p := tea.NewProgram(m,
141-		tea.WithInput(s),
142-		tea.WithOutput(s),
143+	opts := bm.MakeOptions(s)
144+	opts = append(opts,
145 		tea.WithAltScreen(),
146 		tea.WithoutCatchPanics(),
147 		tea.WithMouseCellMotion(),
148 		tea.WithContext(ctx),
149 	)
150+	p := tea.NewProgram(m, opts...)
151 
152 	tuiSessionCounter.WithLabelValues(initialRepo, pty.Term).Inc()
153 
154@@ -78,23 +75,3 @@ func SessionHandler(s ssh.Session) *tea.Program {
155 
156 	return p
157 }
158-
159-var _ termenv.Environ = &sessionEnv{}
160-
161-type sessionEnv struct {
162-	ssh.Session
163-}
164-
165-func (s *sessionEnv) Environ() []string {
166-	pty, _, _ := s.Pty()
167-	return append(s.Session.Environ(), "TERM="+pty.Term)
168-}
169-
170-func (s *sessionEnv) Getenv(key string) string {
171-	for _, env := range s.Environ() {
172-		if strings.HasPrefix(env, key+"=") {
173-			return strings.TrimPrefix(env, key+"=")
174-		}
175-	}
176-	return ""
177-}
178diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go
179index 225deb9b49b4bfc23ff3785688d2420d34ac1e8b..0a501a5a95e11a0b4f71c1408f15460a68c379fa 100644
180--- a/pkg/ssh/ssh.go
181+++ b/pkg/ssh/ssh.go
182@@ -88,6 +88,7 @@ func NewSSHServer(ctx context.Context) (*SSHServer, error) {
183 	s.srv, err = wish.NewServer(
184 		ssh.PublicKeyAuth(s.PublicKeyHandler),
185 		ssh.KeyboardInteractiveAuth(s.KeyboardInteractiveHandler),
186+		ssh.AllocatePty(),
187 		wish.WithAddress(cfg.SSH.ListenAddr),
188 		wish.WithHostKeyPath(cfg.SSH.KeyPath),
189 		wish.WithMiddleware(mw...),
190diff --git a/testscript/script_test.go b/testscript/script_test.go
191index 32ebe77c127a343571e430657263ac8c93a63e81..e5623eb539bb8e9737dfa2af7151d94f4d9ed8e7 100644
192--- a/testscript/script_test.go
193+++ b/testscript/script_test.go
194@@ -238,6 +238,10 @@ func cmdUI(key ssh.Signer) func(ts *testscript.TestScript, neg bool, args []stri
195 		stdin, err := sess.StdinPipe()
196 		check(ts, err, neg)
197 
198+		err = sess.RequestPty("dumb", 40, 80, ssh.TerminalModes{})
199+		check(ts, err, neg)
200+		check(ts, sess.Start(""), neg)
201+
202 		in, err := strconv.Unquote(args[0])
203 		check(ts, err, neg)
204 		reader := strings.NewReader(in)
205@@ -256,9 +260,7 @@ func cmdUI(key ssh.Signer) func(ts *testscript.TestScript, neg bool, args []stri
206 			}
207 		}()
208 
209-		err = sess.RequestPty("dumb", 40, 80, ssh.TerminalModes{})
210-		check(ts, err, neg)
211-		check(ts, sess.Run(""), neg)
212+		check(ts, sess.Wait(), neg)
213 	}
214 }
215 
216diff --git a/testscript/testdata/ui-home.txtar b/testscript/testdata/ui-home.txtar
217index e7203fb0d969c98b958eb1d34d36289e9367a235..0a5c04ab793a4384d8fb1660942594c1547a4648 100644
218--- a/testscript/testdata/ui-home.txtar
219+++ b/testscript/testdata/ui-home.txtar
220@@ -10,7 +10,7 @@ ui '"    q"'
221 cp stdout home.txt
222 grep 'Test Soft Serve' home.txt
223 grep '• Repositories' home.txt
224-grep 'No items found' home.txt
225+grep 'No items' home.txt
226 
227 # test about tab
228 ui '"\t    q"'