Skip to content

Commit f54fb3c

Browse files
authored
Parallelize time-consuming parts when there are many local branches (#130)
1 parent 67aa4cc commit f54fb3c

File tree

1 file changed

+96
-38
lines changed

1 file changed

+96
-38
lines changed

cmd/root.go

Lines changed: 96 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"sort"
1111
"strconv"
1212
"strings"
13+
"sync"
1314

1415
"github.com/pkg/errors"
1516
"github.com/seachicken/gh-poi/shared"
@@ -90,6 +91,7 @@ func GetBranches(ctx context.Context, remote shared.Remote, connection shared.Co
9091

9192
func loadBranches(ctx context.Context, remote shared.Remote, defaultBranchName string, repoNames []string, connection shared.Connection) ([]shared.Branch, error) {
9293
var branches []shared.Branch
94+
9395
if names, err := connection.GetBranchNames(ctx); err == nil {
9496
branches = ToBranch(SplitLines(names))
9597
branches = applyDefault(branches, defaultBranchName)
@@ -117,17 +119,46 @@ func loadBranches(ctx context.Context, remote shared.Remote, defaultBranchName s
117119
prs := []shared.PullRequest{}
118120
orgs := shared.GetQueryOrgs(repoNames)
119121
repos := shared.GetQueryRepos(repoNames)
120-
for _, queryHashes := range shared.GetQueryHashes(branches) {
121-
json, err := connection.GetPullRequests(ctx, remote.Hostname, orgs, repos, queryHashes)
122-
if err != nil {
123-
return nil, err
124-
}
125122

126-
pr, err := toPullRequests(json)
127-
if err != nil {
128-
return nil, err
123+
type pullRequestResult struct {
124+
prs []shared.PullRequest
125+
err error
126+
}
127+
128+
queryHashes := shared.GetQueryHashes(branches)
129+
prChan := make(chan pullRequestResult, len(queryHashes))
130+
var wg sync.WaitGroup
131+
132+
for _, queryHash := range queryHashes {
133+
wg.Add(1)
134+
go func(hash string) {
135+
defer wg.Done()
136+
json, err := connection.GetPullRequests(ctx, remote.Hostname, orgs, repos, hash)
137+
if err != nil {
138+
prChan <- pullRequestResult{err: err}
139+
return
140+
}
141+
142+
pr, err := toPullRequests(json)
143+
if err != nil {
144+
prChan <- pullRequestResult{err: err}
145+
return
146+
}
147+
148+
prChan <- pullRequestResult{prs: pr}
149+
}(queryHash)
150+
}
151+
152+
go func() {
153+
wg.Wait()
154+
close(prChan)
155+
}()
156+
157+
for result := range prChan {
158+
if result.err != nil {
159+
return nil, result.err
129160
}
130-
prs = append(prs, pr...)
161+
prs = append(prs, result.prs...)
131162
}
132163

133164
branches = applyPullRequest(ctx, branches, prs, connection)
@@ -226,45 +257,72 @@ func applyProtected(ctx context.Context, branches []shared.Branch, connection sh
226257
}
227258

228259
func applyCommits(ctx context.Context, remote shared.Remote, branches []shared.Branch, defaultBranchName string, connection shared.Connection) ([]shared.Branch, error) {
260+
var wg sync.WaitGroup
261+
262+
type remoteBranchResult struct {
263+
branch shared.Branch
264+
err error
265+
}
266+
229267
results := []shared.Branch{}
268+
resultChan := make(chan remoteBranchResult, len(branches))
230269

231270
for _, branch := range branches {
232-
if branch.Name == defaultBranchName || branch.IsDetached() {
233-
branch.Commits = []string{}
234-
results = append(results, branch)
235-
continue
236-
}
271+
wg.Add(1)
272+
go func(branch shared.Branch) {
273+
defer wg.Done()
274+
275+
if branch.Name == defaultBranchName || branch.IsDetached() {
276+
branch.Commits = []string{}
277+
resultChan <- remoteBranchResult{branch: branch}
278+
return
279+
}
237280

238-
if remoteHeadOid, err := connection.GetRemoteHeadOid(ctx, remote.Name, branch.Name); err == nil {
239-
branch.RemoteHeadOid = SplitLines(remoteHeadOid)[0]
240-
} else {
241-
result, _ := connection.GetConfig(ctx, fmt.Sprintf("branch.%s.remote", branch.Name))
242-
splitResults := SplitLines(result)
243-
if len(splitResults) > 0 {
244-
remoteUrl := splitResults[0]
245-
if result, err := connection.GetLsRemoteHeadOid(ctx, remoteUrl, branch.Name); err == nil {
246-
splitResults := strings.Fields(result)
247-
if len(splitResults) > 0 {
248-
branch.RemoteHeadOid = splitResults[0]
281+
if remoteHeadOid, err := connection.GetRemoteHeadOid(ctx, remote.Name, branch.Name); err == nil {
282+
branch.RemoteHeadOid = SplitLines(remoteHeadOid)[0]
283+
} else {
284+
result, _ := connection.GetConfig(ctx, fmt.Sprintf("branch.%s.remote", branch.Name))
285+
splitResults := SplitLines(result)
286+
if len(splitResults) > 0 {
287+
remoteUrl := splitResults[0]
288+
if result, err := connection.GetLsRemoteHeadOid(ctx, remoteUrl, branch.Name); err == nil {
289+
splitResults := strings.Fields(result)
290+
if len(splitResults) > 0 {
291+
branch.RemoteHeadOid = splitResults[0]
292+
}
249293
}
250294
}
251295
}
252-
}
253296

254-
oids, err := connection.GetLog(ctx, branch.Name)
255-
if err != nil {
256-
return nil, err
257-
}
297+
oids, err := connection.GetLog(ctx, branch.Name)
298+
if err != nil {
299+
resultChan <- remoteBranchResult{err: err}
300+
return
301+
}
258302

259-
trimmedOids, err := trimBranch(
260-
ctx, SplitLines(oids), branch.RemoteHeadOid, branch.IsMerged,
261-
branch.Name, defaultBranchName, connection)
262-
if err != nil {
263-
return nil, err
264-
}
303+
trimmedOids, err := trimBranch(
304+
ctx, SplitLines(oids), branch.RemoteHeadOid, branch.IsMerged,
305+
branch.Name, defaultBranchName, connection)
306+
if err != nil {
307+
resultChan <- remoteBranchResult{err: err}
308+
return
309+
}
265310

266-
branch.Commits = trimmedOids
267-
results = append(results, branch)
311+
branch.Commits = trimmedOids
312+
resultChan <- remoteBranchResult{branch: branch}
313+
}(branch)
314+
}
315+
316+
go func() {
317+
wg.Wait()
318+
close(resultChan)
319+
}()
320+
321+
for result := range resultChan {
322+
if result.err != nil {
323+
return nil, result.err
324+
}
325+
results = append(results, result.branch)
268326
}
269327

270328
return results, nil

0 commit comments

Comments
 (0)