1package tui
2
3import (
4 "log"
5 "os"
6 "sort"
7 "sync"
8 "time"
9
10 "github.com/go-git/go-git/v5"
11 "github.com/go-git/go-git/v5/plumbing/object"
12)
13
14type commitLog []*object.Commit
15
16func (cl commitLog) Len() int { return len(cl) }
17func (cl commitLog) Swap(i, j int) { cl[i], cl[j] = cl[j], cl[i] }
18func (cl commitLog) Less(i, j int) bool { return cl[i].Author.When.After(cl[j].Author.When) }
19
20type repoSource struct {
21 mtx sync.Mutex
22 path string
23 repos []*git.Repository
24 commits commitLog
25}
26
27func newRepoSource(repoPath string) *repoSource {
28 rs := &repoSource{path: repoPath}
29 go func() {
30 for {
31 rs.loadRepos()
32 time.Sleep(time.Second * 10)
33 }
34 }()
35 return rs
36}
37
38func (rs *repoSource) allRepos() []*git.Repository {
39 rs.mtx.Lock()
40 defer rs.mtx.Unlock()
41 return rs.repos
42}
43
44func (rs *repoSource) getCommits(limit int) []*object.Commit {
45 rs.mtx.Lock()
46 defer rs.mtx.Unlock()
47 if limit > len(rs.commits) {
48 limit = len(rs.commits)
49 }
50 return rs.commits[:limit]
51}
52
53func (rs *repoSource) loadRepos() {
54 rs.mtx.Lock()
55 defer rs.mtx.Unlock()
56 rd, err := os.ReadDir(rs.path)
57 if err != nil {
58 return
59 }
60 rs.repos = make([]*git.Repository, 0)
61 rs.commits = make([]*object.Commit, 0)
62 for _, rd := range rd {
63 r, err := git.PlainOpen(rs.path + string(os.PathSeparator) + rd.Name())
64 if err != nil {
65 log.Fatal(err)
66 }
67 l, err := r.Log(&git.LogOptions{All: true})
68 if err != nil {
69 log.Fatal(err)
70 }
71 l.ForEach(func(c *object.Commit) error {
72 rs.commits = append(rs.commits, c)
73 return nil
74 })
75 sort.Sort(rs.commits)
76 rs.repos = append(rs.repos, r)
77 }
78}