Skip to content

Commit 64cd026

Browse files
committed
Multiple GitGraph improvements.
Add backend support for excluding PRs, selecting branches and files. Fix go-gitea#10327 Signed-off-by: Andrew Thornton <[email protected]>
1 parent e204398 commit 64cd026

File tree

18 files changed

+409
-71
lines changed

18 files changed

+409
-71
lines changed

modules/context/pagination.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ func (p *Pagination) AddParam(ctx *Context, paramKey string, ctxKey string) {
3737
p.urlParams = append(p.urlParams, urlParam)
3838
}
3939

40+
// AddParamString adds a string parameter directly
41+
func (p *Pagination) AddParamString(key string, value string) {
42+
urlParam := fmt.Sprintf("%s=%v", url.QueryEscape(key), url.QueryEscape(value))
43+
p.urlParams = append(p.urlParams, urlParam)
44+
}
45+
4046
// GetParams returns the configured URL params
4147
func (p *Pagination) GetParams() template.URL {
4248
return template.URL(strings.Join(p.urlParams, "&"))

modules/context/repo.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ func (r *Repository) GetCommitsCount() (int64, error) {
157157
})
158158
}
159159

160+
// GetCommitGraphsCount returns cached commit count for current view
161+
func (r *Repository) GetCommitGraphsCount(hidePRRefs bool, branches []string, files []string) (int64, error) {
162+
cacheKey := fmt.Sprintf("commits-count-%d-graph-%t-%s-%s", r.Repository.ID, hidePRRefs, branches, files)
163+
164+
return cache.GetInt64(cacheKey, func() (int64, error) {
165+
if len(branches) == 0 {
166+
return git.AllCommitsCount(r.Repository.RepoPath(), hidePRRefs, files...)
167+
}
168+
return git.CommitsCountFiles(r.Repository.RepoPath(), branches, files)
169+
})
170+
}
171+
160172
// BranchNameSubURL sub-URL for the BranchName field
161173
func (r *Repository) BranchNameSubURL() string {
162174
switch {

modules/git/commit.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,28 @@ func CommitChangesWithArgs(repoPath string, args []string, opts CommitChangesOpt
262262
}
263263

264264
// AllCommitsCount returns count of all commits in repository
265-
func AllCommitsCount(repoPath string) (int64, error) {
266-
stdout, err := NewCommand("rev-list", "--all", "--count").RunInDir(repoPath)
265+
func AllCommitsCount(repoPath string, hidePRRefs bool, files ...string) (int64, error) {
266+
args := []string{"--all", "--count"}
267+
if hidePRRefs {
268+
args = append([]string{"--exclude=refs/pull/*"}, args...)
269+
}
270+
cmd := NewCommand("rev-list")
271+
cmd.AddArguments(args...)
272+
if len(files) > 0 {
273+
cmd.AddArguments("--")
274+
cmd.AddArguments(files...)
275+
}
276+
277+
stdout, err := cmd.RunInDir(repoPath)
267278
if err != nil {
268279
return 0, err
269280
}
270281

271282
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
272283
}
273284

274-
func commitsCount(repoPath string, revision, relpath []string) (int64, error) {
285+
// CommitsCountFiles returns number of total commits of until given revision.
286+
func CommitsCountFiles(repoPath string, revision, relpath []string) (int64, error) {
275287
cmd := NewCommand("rev-list", "--count")
276288
cmd.AddArguments(revision...)
277289
if len(relpath) > 0 {
@@ -288,8 +300,8 @@ func commitsCount(repoPath string, revision, relpath []string) (int64, error) {
288300
}
289301

290302
// CommitsCount returns number of total commits of until given revision.
291-
func CommitsCount(repoPath, revision string) (int64, error) {
292-
return commitsCount(repoPath, []string{revision}, []string{})
303+
func CommitsCount(repoPath string, revision ...string) (int64, error) {
304+
return CommitsCountFiles(repoPath, revision, []string{})
293305
}
294306

295307
// CommitsCount returns number of total commits of until current revision.

modules/git/ref.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
package git
66

7+
import "strings"
8+
79
// Reference represents a Git ref.
810
type Reference struct {
911
Name string
@@ -16,3 +18,44 @@ type Reference struct {
1618
func (ref *Reference) Commit() (*Commit, error) {
1719
return ref.repo.getCommit(ref.Object)
1820
}
21+
22+
// ShortName returns the short name of the reference
23+
func (ref *Reference) ShortName() string {
24+
if ref == nil {
25+
return ""
26+
}
27+
if strings.HasPrefix(ref.Name, "refs/heads/") {
28+
return ref.Name[11:]
29+
}
30+
if strings.HasPrefix(ref.Name, "refs/tags/") {
31+
return ref.Name[10:]
32+
}
33+
if strings.HasPrefix(ref.Name, "refs/remotes/") {
34+
return ref.Name[13:]
35+
}
36+
if strings.HasPrefix(ref.Name, "refs/pull/") && strings.IndexByte(ref.Name[10:], '/') > -1 {
37+
return ref.Name[10 : strings.IndexByte(ref.Name[10:], '/')+10]
38+
}
39+
40+
return ref.Name
41+
}
42+
43+
// RefGroup returns the group type of the reference
44+
func (ref *Reference) RefGroup() string {
45+
if ref == nil {
46+
return ""
47+
}
48+
if strings.HasPrefix(ref.Name, "refs/heads/") {
49+
return "heads"
50+
}
51+
if strings.HasPrefix(ref.Name, "refs/tags/") {
52+
return "tags"
53+
}
54+
if strings.HasPrefix(ref.Name, "refs/remotes/") {
55+
return "remotes"
56+
}
57+
if strings.HasPrefix(ref.Name, "refs/pull/") && strings.IndexByte(ref.Name[10:], '/') > -1 {
58+
return "pull"
59+
}
60+
return ""
61+
}

modules/git/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const prettyLogFormat = `--pretty=format:%H`
4949

5050
// GetAllCommitsCount returns count of all commits in repository
5151
func (repo *Repository) GetAllCommitsCount() (int64, error) {
52-
return AllCommitsCount(repo.Path)
52+
return AllCommitsCount(repo.Path, false)
5353
}
5454

5555
func (repo *Repository) parsePrettyFormatLogToList(logs []byte) (*list.List, error) {

modules/git/repo_commit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bo
318318

319319
// FileCommitsCount return the number of files at a revison
320320
func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
321-
return commitsCount(repo.Path, []string{revision}, []string{file})
321+
return CommitsCountFiles(repo.Path, []string{revision}, []string{file})
322322
}
323323

324324
// CommitsByFileAndRange return the commits according revison file and the page
@@ -413,11 +413,11 @@ func (repo *Repository) CommitsBetweenIDs(last, before string) (*list.List, erro
413413

414414
// CommitsCountBetween return numbers of commits between two commits
415415
func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
416-
count, err := commitsCount(repo.Path, []string{start + "..." + end}, []string{})
416+
count, err := CommitsCountFiles(repo.Path, []string{start + "..." + end}, []string{})
417417
if err != nil && strings.Contains(err.Error(), "no merge base") {
418418
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
419419
// previously it would return the results of git rev-list before last so let's try that...
420-
return commitsCount(repo.Path, []string{start, end}, []string{})
420+
return CommitsCountFiles(repo.Path, []string{start, end}, []string{})
421421
}
422422

423423
return count, err

modules/gitgraph/graph.go

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,42 @@ import (
1717
)
1818

1919
// GetCommitGraph return a list of commit (GraphItems) from all branches
20-
func GetCommitGraph(r *git.Repository, page int, maxAllowedColors int) (*Graph, error) {
21-
format := "DATA:%d|%H|%ad|%an|%ae|%h|%s"
20+
func GetCommitGraph(r *git.Repository, page int, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) {
21+
format := "DATA:%D|%H|%ad|%an|%ae|%h|%s"
2222

2323
if page == 0 {
2424
page = 1
2525
}
2626

27-
graphCmd := git.NewCommand("log")
28-
graphCmd.AddArguments("--graph",
29-
"--date-order",
30-
"--all",
27+
args := make([]string, 0, 12+len(branches)+len(files))
28+
29+
args = append(args, "--graph", "--date-order", "--decorate=full")
30+
31+
if hidePRRefs {
32+
args = append(args, "--exclude=refs/pull/*")
33+
}
34+
35+
if len(branches) == 0 {
36+
args = append(args, "--all")
37+
}
38+
39+
args = append(args,
3140
"-C",
3241
"-M",
3342
fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page),
3443
"--date=iso",
35-
fmt.Sprintf("--pretty=format:%s", format),
36-
)
44+
fmt.Sprintf("--pretty=format:%s", format))
45+
46+
if len(branches) > 0 {
47+
args = append(args, branches...)
48+
}
49+
args = append(args, "--")
50+
if len(files) > 0 {
51+
args = append(args, files...)
52+
}
53+
54+
graphCmd := git.NewCommand("log")
55+
graphCmd.AddArguments(args...)
3756
graph := NewGraph()
3857

3958
stderr := new(strings.Builder)

modules/gitgraph/graph_models.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ package gitgraph
77
import (
88
"bytes"
99
"fmt"
10+
11+
"code.gitea.io/gitea/modules/git"
1012
)
1113

1214
// NewGraph creates a basic graph
@@ -150,7 +152,7 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
150152
Row: row,
151153
Column: column,
152154
// 0 matches git log --pretty=format:%d => ref names, like the --decorate option of git-log(1)
153-
Branch: string(data[0]),
155+
Refs: newRefsFromRefNames(data[0]),
154156
// 1 matches git log --pretty=format:%H => commit hash
155157
Rev: string(data[1]),
156158
// 2 matches git log --pretty=format:%ad => author date (format respects --date= option)
@@ -166,12 +168,32 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
166168
}, nil
167169
}
168170

171+
func newRefsFromRefNames(refNames []byte) []git.Reference {
172+
refBytes := bytes.Split(refNames, []byte{',', ' '})
173+
refs := make([]git.Reference, 0, len(refBytes))
174+
for _, refNameBytes := range refBytes {
175+
if len(refNameBytes) == 0 {
176+
continue
177+
}
178+
refName := string(refNameBytes)
179+
if refName[0:5] == "tag: " {
180+
refName = refName[5:]
181+
} else if refName[0:8] == "HEAD -> " {
182+
refName = refName[8:]
183+
}
184+
refs = append(refs, git.Reference{
185+
Name: refName,
186+
})
187+
}
188+
return refs
189+
}
190+
169191
// Commit represents a commit at co-ordinate X, Y with the data
170192
type Commit struct {
171193
Flow int64
172194
Row int
173195
Column int
174-
Branch string
196+
Refs []git.Reference
175197
Rev string
176198
Date string
177199
Author string

modules/gitgraph/graph_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func BenchmarkGetCommitGraph(b *testing.B) {
2222
defer currentRepo.Close()
2323

2424
for i := 0; i < b.N; i++ {
25-
graph, err := GetCommitGraph(currentRepo, 1, 0)
25+
graph, err := GetCommitGraph(currentRepo, 1, 0, false, nil, nil)
2626
if err != nil {
2727
b.Error("Could get commit graph")
2828
}

modules/templates/helper.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"mime"
1717
"net/url"
1818
"path/filepath"
19+
"reflect"
1920
"regexp"
2021
"runtime"
2122
"strings"
@@ -309,6 +310,26 @@ func NewFuncMap() []template.FuncMap {
309310
"EventSourceUpdateTime": int(setting.UI.Notification.EventSourceUpdateTime / time.Millisecond),
310311
}
311312
},
313+
"containGeneric": func(arr interface{}, v interface{}) bool {
314+
arrV := reflect.ValueOf(arr)
315+
if arrV.Kind() == reflect.String && reflect.ValueOf(v).Kind() == reflect.String {
316+
return strings.Contains(arr.(string), v.(string))
317+
}
318+
319+
if arrV.Kind() == reflect.Slice {
320+
for i := 0; i < arrV.Len(); i++ {
321+
iV := arrV.Index(i)
322+
if !iV.CanInterface() {
323+
continue
324+
}
325+
if iV.Interface() == v {
326+
return true
327+
}
328+
}
329+
}
330+
331+
return false
332+
},
312333
"contain": func(s []int64, id int64) bool {
313334
for i := 0; i < len(s); i++ {
314335
if s[i] == id {

options/locale/locale_en-US.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,8 @@ audio_not_supported_in_browser = Your browser does not support the HTML5 'audio'
785785
stored_lfs = Stored with Git LFS
786786
symbolic_link = Symbolic link
787787
commit_graph = Commit Graph
788+
commit_graph.select = Select branches to show...
789+
commit_graph.hide_pr_refs = Hide PRs
788790
commit_graph.monochrome = Mono
789791
commit_graph.color = Color
790792
blame = Blame

0 commit comments

Comments
 (0)