Diff
1diff --git a/cmd/soft/root.go b/cmd/soft/root.go
2index edd7c21492974d1923c7cf8a6967237fa24bc09b..1dc8e1883c9bac8c1b38b00c422cbc4bb7037532 100644
3--- a/cmd/soft/root.go
4+++ b/cmd/soft/root.go
5@@ -4,11 +4,9 @@ import (
6 "context"
7 "os"
8 "runtime/debug"
9- "strconv"
10- "strings"
11- "time"
12
13 "github.com/charmbracelet/log"
14+ . "github.com/charmbracelet/soft-serve/internal/log"
15 "github.com/spf13/cobra"
16 )
17
18@@ -53,28 +51,8 @@ func init() {
19 }
20
21 func main() {
22- ctx := context.Background()
23- logger := log.NewWithOptions(os.Stderr, log.Options{
24- ReportTimestamp: true,
25- TimeFormat: time.DateOnly,
26- })
27- if debug, _ := strconv.ParseBool(os.Getenv("SOFT_SERVE_DEBUG")); debug {
28- logger.SetLevel(log.DebugLevel)
29- }
30- if tsfmt := os.Getenv("SOFT_SERVE_LOG_TIME_FORMAT"); tsfmt != "" {
31- logger.SetTimeFormat(tsfmt)
32- }
33-
34- switch strings.ToLower(os.Getenv("SOFT_SERVE_LOG_FORMAT")) {
35- case "json":
36- logger.SetFormatter(log.JSONFormatter)
37- case "logfmt":
38- logger.SetFormatter(log.LogfmtFormatter)
39- case "text":
40- logger.SetFormatter(log.TextFormatter)
41- }
42-
43- ctx = log.WithContext(ctx, logger)
44+ logger := NewDefaultLogger()
45+ ctx := log.WithContext(context.Background(), logger)
46 if err := rootCmd.ExecuteContext(ctx); err != nil {
47 os.Exit(1)
48 }
49diff --git a/git/repo.go b/git/repo.go
50index 050d3f67fd85a53766ce7b7de5f4311bc3563b9e..67a0e286d45ce438102a9e793665f86745c1be8e 100644
51--- a/git/repo.go
52+++ b/git/repo.go
53@@ -147,7 +147,11 @@ func (r *Repository) TreePath(ref *Reference, path string) (*Tree, error) {
54
55 // Diff returns the diff for the given commit.
56 func (r *Repository) Diff(commit *Commit) (*Diff, error) {
57- ddiff, err := r.Repository.Diff(commit.Hash.String(), DiffMaxFiles, DiffMaxFileLines, DiffMaxLineChars)
58+ ddiff, err := r.Repository.Diff(commit.Hash.String(), DiffMaxFiles, DiffMaxFileLines, DiffMaxLineChars, git.DiffOptions{
59+ CommandOptions: git.CommandOptions{
60+ Envs: []string{"GIT_CONFIG_GLOBAL=/dev/null"},
61+ },
62+ })
63 if err != nil {
64 return nil, err
65 }
66diff --git a/internal/log/log.go b/internal/log/log.go
67new file mode 100644
68index 0000000000000000000000000000000000000000..a1184153b81da766f76fc10ca7f533c0a486b710
69--- /dev/null
70+++ b/internal/log/log.go
71@@ -0,0 +1,39 @@
72+package log
73+
74+import (
75+ "os"
76+ "strconv"
77+ "strings"
78+ "time"
79+
80+ "github.com/charmbracelet/log"
81+)
82+
83+var contextKey = &struct{ string }{"logger"}
84+
85+// NewDefaultLogger returns a new logger with default settings.
86+func NewDefaultLogger() *log.Logger {
87+ logger := log.NewWithOptions(os.Stderr, log.Options{
88+ ReportTimestamp: true,
89+ TimeFormat: time.DateOnly,
90+ })
91+
92+ if debug, _ := strconv.ParseBool(os.Getenv("SOFT_SERVE_DEBUG")); debug {
93+ logger.SetLevel(log.DebugLevel)
94+ }
95+
96+ if tsfmt := os.Getenv("SOFT_SERVE_LOG_TIME_FORMAT"); tsfmt != "" {
97+ logger.SetTimeFormat(tsfmt)
98+ }
99+
100+ switch strings.ToLower(os.Getenv("SOFT_SERVE_LOG_FORMAT")) {
101+ case "json":
102+ logger.SetFormatter(log.JSONFormatter)
103+ case "logfmt":
104+ logger.SetFormatter(log.LogfmtFormatter)
105+ case "text":
106+ logger.SetFormatter(log.TextFormatter)
107+ }
108+
109+ return logger
110+}
111diff --git a/server/git/git.go b/server/git/git.go
112index 0b14f0b5031901b2b4299d87981f43134509edb9..85e2cf068e5f24e141c0455db2d8a1a5aa01121c 100644
113--- a/server/git/git.go
114+++ b/server/git/git.go
115@@ -88,6 +88,7 @@ func RunGit(ctx context.Context, in io.Reader, out io.Writer, er io.Writer, dir
116 c.Env = append(c.Env, "SOFT_SERVE_DEBUG="+os.Getenv("SOFT_SERVE_DEBUG"))
117 if cfg != nil {
118 c.Env = append(c.Env, "SOFT_SERVE_LOG_FORMAT="+cfg.LogFormat)
119+ c.Env = append(c.Env, "SOFT_SERVE_LOG_TIME_FORMAT="+cfg.LogTimeFormat)
120 }
121
122 stdin, err := c.StdinPipe()
123diff --git a/server/ssh/session.go b/server/ssh/session.go
124index e24bdc83a4cd9d453ae0acf3793c6c459fa5c6a3..b39e15e24cc305c14eac1f59c777c0baa5f20f52 100644
125--- a/server/ssh/session.go
126+++ b/server/ssh/session.go
127@@ -4,6 +4,8 @@ import (
128 "strings"
129
130 tea "github.com/charmbracelet/bubbletea"
131+ "github.com/charmbracelet/log"
132+ . "github.com/charmbracelet/soft-serve/internal/log"
133 "github.com/charmbracelet/soft-serve/server/backend"
134 "github.com/charmbracelet/soft-serve/server/config"
135 "github.com/charmbracelet/soft-serve/server/errors"
136@@ -48,7 +50,9 @@ func SessionHandler(cfg *config.Config) bm.ProgramHandler {
137
138 envs := &sessionEnv{s}
139 output := termenv.NewOutput(s, termenv.WithColorCache(true), termenv.WithEnvironment(envs))
140- c := common.NewCommon(s.Context(), output, pty.Window.Width, pty.Window.Height)
141+ logger := NewDefaultLogger()
142+ ctx := log.WithContext(s.Context(), logger)
143+ c := common.NewCommon(ctx, output, pty.Window.Width, pty.Window.Height)
144 c.SetValue(common.ConfigKey, cfg)
145 m := ui.New(c, initialRepo)
146 p := tea.NewProgram(m,
147diff --git a/server/ui/components/code/code.go b/server/ui/components/code/code.go
148index bf3fc4c4d080159e478aac05280d22631e97a9b7..8291183349ee1059b6baa703f692014f0c55952c 100644
149--- a/server/ui/components/code/code.go
150+++ b/server/ui/components/code/code.go
151@@ -6,7 +6,6 @@ import (
152 "sync"
153
154 "github.com/alecthomas/chroma/lexers"
155- "github.com/charmbracelet/bubbles/key"
156 tea "github.com/charmbracelet/bubbletea"
157 "github.com/charmbracelet/glamour"
158 gansi "github.com/charmbracelet/glamour/ansi"
159@@ -99,18 +98,10 @@ func (r *Code) Init() tea.Cmd {
160 // Update implements tea.Model.
161 func (r *Code) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
162 cmds := make([]tea.Cmd, 0)
163- switch msg := msg.(type) {
164+ switch msg.(type) {
165 case tea.WindowSizeMsg:
166 // Recalculate content width and line wrap.
167 cmds = append(cmds, r.Init())
168- case tea.KeyMsg:
169- // Viewport doesn't handle these keys, so we do it here.
170- switch {
171- case key.Matches(msg, r.common.KeyMap.GotoTop):
172- r.GotoTop()
173- case key.Matches(msg, r.common.KeyMap.GotoBottom):
174- r.GotoBottom()
175- }
176 }
177 v, cmd := r.Viewport.Update(msg)
178 r.Viewport = v.(*vp.Viewport)
179diff --git a/server/ui/components/viewport/viewport.go b/server/ui/components/viewport/viewport.go
180index bdccc0f0ad5971938b6dc364b938e529c0c6248b..35fe8f24da7147bb2404d03af6fdeb6982c3514d 100644
181--- a/server/ui/components/viewport/viewport.go
182+++ b/server/ui/components/viewport/viewport.go
183@@ -1,6 +1,7 @@
184 package viewport
185
186 import (
187+ "github.com/charmbracelet/bubbles/key"
188 "github.com/charmbracelet/bubbles/viewport"
189 tea "github.com/charmbracelet/bubbletea"
190 "github.com/charmbracelet/soft-serve/server/ui/common"
191@@ -36,6 +37,15 @@ func (v *Viewport) Init() tea.Cmd {
192
193 // Update implements tea.Model.
194 func (v *Viewport) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
195+ switch msg := msg.(type) {
196+ case tea.KeyMsg:
197+ switch {
198+ case key.Matches(msg, v.common.KeyMap.GotoTop):
199+ v.GotoTop()
200+ case key.Matches(msg, v.common.KeyMap.GotoBottom):
201+ v.GotoBottom()
202+ }
203+ }
204 vp, cmd := v.Model.Update(msg)
205 v.Model = &vp
206 return v, cmd
207diff --git a/server/ui/pages/repo/log.go b/server/ui/pages/repo/log.go
208index 0b1480b466840e9f6f6fb9ca09c4fbdaed0adb2a..21bbcdf9fe46cf8fec7738168fcdbb50d2efd3b1 100644
209--- a/server/ui/pages/repo/log.go
210+++ b/server/ui/pages/repo/log.go
211@@ -105,6 +105,8 @@ func (l *Log) ShortHelp() []key.Binding {
212 return []key.Binding{
213 l.common.KeyMap.UpDown,
214 l.common.KeyMap.BackItem,
215+ l.common.KeyMap.GotoTop,
216+ l.common.KeyMap.GotoBottom,
217 }
218 default:
219 return []key.Binding{}
220@@ -151,6 +153,8 @@ func (l *Log) FullHelp() [][]key.Binding {
221 {
222 k.Down,
223 k.Up,
224+ l.common.KeyMap.GotoTop,
225+ l.common.KeyMap.GotoBottom,
226 },
227 }...)
228 }
229diff --git a/server/ui/pages/selection/item.go b/server/ui/pages/selection/item.go
230index bc06210738a1b4206ad794f53a86b0e5506ce864..6550497c78b954f03ce5dc9627aefce0d9ce66b4 100644
231--- a/server/ui/pages/selection/item.go
232+++ b/server/ui/pages/selection/item.go
233@@ -83,7 +83,7 @@ func (i Item) Title() string {
234 }
235
236 // Description returns the item description. Implements list.DefaultItem.
237-func (i Item) Description() string { return i.repo.Description() }
238+func (i Item) Description() string { return strings.TrimSpace(i.repo.Description()) }
239
240 // FilterValue implements list.Item.
241 func (i Item) FilterValue() string { return i.Title() }
242@@ -199,13 +199,16 @@ func (d *ItemDelegate) Render(w io.Writer, m list.Model, index int, listItem lis
243 s.WriteRune('\n')
244 s.WriteString(desc)
245 s.WriteRune('\n')
246- cmd := common.TruncateString(i.Command(), m.Width()-styles.Base.GetHorizontalFrameSize())
247- cmd = styles.Command.Render(cmd)
248+
249+ cmd := i.Command()
250+ cmdStyler := styles.Command.Render
251 if d.copiedIdx == index {
252- cmd += " " + styles.Desc.Render("(copied to clipboard)")
253+ cmd = "(copied to clipboard)"
254+ cmdStyler = styles.Desc.Render
255 d.copiedIdx = -1
256 }
257- s.WriteString(cmd)
258+ cmd = common.TruncateString(cmd, m.Width()-styles.Base.GetHorizontalFrameSize())
259+ s.WriteString(cmdStyler(cmd))
260 fmt.Fprint(w,
261 d.common.Zone.Mark(i.ID(),
262 styles.Base.Render(s.String()),