Refactor RepoSource

Toby Padilla created

Change summary

git/git.go      | 32 ++++++++++++++++++++++----------
tui/bubble.go   | 39 ++++++++++++++++-----------------------
tui/commands.go |  9 ++++++++-
3 files changed, 46 insertions(+), 34 deletions(-)

Detailed changes

git/git.go 🔗

@@ -11,9 +11,15 @@ import (
 	"github.com/go-git/go-git/v5/plumbing/object"
 )
 
+type Repo struct {
+	Name        string
+	Repository  *git.Repository
+	Readme      string
+	LastUpdated *time.Time
+}
+
 type RepoCommit struct {
 	Name   string
-	Repo   *git.Repository
 	Commit *object.Commit
 }
 
@@ -28,22 +34,22 @@ func (cl CommitLog) Less(i, j int) bool {
 type RepoSource struct {
 	mtx     sync.Mutex
 	path    string
-	repos   []*git.Repository
+	repos   []*Repo
 	commits CommitLog
 }
 
-func NewRepoSource(repoPath string) *RepoSource {
+func NewRepoSource(repoPath string, poll time.Duration) *RepoSource {
 	rs := &RepoSource{path: repoPath}
 	go func() {
 		for {
 			rs.loadRepos()
-			time.Sleep(time.Second * 10)
+			time.Sleep(poll)
 		}
 	}()
 	return rs
 }
 
-func (rs *RepoSource) AllRepos() []*git.Repository {
+func (rs *RepoSource) AllRepos() []*Repo {
 	rs.mtx.Lock()
 	defer rs.mtx.Unlock()
 	return rs.repos
@@ -65,19 +71,25 @@ func (rs *RepoSource) loadRepos() {
 	if err != nil {
 		return
 	}
-	rs.repos = make([]*git.Repository, 0)
+	rs.repos = make([]*Repo, 0)
 	rs.commits = make([]RepoCommit, 0)
-	for _, rd := range rd {
-		r, err := git.PlainOpen(rs.path + string(os.PathSeparator) + rd.Name())
+	for _, de := range rd {
+		rn := de.Name()
+		r := &Repo{Name: rn}
+		rg, err := git.PlainOpen(rs.path + string(os.PathSeparator) + rn)
 		if err != nil {
 			log.Fatal(err)
 		}
-		l, err := r.Log(&git.LogOptions{All: true})
+		r.Repository = rg
+		l, err := rg.Log(&git.LogOptions{All: true})
 		if err != nil {
 			log.Fatal(err)
 		}
 		l.ForEach(func(c *object.Commit) error {
-			rs.commits = append(rs.commits, RepoCommit{Name: rd.Name(), Repo: r, Commit: c})
+			if r.LastUpdated == nil {
+				r.LastUpdated = &c.Author.When
+			}
+			rs.commits = append(rs.commits, RepoCommit{Name: rn, Commit: c})
 			return nil
 		})
 		sort.Sort(rs.commits)

tui/bubble.go 🔗

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"smoothie/git"
 	"smoothie/tui/bubbles/commits"
+	"time"
 
 	tea "github.com/charmbracelet/bubbletea"
 	"github.com/gliderlabs/ssh"
@@ -19,28 +20,6 @@ const (
 	quitState
 )
 
-type stateMsg struct{ state sessionState }
-type infoMsg struct{ text string }
-type errMsg struct{ err error }
-
-func (e errMsg) Error() string {
-	return e.err.Error()
-}
-
-func SessionHandler(reposPath string) func(ssh.Session) (tea.Model, []tea.ProgramOption) {
-	rs := git.NewRepoSource(reposPath)
-	return func(s ssh.Session) (tea.Model, []tea.ProgramOption) {
-		if len(s.Command()) == 0 {
-			pty, changes, active := s.Pty()
-			if !active {
-				return nil, nil
-			}
-			return NewModel(pty.Window.Width, pty.Window.Height, changes, rs), []tea.ProgramOption{tea.WithAltScreen()}
-		}
-		return nil, nil
-	}
-}
-
 type Model struct {
 	state          sessionState
 	error          string
@@ -64,7 +43,7 @@ func NewModel(width int, height int, windowChanges <-chan ssh.Window, repoSource
 }
 
 func (m *Model) Init() tea.Cmd {
-	return tea.Batch(m.windowChangesCmd, m.getCommitsCmd)
+	return tea.Batch(m.windowChangesCmd, m.loadGitCmd)
 }
 
 func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
@@ -114,3 +93,17 @@ func (m *Model) View() string {
 	content = h + "\n" + s + "\n" + f
 	return appBoxStyle.Render(content)
 }
+
+func SessionHandler(reposPath string) func(ssh.Session) (tea.Model, []tea.ProgramOption) {
+	rs := git.NewRepoSource(reposPath, time.Second*10)
+	return func(s ssh.Session) (tea.Model, []tea.ProgramOption) {
+		if len(s.Command()) == 0 {
+			pty, changes, active := s.Pty()
+			if !active {
+				return nil, nil
+			}
+			return NewModel(pty.Window.Width, pty.Window.Height, changes, rs), []tea.ProgramOption{tea.WithAltScreen()}
+		}
+		return nil, nil
+	}
+}

tui/commands.go 🔗

@@ -6,7 +6,14 @@ import (
 	tea "github.com/charmbracelet/bubbletea"
 )
 
+type stateMsg struct{ state sessionState }
+type infoMsg struct{ text string }
 type windowMsg struct{}
+type errMsg struct{ err error }
+
+func (e errMsg) Error() string {
+	return e.err.Error()
+}
 
 func (m *Model) windowChangesCmd() tea.Msg {
 	w := <-m.windowChanges
@@ -15,7 +22,7 @@ func (m *Model) windowChangesCmd() tea.Msg {
 	return windowMsg{}
 }
 
-func (m *Model) getCommitsCmd() tea.Msg {
+func (m *Model) loadGitCmd() tea.Msg {
 	m.commitTimeline = commits.NewBubble(m.height, 2, 80, m.repoSource.GetCommits(200))
 	m.state = loadedState
 	return nil