diff options
author | zeripath <art27@cantab.net> | 2020-11-08 17:21:54 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-08 12:21:54 -0500 |
commit | c05a8abc762f868e67dd131d34f45218a0fb95ab (patch) | |
tree | 9aa0909c736933adc895ef830941dca85206ee07 /modules/gitgraph | |
parent | d4e0b286558a68c96b0001a0676099c06067511b (diff) | |
download | gitea-c05a8abc762f868e67dd131d34f45218a0fb95ab.tar.gz gitea-c05a8abc762f868e67dd131d34f45218a0fb95ab.zip |
Multiple GitGraph improvements: Exclude PR heads, Add branch/PR links, Show only certain branches, (#12766)
* Multiple GitGraph improvements.
Add backend support for excluding PRs, selecting branches and files.
Fix #10327
Signed-off-by: Andrew Thornton <art27@cantab.net>
* as per @silverwind
Signed-off-by: Andrew Thornton <art27@cantab.net>
* as per @silverwind
Signed-off-by: Andrew Thornton <art27@cantab.net>
* Only show refs in dropdown we display on the graph
Signed-off-by: Andrew Thornton <art27@cantab.net>
* as per @silverwind
Signed-off-by: Andrew Thornton <art27@cantab.net>
* use flexbox for ui header
Signed-off-by: Andrew Thornton <art27@cantab.net>
* Move Hide Pull Request button to the dropdown
Signed-off-by: Andrew Thornton <art27@cantab.net>
* Add SHA and user pictures
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fix test
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fix test 2
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fixes
* async
* more tweaks
* use tabs in tmpl
Signed-off-by: Andrew Thornton <art27@cantab.net>
* remove commented thing
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fix linting
Signed-off-by: Andrew Thornton <art27@cantab.net>
* Update web_src/js/features/gitgraph.js
Co-authored-by: silverwind <me@silverwind.io>
* graph tweaks
* more tweaks
* add title
Signed-off-by: Andrew Thornton <art27@cantab.net>
* fix loading indicator z-index and position
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'modules/gitgraph')
-rw-r--r-- | modules/gitgraph/graph.go | 35 | ||||
-rw-r--r-- | modules/gitgraph/graph_models.go | 106 | ||||
-rw-r--r-- | modules/gitgraph/graph_test.go | 8 |
3 files changed, 116 insertions, 33 deletions
diff --git a/modules/gitgraph/graph.go b/modules/gitgraph/graph.go index 257e4f3af0..8505678639 100644 --- a/modules/gitgraph/graph.go +++ b/modules/gitgraph/graph.go @@ -17,23 +17,42 @@ import ( ) // GetCommitGraph return a list of commit (GraphItems) from all branches -func GetCommitGraph(r *git.Repository, page int, maxAllowedColors int) (*Graph, error) { - format := "DATA:%d|%H|%ad|%an|%ae|%h|%s" +func GetCommitGraph(r *git.Repository, page int, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) { + format := "DATA:%D|%H|%ad|%h|%s" if page == 0 { page = 1 } - graphCmd := git.NewCommand("log") - graphCmd.AddArguments("--graph", - "--date-order", - "--all", + args := make([]string, 0, 12+len(branches)+len(files)) + + args = append(args, "--graph", "--date-order", "--decorate=full") + + if hidePRRefs { + args = append(args, "--exclude=refs/pull/*") + } + + if len(branches) == 0 { + args = append(args, "--all") + } + + args = append(args, "-C", "-M", fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page), "--date=iso", - fmt.Sprintf("--pretty=format:%s", format), - ) + fmt.Sprintf("--pretty=format:%s", format)) + + if len(branches) > 0 { + args = append(args, branches...) + } + args = append(args, "--") + if len(files) > 0 { + args = append(args, files...) + } + + graphCmd := git.NewCommand("log") + graphCmd.AddArguments(args...) graph := NewGraph() stderr := new(strings.Builder) diff --git a/modules/gitgraph/graph_models.go b/modules/gitgraph/graph_models.go index ea6ba96084..ba168ab19d 100644 --- a/modules/gitgraph/graph_models.go +++ b/modules/gitgraph/graph_models.go @@ -7,6 +7,10 @@ package gitgraph import ( "bytes" "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" ) // NewGraph creates a basic graph @@ -77,6 +81,48 @@ func (graph *Graph) AddCommit(row, column int, flowID int64, data []byte) error return nil } +// LoadAndProcessCommits will load the git.Commits for each commit in the graph, +// the associate the commit with the user author, and check the commit verification +// before finally retrieving the latest status +func (graph *Graph) LoadAndProcessCommits(repository *models.Repository, gitRepo *git.Repository) error { + var err error + + var ok bool + + emails := map[string]*models.User{} + keyMap := map[string]bool{} + + for _, c := range graph.Commits { + if len(c.Rev) == 0 { + continue + } + c.Commit, err = gitRepo.GetCommit(c.Rev) + if err != nil { + return fmt.Errorf("GetCommit: %s Error: %w", c.Rev, err) + } + + if c.Commit.Author != nil { + email := c.Commit.Author.Email + if c.User, ok = emails[email]; !ok { + c.User, _ = models.GetUserByEmail(email) + emails[email] = c.User + } + } + + c.Verification = models.ParseCommitWithSignature(c.Commit) + + _ = models.CalculateTrustStatus(c.Verification, repository, &keyMap) + + statuses, err := models.GetLatestCommitStatus(repository, c.Commit.ID.String(), 0) + if err != nil { + log.Error("GetLatestCommitStatus: %v", err) + } else { + c.Status = models.CalcCommitStatus(statuses) + } + } + return nil +} + // NewFlow creates a new flow func NewFlow(flowID int64, color, row, column int) *Flow { return &Flow{ @@ -142,42 +188,60 @@ var RelationCommit = &Commit{ // NewCommit creates a new commit from a provided line func NewCommit(row, column int, line []byte) (*Commit, error) { - data := bytes.SplitN(line, []byte("|"), 7) - if len(data) < 7 { + data := bytes.SplitN(line, []byte("|"), 5) + if len(data) < 5 { return nil, fmt.Errorf("malformed data section on line %d with commit: %s", row, string(line)) } return &Commit{ Row: row, Column: column, // 0 matches git log --pretty=format:%d => ref names, like the --decorate option of git-log(1) - Branch: string(data[0]), + Refs: newRefsFromRefNames(data[0]), // 1 matches git log --pretty=format:%H => commit hash Rev: string(data[1]), // 2 matches git log --pretty=format:%ad => author date (format respects --date= option) Date: string(data[2]), - // 3 matches git log --pretty=format:%an => author name - Author: string(data[3]), - // 4 matches git log --pretty=format:%ae => author email - AuthorEmail: string(data[4]), - // 5 matches git log --pretty=format:%h => abbreviated commit hash - ShortRev: string(data[5]), - // 6 matches git log --pretty=format:%s => subject - Subject: string(data[6]), + // 3 matches git log --pretty=format:%h => abbreviated commit hash + ShortRev: string(data[3]), + // 4 matches git log --pretty=format:%s => subject + Subject: string(data[4]), }, nil } +func newRefsFromRefNames(refNames []byte) []git.Reference { + refBytes := bytes.Split(refNames, []byte{',', ' '}) + refs := make([]git.Reference, 0, len(refBytes)) + for _, refNameBytes := range refBytes { + if len(refNameBytes) == 0 { + continue + } + refName := string(refNameBytes) + if refName[0:5] == "tag: " { + refName = refName[5:] + } else if refName[0:8] == "HEAD -> " { + refName = refName[8:] + } + refs = append(refs, git.Reference{ + Name: refName, + }) + } + return refs +} + // Commit represents a commit at co-ordinate X, Y with the data type Commit struct { - Flow int64 - Row int - Column int - Branch string - Rev string - Date string - Author string - AuthorEmail string - ShortRev string - Subject string + Commit *git.Commit + User *models.User + Verification *models.CommitVerification + Status *models.CommitStatus + Flow int64 + Row int + Column int + Refs []git.Reference + Rev string + Date string + ShortRev string + Subject string } // OnlyRelation returns whether this a relation only commit diff --git a/modules/gitgraph/graph_test.go b/modules/gitgraph/graph_test.go index ca9d653cee..c2726a731a 100644 --- a/modules/gitgraph/graph_test.go +++ b/modules/gitgraph/graph_test.go @@ -22,7 +22,7 @@ func BenchmarkGetCommitGraph(b *testing.B) { defer currentRepo.Close() for i := 0; i < b.N; i++ { - graph, err := GetCommitGraph(currentRepo, 1, 0) + graph, err := GetCommitGraph(currentRepo, 1, 0, false, nil, nil) if err != nil { b.Error("Could get commit graph") } @@ -34,7 +34,7 @@ func BenchmarkGetCommitGraph(b *testing.B) { } func BenchmarkParseCommitString(b *testing.B) { - testString := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|Kjell Kvinge|kjell@kvinge.biz|4e61bac|Add route for graph" + testString := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|4e61bac|Add route for graph" parser := &Parser{} parser.Reset() @@ -44,7 +44,7 @@ func BenchmarkParseCommitString(b *testing.B) { if err := parser.AddLineToGraph(graph, 0, []byte(testString)); err != nil { b.Error("could not parse teststring") } - if graph.Flows[1].Commits[0].Author != "Kjell Kvinge" { + if graph.Flows[1].Commits[0].Rev != "4e61bacab44e9b4730e44a6615d04098dd3a8eaf" { b.Error("Did not get expected data") } } @@ -244,7 +244,7 @@ func TestParseGlyphs(t *testing.T) { } func TestCommitStringParsing(t *testing.T) { - dataFirstPart := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|Author|user@mail.something|4e61bac|" + dataFirstPart := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|4e61bac|" tests := []struct { shouldPass bool testName string |