5
5
"regexp"
6
6
"strconv"
7
7
"strings"
8
+ "time"
8
9
9
10
"github.com/jesseduffield/generics/set"
10
11
"github.com/jesseduffield/go-git/v5/config"
@@ -14,6 +15,7 @@ import (
14
15
"github.com/jesseduffield/lazygit/pkg/utils"
15
16
"github.com/samber/lo"
16
17
"golang.org/x/exp/slices"
18
+ "golang.org/x/sync/errgroup"
17
19
)
18
20
19
21
// context:
@@ -63,7 +65,13 @@ func NewBranchLoader(
63
65
}
64
66
65
67
// Load the list of branches for the current repo
66
- func (self * BranchLoader ) Load (reflogCommits []* models.Commit ) ([]* models.Branch , error ) {
68
+ func (self * BranchLoader ) Load (reflogCommits []* models.Commit ,
69
+ mainBranches * MainBranches ,
70
+ oldBranches []* models.Branch ,
71
+ loadBehindCounts bool ,
72
+ onWorker func (func () error ),
73
+ renderFunc func (),
74
+ ) ([]* models.Branch , error ) {
67
75
branches := self .obtainBranches (self .version .IsAtLeast (2 , 22 , 0 ))
68
76
69
77
if self .AppState .LocalBranchSortOrder == "recency" {
@@ -122,11 +130,75 @@ func (self *BranchLoader) Load(reflogCommits []*models.Commit) ([]*models.Branch
122
130
branch .UpstreamRemote = match .Remote
123
131
branch .UpstreamBranch = match .Merge .Short ()
124
132
}
133
+
134
+ // If the branch already existed, take over its BehindBaseBranch value
135
+ // to reduce flicker
136
+ if oldBranch , found := lo .Find (oldBranches , func (b * models.Branch ) bool {
137
+ return b .Name == branch .Name
138
+ }); found {
139
+ branch .BehindBaseBranch .Store (oldBranch .BehindBaseBranch .Load ())
140
+ }
141
+ }
142
+
143
+ if loadBehindCounts && self .UserConfig .Gui .ShowDivergenceFromBaseBranch != "none" {
144
+ onWorker (func () error {
145
+ return self .GetBehindBaseBranchValuesForAllBranches (branches , mainBranches , renderFunc )
146
+ })
125
147
}
126
148
127
149
return branches , nil
128
150
}
129
151
152
+ func (self * BranchLoader ) GetBehindBaseBranchValuesForAllBranches (
153
+ branches []* models.Branch ,
154
+ mainBranches * MainBranches ,
155
+ renderFunc func (),
156
+ ) error {
157
+ mainBranchRefs := mainBranches .Get ()
158
+ if len (mainBranchRefs ) == 0 {
159
+ return nil
160
+ }
161
+
162
+ t := time .Now ()
163
+ errg := errgroup.Group {}
164
+
165
+ for _ , branch := range branches {
166
+ errg .Go (func () error {
167
+ baseBranch , err := self .GetBaseBranch (branch , mainBranches )
168
+ if err != nil {
169
+ return err
170
+ }
171
+ behind := 0 // prime it in case something below fails
172
+ if baseBranch != "" {
173
+ output , err := self .cmd .New (
174
+ NewGitCmd ("rev-list" ).
175
+ Arg ("--left-right" ).
176
+ Arg ("--count" ).
177
+ Arg (fmt .Sprintf ("%s...%s" , branch .FullRefName (), baseBranch )).
178
+ ToArgv (),
179
+ ).DontLog ().RunWithOutput ()
180
+ if err != nil {
181
+ return err
182
+ }
183
+ // The format of the output is "<ahead>\t<behind>"
184
+ aheadBehindStr := strings .Split (strings .TrimSpace (output ), "\t " )
185
+ if len (aheadBehindStr ) == 2 {
186
+ if value , err := strconv .Atoi (aheadBehindStr [1 ]); err == nil {
187
+ behind = value
188
+ }
189
+ }
190
+ }
191
+ branch .BehindBaseBranch .Store (int32 (behind ))
192
+ return nil
193
+ })
194
+ }
195
+
196
+ err := errg .Wait ()
197
+ self .Log .Debugf ("time to get behind base branch values for all branches: %s" , time .Since (t ))
198
+ renderFunc ()
199
+ return err
200
+ }
201
+
130
202
// Find the base branch for the given branch (i.e. the main branch that the
131
203
// given branch was forked off of)
132
204
//
0 commit comments