1e58693e3c2efd527fa869abbdf324a26f2d46d5
- Author
- Toby Padilla <toby@charm.sh>
- Committer
- Toby Padilla <toby@charm.sh>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/git/git.go b/git/git.go
2index 3996165a5cde47ed3cbfcae7f5054d64dd9a7257..5858e9c30e10d333cb4cd20489e7274d2c5794b5 100644
3--- a/git/git.go
4+++ b/git/git.go
5@@ -142,3 +142,23 @@ func (rs *RepoSource) loadRepo(name string, rg *git.Repository) (*Repo, error) {
6 sort.Sort(rs.commits)
7 return r, nil
8 }
9+
10+func (r *Repo) LatestFile(path string) (string, error) {
11+ lg, err := r.Repository.Log(&git.LogOptions{})
12+ if err != nil {
13+ return "", err
14+ }
15+ c, err := lg.Next()
16+ if err != nil {
17+ return "", err
18+ }
19+ f, err := c.File(path)
20+ if err != nil {
21+ return "", nil
22+ }
23+ content, err := f.Contents()
24+ if err != nil {
25+ return "", nil
26+ }
27+ return content, nil
28+}
29diff --git a/main.go b/main.go
30index 537c061f1a55b480c0e341b991cdcdbf2c31d633..fae768a156c2b39d21e290129740bbc017f19615 100644
31--- a/main.go
32+++ b/main.go
33@@ -7,6 +7,7 @@ import (
34 gm "smoothie/server/middleware/git"
35 lm "smoothie/server/middleware/logging"
36 "smoothie/tui"
37+ "time"
38
39 "github.com/meowgorithm/babyenv"
40 )
41@@ -27,7 +28,7 @@ func main() {
42 s, err := server.NewServer(
43 cfg.Port,
44 cfg.KeyPath,
45- bm.Middleware(tui.SessionHandler(cfg.RepoPath)),
46+ bm.Middleware(tui.SessionHandler(cfg.RepoPath, time.Second*5)),
47 gm.Middleware(cfg.RepoPath, cfg.RepoAuthPath),
48 lm.Middleware(),
49 )
50diff --git a/tui/bubble.go b/tui/bubble.go
51index 4bc44308435a7803317896a1e4b6dc0b4e70277c..8c8c810c7feb613ca33cfa5640aaa14897041edf 100644
52--- a/tui/bubble.go
53+++ b/tui/bubble.go
54@@ -1,11 +1,13 @@
55 package tui
56
57 import (
58+ "encoding/json"
59 "fmt"
60 "log"
61 "smoothie/git"
62 "smoothie/tui/bubbles/commits"
63 "smoothie/tui/bubbles/selection"
64+ "time"
65
66 "github.com/charmbracelet/bubbles/viewport"
67 tea "github.com/charmbracelet/bubbletea"
68@@ -24,14 +26,33 @@ const (
69 quitState
70 )
71
72+type MenuEntry struct {
73+ Name string `json:"name"`
74+ Repo string `json:"repo"`
75+}
76+
77+type Config struct {
78+ Name string `json:"name"`
79+ ShowAllRepos bool `json:"show_all_repos"`
80+ Menu []MenuEntry `json:"menu"`
81+ RepoSource *git.RepoSource
82+}
83+
84+type SessionConfig struct {
85+ Width int
86+ Height int
87+ WindowChanges <-chan ssh.Window
88+}
89+
90 type Bubble struct {
91+ config *Config
92 state sessionState
93 error string
94 width int
95 height int
96- session ssh.Session
97 windowChanges <-chan ssh.Window
98 repoSource *git.RepoSource
99+ repoMenu []MenuEntry
100 repos []*git.Repo
101 boxes []tea.Model
102 activeBox int
103@@ -40,25 +61,18 @@ type Bubble struct {
104 readmeViewport *ViewportBubble
105 }
106
107-type Config struct {
108- Width int
109- Height int
110- Session ssh.Session
111- WindowChanges <-chan ssh.Window
112- RepoSource *git.RepoSource
113-}
114-
115-func NewBubble(cfg Config) *Bubble {
116+func NewBubble(cfg *Config, sCfg *SessionConfig) *Bubble {
117 b := &Bubble{
118- width: cfg.Width,
119- height: cfg.Height,
120- windowChanges: cfg.WindowChanges,
121+ config: cfg,
122+ width: sCfg.Width,
123+ height: sCfg.Height,
124+ windowChanges: sCfg.WindowChanges,
125 repoSource: cfg.RepoSource,
126 boxes: make([]tea.Model, 2),
127 readmeViewport: &ViewportBubble{
128 Viewport: &viewport.Model{
129 Width: boxRightWidth - horizontalPadding - 2,
130- Height: cfg.Height - verticalPadding - viewportHeightConstant,
131+ Height: sCfg.Height - verticalPadding - viewportHeightConstant,
132 },
133 },
134 }
135@@ -91,7 +105,7 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
136 b.width = msg.Width
137 b.height = msg.Height
138 case selection.SelectedMsg:
139- cmds = append(cmds, b.getRepoCmd(b.repos[msg.Index].Name))
140+ cmds = append(cmds, b.getRepoCmd(b.repoMenu[msg.Index].Repo))
141 }
142 if b.state == loadedState {
143 ab, cmd := b.boxes[b.activeBox].Update(msg)
144@@ -114,7 +128,7 @@ func (b *Bubble) viewForBox(i int, width int) string {
145 }
146
147 func (b *Bubble) View() string {
148- h := headerStyle.Width(b.width - horizontalPadding).Render("Charm Beta")
149+ h := headerStyle.Width(b.width - horizontalPadding).Render(b.config.Name)
150 f := footerStyle.Render("")
151 s := ""
152 content := ""
153@@ -147,22 +161,41 @@ func glamourReadme(md string) string {
154diff --git a/tui/bubbles/selection/bubble.go b/tui/bubbles/selection/bubble.go
155index c052723ed6af6d6c62a8cc832442b4f03e986611..ab4f0c6bdff16af252f5d958632348a0af6970ba 100644
156--- a/tui/bubbles/selection/bubble.go
157+++ b/tui/bubbles/selection/bubble.go
158@@ -22,7 +22,6 @@ func NewBubble(items []string) *Bubble {
159 NormalStyle: normalStyle,
160 SelectedStyle: selectedStyle,
161 Items: items,
162- selectedItem: -1,
163 }
164 }
165
166diff --git a/tui/commands.go b/tui/commands.go
167index 704f9072e3958fdeb014e7eea7a6abd092649fb7..a32ad7d4c89d7fd75c307d80d8014e8df7224e92 100644
168--- a/tui/commands.go
169+++ b/tui/commands.go
170@@ -1,15 +1,10 @@
171 package tui
172
173 import (
174- "os"
175- "path/filepath"
176- "smoothie/git"
177 "smoothie/tui/bubbles/commits"
178 "smoothie/tui/bubbles/selection"
179
180 tea "github.com/charmbracelet/bubbletea"
181- gg "github.com/go-git/go-git/v5"
182- "github.com/go-git/go-git/v5/plumbing/object"
183 )
184
185 type windowMsg struct{}
186@@ -27,78 +22,26 @@ func (b *Bubble) windowChangesCmd() tea.Msg {
187 }
188
189 func (b *Bubble) loadGitCmd() tea.Msg {
190- cn := "config"
191- err := b.repoSource.LoadRepos()
192- cr, err := b.repoSource.GetRepo(cn)
193- if err == git.ErrMissingRepo {
194- cr, err = b.repoSource.InitRepo(cn, false)
195- if err != nil {
196- return errMsg{err}
197- }
198-
199- // Add default README and config
200- rp := filepath.Join(b.repoSource.Path, cn, "README.md")
201- rf, err := os.Create(rp)
202- if err != nil {
203- return errMsg{err}
204- }
205- defer rf.Close()
206- _, err = rf.WriteString(defaultReadme)
207- if err != nil {
208- return errMsg{err}
209- }
210- err = rf.Sync()
211- if err != nil {
212- return errMsg{err}
213- }
214- cp := filepath.Join(b.repoSource.Path, cn, "config.json")
215- cf, err := os.Create(cp)
216- if err != nil {
217- return errMsg{err}
218- }
219- defer cf.Close()
220- _, err = cf.WriteString(defaultConfig)
221- if err != nil {
222- return errMsg{err}
223- }
224- err = cf.Sync()
225- if err != nil {
226- return errMsg{err}
227- }
228- wt, err := cr.Repository.Worktree()
229- if err != nil {
230- return errMsg{err}
231- }
232- _, err = wt.Add("README.md")
233- if err != nil {
234- return errMsg{err}
235- }
236- _, err = wt.Add("config.json")
237- if err != nil {
238- return errMsg{err}
239- }
240- _, err = wt.Commit("Default init", &gg.CommitOptions{
241- All: true,
242- Author: &object.Signature{
243- Name: "Smoothie Server",
244- Email: "vt100@charm.sh",
245- },
246- })
247- if err != nil {
248- return errMsg{err}
249- }
250- err = b.repoSource.LoadRepos()
251- if err != nil {
252- return errMsg{err}
253- }
254- } else if err != nil {
255- return errMsg{err}
256- }
257 b.repos = b.repoSource.AllRepos()
258-
259+ mes := make([]MenuEntry, 0)
260 rs := make([]string, 0)
261- for _, r := range b.repos {
262- rs = append(rs, r.Name)
263+ for _, me := range b.config.Menu {
264+ mes = append(mes, me)
265+ }
266+ if b.config.ShowAllRepos {
267+ OUTER:
268+ for _, r := range b.repos {
269+ for _, me := range mes {
270diff --git a/tui/defaults.go b/tui/defaults.go
271index e6200c18a72275b8a9e0195b0b1ac54eeb3e384d..6724b8101a430fe080e08ff2795ac2b6c0bac983 100644
272--- a/tui/defaults.go
273+++ b/tui/defaults.go
274@@ -1,5 +1,14 @@
275 package tui
276
277+import (
278+ "os"
279+ "path/filepath"
280+ "smoothie/git"
281+
282+ gg "github.com/go-git/go-git/v5"
283+ "github.com/go-git/go-git/v5/plumbing/object"
284+)
285+
286 const defaultReadme = "# Smoothie\nWelcome to Smoothie. To setup your own configuration, please clone this repo."
287
288 const defaultConfig = `{
289@@ -13,3 +22,68 @@ const defaultConfig = `{
290 }
291 ]
292 }`
293+
294+func createFile(path string, content string) error {
295+ f, err := os.Create(path)
296+ if err != nil {
297+ return err
298+ }
299+ defer f.Close()
300+ _, err = f.WriteString(content)
301+ if err != nil {
302+ return err
303+ }
304+ return f.Sync()
305+}
306+
307+func createDefaultConfigRepo(rs *git.RepoSource) error {
308+ cn := "config"
309+ err := rs.LoadRepos()
310+ cr, err := rs.GetRepo(cn)
311+ if err == git.ErrMissingRepo {
312+ cr, err = rs.InitRepo(cn, false)
313+ if err != nil {
314+ return err
315+ }
316+
317+ rp := filepath.Join(rs.Path, cn, "README.md")
318+ err = createFile(rp, defaultReadme)
319+ if err != nil {
320+ return err
321+ }
322+ cp := filepath.Join(rs.Path, cn, "config.json")
323+ err = createFile(cp, defaultConfig)
324+ if err != nil {
325+ return err
326+ }
327+ wt, err := cr.Repository.Worktree()
328+ if err != nil {
329+ return err
330+ }
331+ _, err = wt.Add("README.md")
332+ if err != nil {
333+ return err
334+ }
335+ _, err = wt.Add("config.json")
336+ if err != nil {
337+ return err
338+ }
339+ _, err = wt.Commit("Default init", &gg.CommitOptions{
340+ All: true,
341+ Author: &object.Signature{
342+ Name: "Smoothie Server",
343+ Email: "vt100@charm.sh",
344+ },
345+ })
346+ if err != nil {
347+ return err
348+ }
349+ err = rs.LoadRepos()
350+ if err != nil {
351+ return err
352+ }
353+ } else if err != nil {
354+ return err
355+ }
356+ return nil
357+}