37950203a7110c0061aed869deaec1cf3b486c2f
- Author
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Committer
- Ayman Bagabas <ayman.bagabas@gmail.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/internal/git/git.go b/internal/git/git.go
2index cf2b09d37bfdbb3bcea2ae0ec3daab12e26aa222..7cbd469849e185d641c700fae01a0a74a72c8e2e 100644
3--- a/internal/git/git.go
4+++ b/internal/git/git.go
5@@ -1,6 +1,7 @@
6 package git
7
8 import (
9+ "context"
10 "errors"
11 "log"
12 "os"
13@@ -30,6 +31,7 @@ type Repo struct {
14 refs []*plumbing.Reference
15 trees map[plumbing.Hash]*object.Tree
16 commits map[plumbing.Hash]*object.Commit
17+ patch map[plumbing.Hash]*object.Patch
18 }
19
20 // GetName returns the name of the repository.
21@@ -105,6 +107,40 @@ func (r *Repo) commitForHash(hash plumbing.Hash) (*object.Commit, error) {
22 return co, nil
23 }
24
25+func (r *Repo) PatchCtx(ctx context.Context, commit *object.Commit) (*object.Patch, error) {
26+ hash := commit.Hash
27+ p, ok := r.patch[hash]
28+ if !ok {
29+ c, err := r.commitForHash(hash)
30+ if err != nil {
31+ return nil, err
32+ }
33+ // Using commit trees fixes the issue when generating diff for the first commit
34+ // https://github.com/go-git/go-git/issues/281
35+ tree, err := r.treeForHash(c.TreeHash)
36+ if err != nil {
37+ return nil, err
38+ }
39+ var parent *object.Commit
40+ parentTree := &object.Tree{}
41+ if c.NumParents() > 0 {
42+ parent, err = r.commitForHash(c.ParentHashes[0])
43+ if err != nil {
44+ return nil, err
45+ }
46+ parentTree, err = r.treeForHash(parent.TreeHash)
47+ if err != nil {
48+ return nil, err
49+ }
50+ }
51+ p, err = parentTree.PatchContext(ctx, tree)
52+ if err != nil {
53+ return nil, err
54+ }
55+ }
56+ return p, nil
57+}
58+
59 // GetCommits returns the commits for a repository.
60 func (r *Repo) GetCommits(ref *plumbing.Reference) (gitypes.Commits, error) {
61 hash, err := r.targetHash(ref)
62@@ -264,6 +300,7 @@ func (rs *RepoSource) loadRepo(name string, rg *git.Repository) (*Repo, error) {
63 r := &Repo{
64 name: name,
65 repository: rg,
66+ patch: make(map[plumbing.Hash]*object.Patch),
67 }
68 r.commits = make(map[plumbing.Hash]*object.Commit)
69 r.trees = make(map[plumbing.Hash]*object.Tree)
70diff --git a/internal/tui/bubbles/git/log/bubble.go b/internal/tui/bubbles/git/log/bubble.go
71index 600011791a4424921cd0a12d8f4daf6ef0e3bf0c..95e6b7b5598a937b3a7c1b762be43f0b8150d1fa 100644
72--- a/internal/tui/bubbles/git/log/bubble.go
73+++ b/internal/tui/bubbles/git/log/bubble.go
74@@ -9,6 +9,7 @@ import (
75 "time"
76
77 "github.com/charmbracelet/bubbles/list"
78+ "github.com/charmbracelet/bubbles/spinner"
79 "github.com/charmbracelet/bubbles/viewport"
80 tea "github.com/charmbracelet/bubbletea"
81 gansi "github.com/charmbracelet/glamour/ansi"
82@@ -26,21 +27,17 @@ var (
83 Code: "",
84 Language: "diff",
85 }
86+ waitBeforeLoading = time.Millisecond * 300
87 )
88
89-type commitMsg struct {
90- commit *object.Commit
91- parent *object.Commit
92- tree *object.Tree
93- parentTree *object.Tree
94- patch *object.Patch
95-}
96+type commitMsg *object.Commit
97
98 type sessionState int
99
100 const (
101 logState sessionState = iota
102 commitState
103+ loadingState
104 errorState
105 )
106
107@@ -100,6 +97,7 @@ type Bubble struct {
108 height int
109 heightMargin int
110 error types.ErrMsg
111+ spinner spinner.Model
112 }
113
114 func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height, heightMargin int) *Bubble {
115@@ -113,6 +111,9 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height
116 l.DisableQuitKeybindings()
117 l.KeyMap.NextPage = types.NextPage
118 l.KeyMap.PrevPage = types.PrevPage
119+ s := spinner.New()
120+ s.Spinner = spinner.Dot
121+ s.Style = styles.Spinner
122 b := &Bubble{
123 commitViewport: &vp.ViewportBubble{
124 Viewport: &viewport.Model{},
125@@ -126,6 +127,7 @@ func NewBubble(repo types.Repo, styles *style.Styles, width, widthMargin, height
126 heightMargin: heightMargin,
127 list: l,
128 ref: repo.GetHEAD(),
129+ spinner: s,
130 }
131 b.SetSize(width, height)
132 return b
133@@ -193,12 +195,19 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
134 b.state = errorState
135 return b, nil
136 case commitMsg:
137- content := b.renderCommit(msg)
138- b.state = commitState
139- b.commitViewport.Viewport.SetContent(content)
140- b.GotoTop()
141+ if b.state == loadingState {
142+ cmds = append(cmds, b.spinner.Tick)
143+ }
144 case refs.RefMsg:
145 b.ref = msg
146+ case spinner.TickMsg:
147+ if b.state == loadingState {
148+ s, cmd := b.spinner.Update(msg)
149+ if cmd != nil {
150+ cmds = append(cmds, cmd)
151+ }
152+ b.spinner = s
153+ }
154 }
155
156 switch b.state {
157@@ -215,83 +224,77 @@ func (b *Bubble) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
158 return b, tea.Batch(cmds...)
159 }
160
161+func (b *Bubble) loadPatch(c *object.Commit) error {
162+ var patch strings.Builder
163+ style := b.style.LogCommit.Copy().Width(b.width - b.widthMargin - b.style.LogCommit.GetHorizontalFrameSize())
164+ ctx, cancel := context.WithTimeout(context.TODO(), types.MaxPatchWait)
165+ defer cancel()
166+ p, err := b.repo.PatchCtx(ctx, c)
167+ if err != nil {
168+ return err
169+ }
170+ patch.WriteString(b.renderCommit(c))
171+ fpl := len(p.FilePatches())
172+ if fpl > types.MaxDiffFiles {
173+ patch.WriteString("\n" + types.ErrDiffFilesTooLong.Error())
174diff --git a/internal/tui/bubbles/git/types/git.go b/internal/tui/bubbles/git/types/git.go
175index 758f9d126eb39b2018ba03c4f70e869df4b555b8..05a1c26114c178ee6e08286c3687c7a187c6b95c 100644
176--- a/internal/tui/bubbles/git/types/git.go
177+++ b/internal/tui/bubbles/git/types/git.go
178@@ -1,6 +1,8 @@
179 package types
180
181 import (
182+ "context"
183+
184 "github.com/go-git/go-git/v5"
185 "github.com/go-git/go-git/v5/plumbing"
186 "github.com/go-git/go-git/v5/plumbing/object"
187@@ -15,6 +17,7 @@ type Repo interface {
188 GetCommits(*plumbing.Reference) (Commits, error)
189 Repository() *git.Repository
190 Tree(*plumbing.Reference, string) (*object.Tree, error)
191+ PatchCtx(context.Context, *object.Commit) (*object.Patch, error)
192 }
193
194 type Commits []*object.Commit
195diff --git a/internal/tui/style/style.go b/internal/tui/style/style.go
196index 1f57cb5b763cd83ea39c5add97521545ab2ac6eb..bc997ed31d03c6d46ad65931995f307bdca62393 100644
197--- a/internal/tui/style/style.go
198+++ b/internal/tui/style/style.go
199@@ -65,6 +65,8 @@ type Styles struct {
200 TreeFileMode lipgloss.Style
201 TreeFileSize lipgloss.Style
202 TreeFileContent lipgloss.Style
203+
204+ Spinner lipgloss.Style
205 }
206
207 // DefaultStyles returns default styles for the TUI.
208@@ -252,5 +254,9 @@ func DefaultStyles() *Styles {
209
210 s.TreeFileContent = lipgloss.NewStyle()
211
212+ s.Spinner = lipgloss.NewStyle().
213+ MarginLeft(1).
214+ Foreground(lipgloss.Color("205"))
215+
216 return s
217 }