]> source.dussan.org Git - gitea.git/commitdiff
Multiple GitGraph improvements: Exclude PR heads, Add branch/PR links, Show only...
authorzeripath <art27@cantab.net>
Sun, 8 Nov 2020 17:21:54 +0000 (17:21 +0000)
committerGitHub <noreply@github.com>
Sun, 8 Nov 2020 17:21:54 +0000 (12:21 -0500)
* 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>
21 files changed:
modules/context/pagination.go
modules/context/repo.go
modules/git/commit.go
modules/git/ref.go
modules/git/repo.go
modules/git/repo_commit.go
modules/gitgraph/graph.go
modules/gitgraph/graph_models.go
modules/gitgraph/graph_test.go
modules/templates/helper.go
options/locale/locale_en-US.ini
routers/repo/commit.go
templates/repo/graph.tmpl
templates/repo/graph/commits.tmpl [new file with mode: 0644]
templates/repo/graph/div.tmpl [new file with mode: 0644]
templates/repo/graph/svgcontainer.tmpl [new file with mode: 0644]
web_src/js/features/gitgraph.js
web_src/less/_base.less
web_src/less/_repository.less
web_src/less/features/gitgraph.less
web_src/less/themes/theme-arc-green.less

index 9a6ad0b5c4f98df61fee0ee5aba6a54a8e336ab9..a6638f40865b6db38a1e7fa589270bcc212a6984 100644 (file)
@@ -37,6 +37,12 @@ func (p *Pagination) AddParam(ctx *Context, paramKey string, ctxKey string) {
        p.urlParams = append(p.urlParams, urlParam)
 }
 
+// AddParamString adds a string parameter directly
+func (p *Pagination) AddParamString(key string, value string) {
+       urlParam := fmt.Sprintf("%s=%v", url.QueryEscape(key), url.QueryEscape(value))
+       p.urlParams = append(p.urlParams, urlParam)
+}
+
 // GetParams returns the configured URL params
 func (p *Pagination) GetParams() template.URL {
        return template.URL(strings.Join(p.urlParams, "&"))
index f34b05d1d0a1141045e6fff41c429f201e5d52dc..0ef644b522b45478eaebf459a30a951abb4c48b5 100644 (file)
@@ -171,6 +171,18 @@ func (r *Repository) GetCommitsCount() (int64, error) {
        })
 }
 
+// GetCommitGraphsCount returns cached commit count for current view
+func (r *Repository) GetCommitGraphsCount(hidePRRefs bool, branches []string, files []string) (int64, error) {
+       cacheKey := fmt.Sprintf("commits-count-%d-graph-%t-%s-%s", r.Repository.ID, hidePRRefs, branches, files)
+
+       return cache.GetInt64(cacheKey, func() (int64, error) {
+               if len(branches) == 0 {
+                       return git.AllCommitsCount(r.Repository.RepoPath(), hidePRRefs, files...)
+               }
+               return git.CommitsCountFiles(r.Repository.RepoPath(), branches, files)
+       })
+}
+
 // BranchNameSubURL sub-URL for the BranchName field
 func (r *Repository) BranchNameSubURL() string {
        switch {
index 87278af9c7df43dec8c7028df747034a16c8ae03..6425345ea8ee0dadbcc95665d257d10c2388c48b 100644 (file)
@@ -262,8 +262,19 @@ func CommitChangesWithArgs(repoPath string, args []string, opts CommitChangesOpt
 }
 
 // AllCommitsCount returns count of all commits in repository
-func AllCommitsCount(repoPath string) (int64, error) {
-       stdout, err := NewCommand("rev-list", "--all", "--count").RunInDir(repoPath)
+func AllCommitsCount(repoPath string, hidePRRefs bool, files ...string) (int64, error) {
+       args := []string{"--all", "--count"}
+       if hidePRRefs {
+               args = append([]string{"--exclude=refs/pull/*"}, args...)
+       }
+       cmd := NewCommand("rev-list")
+       cmd.AddArguments(args...)
+       if len(files) > 0 {
+               cmd.AddArguments("--")
+               cmd.AddArguments(files...)
+       }
+
+       stdout, err := cmd.RunInDir(repoPath)
        if err != nil {
                return 0, err
        }
@@ -271,7 +282,8 @@ func AllCommitsCount(repoPath string) (int64, error) {
        return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
 }
 
-func commitsCount(repoPath string, revision, relpath []string) (int64, error) {
+// CommitsCountFiles returns number of total commits of until given revision.
+func CommitsCountFiles(repoPath string, revision, relpath []string) (int64, error) {
        cmd := NewCommand("rev-list", "--count")
        cmd.AddArguments(revision...)
        if len(relpath) > 0 {
@@ -288,8 +300,8 @@ func commitsCount(repoPath string, revision, relpath []string) (int64, error) {
 }
 
 // CommitsCount returns number of total commits of until given revision.
-func CommitsCount(repoPath, revision string) (int64, error) {
-       return commitsCount(repoPath, []string{revision}, []string{})
+func CommitsCount(repoPath string, revision ...string) (int64, error) {
+       return CommitsCountFiles(repoPath, revision, []string{})
 }
 
 // CommitsCount returns number of total commits of until current revision.
index 67b56ac99948ce0ef76f81e55599eaf2bf7240ae..2a2798b18f9ab1dc3e7e285b25c766c013a85424 100644 (file)
@@ -4,6 +4,8 @@
 
 package git
 
+import "strings"
+
 // Reference represents a Git ref.
 type Reference struct {
        Name   string
@@ -16,3 +18,44 @@ type Reference struct {
 func (ref *Reference) Commit() (*Commit, error) {
        return ref.repo.getCommit(ref.Object)
 }
+
+// ShortName returns the short name of the reference
+func (ref *Reference) ShortName() string {
+       if ref == nil {
+               return ""
+       }
+       if strings.HasPrefix(ref.Name, "refs/heads/") {
+               return ref.Name[11:]
+       }
+       if strings.HasPrefix(ref.Name, "refs/tags/") {
+               return ref.Name[10:]
+       }
+       if strings.HasPrefix(ref.Name, "refs/remotes/") {
+               return ref.Name[13:]
+       }
+       if strings.HasPrefix(ref.Name, "refs/pull/") && strings.IndexByte(ref.Name[10:], '/') > -1 {
+               return ref.Name[10 : strings.IndexByte(ref.Name[10:], '/')+10]
+       }
+
+       return ref.Name
+}
+
+// RefGroup returns the group type of the reference
+func (ref *Reference) RefGroup() string {
+       if ref == nil {
+               return ""
+       }
+       if strings.HasPrefix(ref.Name, "refs/heads/") {
+               return "heads"
+       }
+       if strings.HasPrefix(ref.Name, "refs/tags/") {
+               return "tags"
+       }
+       if strings.HasPrefix(ref.Name, "refs/remotes/") {
+               return "remotes"
+       }
+       if strings.HasPrefix(ref.Name, "refs/pull/") && strings.IndexByte(ref.Name[10:], '/') > -1 {
+               return "pull"
+       }
+       return ""
+}
index 644ff09284c64c091dcfd3fb139d0dca0a9800fe..ae370d3da973aedb6812a2af226d64980063fff6 100644 (file)
@@ -49,7 +49,7 @@ const prettyLogFormat = `--pretty=format:%H`
 
 // GetAllCommitsCount returns count of all commits in repository
 func (repo *Repository) GetAllCommitsCount() (int64, error) {
-       return AllCommitsCount(repo.Path)
+       return AllCommitsCount(repo.Path, false)
 }
 
 func (repo *Repository) parsePrettyFormatLogToList(logs []byte) (*list.List, error) {
index 1f123c97fbba1ea0b955ab0954ef9f2aeaaebee7..ee3b05447b8fb505b5540cbabbf0a08079443c2f 100644 (file)
@@ -318,7 +318,7 @@ func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bo
 
 // FileCommitsCount return the number of files at a revison
 func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
-       return commitsCount(repo.Path, []string{revision}, []string{file})
+       return CommitsCountFiles(repo.Path, []string{revision}, []string{file})
 }
 
 // CommitsByFileAndRange return the commits according revison file and the page
@@ -413,11 +413,11 @@ func (repo *Repository) CommitsBetweenIDs(last, before string) (*list.List, erro
 
 // CommitsCountBetween return numbers of commits between two commits
 func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
-       count, err := commitsCount(repo.Path, []string{start + "..." + end}, []string{})
+       count, err := CommitsCountFiles(repo.Path, []string{start + "..." + end}, []string{})
        if err != nil && strings.Contains(err.Error(), "no merge base") {
                // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
                // previously it would return the results of git rev-list before last so let's try that...
-               return commitsCount(repo.Path, []string{start, end}, []string{})
+               return CommitsCountFiles(repo.Path, []string{start, end}, []string{})
        }
 
        return count, err
index 257e4f3af0de5452a76ae1ab1e5a840f97c90342..85056786395c2b2bb8dd68e957d9b0fdec499593 100644 (file)
@@ -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)
index ea6ba960846dc4e04c930e05e8779f697626eac9..ba168ab19de329ac8900308ed44ca93c334d5543 100644 (file)
@@ -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
index ca9d653ceed3a13c4beefe61072485e15f164a70..c2726a731a45a5b16fe13e561ea4805f0078279c 100644 (file)
@@ -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
index 03ec80f99c2353915c1166a94cf9e97c0437e678..e4107dfa9a10d5e30ad86518635b01f0da3d5b0a 100644 (file)
@@ -16,6 +16,7 @@ import (
        "mime"
        "net/url"
        "path/filepath"
+       "reflect"
        "regexp"
        "runtime"
        "strings"
@@ -310,6 +311,26 @@ func NewFuncMap() []template.FuncMap {
                                "EventSourceUpdateTime": int(setting.UI.Notification.EventSourceUpdateTime / time.Millisecond),
                        }
                },
+               "containGeneric": func(arr interface{}, v interface{}) bool {
+                       arrV := reflect.ValueOf(arr)
+                       if arrV.Kind() == reflect.String && reflect.ValueOf(v).Kind() == reflect.String {
+                               return strings.Contains(arr.(string), v.(string))
+                       }
+
+                       if arrV.Kind() == reflect.Slice {
+                               for i := 0; i < arrV.Len(); i++ {
+                                       iV := arrV.Index(i)
+                                       if !iV.CanInterface() {
+                                               continue
+                                       }
+                                       if iV.Interface() == v {
+                                               return true
+                                       }
+                               }
+                       }
+
+                       return false
+               },
                "contain": func(s []int64, id int64) bool {
                        for i := 0; i < len(s); i++ {
                                if s[i] == id {
index 815d69c518ab689833313b2cb326cceb773d2319..b1447f310867f8e3d067c90a4a63bcda2438199a 100644 (file)
@@ -822,6 +822,8 @@ audio_not_supported_in_browser = Your browser does not support the HTML5 'audio'
 stored_lfs = Stored with Git LFS
 symbolic_link = Symbolic link
 commit_graph = Commit Graph
+commit_graph.select = Select branches
+commit_graph.hide_pr_refs = Hide Pull Requests
 commit_graph.monochrome = Mono
 commit_graph.color = Color
 blame = Blame
index d9547cc51de625f7074b1ab30560df20123b0aee..5bb26ffe41a9465ac661b0a54a9ca165631eb38f 100644 (file)
@@ -23,6 +23,7 @@ import (
 const (
        tplCommits    base.TplName = "repo/commits"
        tplGraph      base.TplName = "repo/graph"
+       tplGraphDiv   base.TplName = "repo/graph/div"
        tplCommitPage base.TplName = "repo/commit_page"
 )
 
@@ -88,6 +89,7 @@ func Commits(ctx *context.Context) {
 
 // Graph render commit graph - show commits from all branches.
 func Graph(ctx *context.Context) {
+       ctx.Data["Title"] = ctx.Tr("repo.commit_graph")
        ctx.Data["PageIsCommits"] = true
        ctx.Data["PageIsViewCode"] = true
        mode := strings.ToLower(ctx.QueryTrim("mode"))
@@ -95,6 +97,18 @@ func Graph(ctx *context.Context) {
                mode = "color"
        }
        ctx.Data["Mode"] = mode
+       hidePRRefs := ctx.QueryBool("hide-pr-refs")
+       ctx.Data["HidePRRefs"] = hidePRRefs
+       branches := ctx.QueryStrings("branch")
+       realBranches := make([]string, len(branches))
+       copy(realBranches, branches)
+       for i, branch := range realBranches {
+               if strings.HasPrefix(branch, "--") {
+                       realBranches[i] = "refs/heads/" + branch
+               }
+       }
+       ctx.Data["SelectedBranches"] = realBranches
+       files := ctx.QueryStrings("file")
 
        commitsCount, err := ctx.Repo.GetCommitsCount()
        if err != nil {
@@ -102,28 +116,60 @@ func Graph(ctx *context.Context) {
                return
        }
 
-       allCommitsCount, err := ctx.Repo.GitRepo.GetAllCommitsCount()
+       graphCommitsCount, err := ctx.Repo.GetCommitGraphsCount(hidePRRefs, realBranches, files)
        if err != nil {
-               ctx.ServerError("GetAllCommitsCount", err)
-               return
+               log.Warn("GetCommitGraphsCount error for generate graph exclude prs: %t branches: %s in %-v, Will Ignore branches and try again. Underlying Error: %v", hidePRRefs, branches, ctx.Repo.Repository, err)
+               realBranches = []string{}
+               branches = []string{}
+               graphCommitsCount, err = ctx.Repo.GetCommitGraphsCount(hidePRRefs, realBranches, files)
+               if err != nil {
+                       ctx.ServerError("GetCommitGraphsCount", err)
+                       return
+               }
        }
 
        page := ctx.QueryInt("page")
 
-       graph, err := gitgraph.GetCommitGraph(ctx.Repo.GitRepo, page, 0)
+       graph, err := gitgraph.GetCommitGraph(ctx.Repo.GitRepo, page, 0, hidePRRefs, realBranches, files)
        if err != nil {
                ctx.ServerError("GetCommitGraph", err)
                return
        }
 
+       if err := graph.LoadAndProcessCommits(ctx.Repo.Repository, ctx.Repo.GitRepo); err != nil {
+               ctx.ServerError("LoadAndProcessCommits", err)
+               return
+       }
+
        ctx.Data["Graph"] = graph
+
+       gitRefs, err := ctx.Repo.GitRepo.GetRefs()
+       if err != nil {
+               ctx.ServerError("GitRepo.GetRefs", err)
+               return
+       }
+
+       ctx.Data["AllRefs"] = gitRefs
+
        ctx.Data["Username"] = ctx.Repo.Owner.Name
        ctx.Data["Reponame"] = ctx.Repo.Repository.Name
        ctx.Data["CommitCount"] = commitsCount
        ctx.Data["Branch"] = ctx.Repo.BranchName
-       paginator := context.NewPagination(int(allCommitsCount), setting.UI.GraphMaxCommitNum, page, 5)
+       paginator := context.NewPagination(int(graphCommitsCount), setting.UI.GraphMaxCommitNum, page, 5)
        paginator.AddParam(ctx, "mode", "Mode")
+       paginator.AddParam(ctx, "hide-pr-refs", "HidePRRefs")
+       for _, branch := range branches {
+               paginator.AddParamString("branch", branch)
+       }
+       for _, file := range files {
+               paginator.AddParamString("file", file)
+       }
        ctx.Data["Page"] = paginator
+       if ctx.QueryBool("div-only") {
+               ctx.HTML(200, tplGraphDiv)
+               return
+       }
+
        ctx.HTML(200, tplGraph)
 }
 
index 7d2ecb5a914ddade7274582e8149c16bf0f34274..fa027adc033c17004fbd7fb9f3eb8a278f377af5 100644 (file)
@@ -3,60 +3,61 @@
        {{template "repo/header" .}}
        <div class="ui container">
                <div id="git-graph-container" class="ui segment{{if eq .Mode "monochrome"}} monochrome{{end}}">
-                       <h2 class="ui header dividing">{{.i18n.Tr "repo.commit_graph"}}
-                               <div class="ui right">
-                                       <div class="ui icon buttons tiny color-buttons">
-                                               <button id="flow-color-monochrome" class="ui labelled icon button{{if eq .Mode "monochrome"}} active{{end}}" title="{{.i18n.Tr "repo.commit_graph.monochrome"}}"><span class="emoji">{{svg "material-invert-colors"}}</span> {{.i18n.Tr "repo.commit_graph.monochrome"}}</button>
-                                               <button id="flow-color-colored" class="ui labelled icon button{{if ne .Mode "monochrome"}} active{{end}}" title="{{.i18n.Tr "repo.commit_graph.color"}}"><span class="emoji">{{svg "material-palette"}}</span> {{.i18n.Tr "repo.commit_graph.color"}}</button>
+                       <h2 class="ui header dividing">
+                               {{.i18n.Tr "repo.commit_graph"}}
+                               <div class="ui icon buttons tiny color-buttons">
+                                       <div class="ui multiple selection search dropdown" id="flow-select-refs-dropdown">
+                                               <input type="hidden" name="flow">
+                                               <i class="dropdown icon"></i>
+                                               <div class="default text">{{.i18n.Tr "repo.commit_graph.select"}}</div>
+                                               <div class="menu">
+                                                       <div class="item" data-value="...flow-hide-pr-refs">
+                                                               <span class="truncate">
+                                                                       {{svg "octicon-eye-closed" 16 "mr-2"}}<span title="{{.i18n.Tr "repo.commit_graph.hide_pr_refs"}}">{{.i18n.Tr "repo.commit_graph.hide_pr_refs"}}</span>
+                                                               </span>
+                                                       </div>
+                                                       {{range .AllRefs}}
+                                                               {{$refGroup := .RefGroup}}
+                                                               {{if eq $refGroup "pull"}}
+                                                                       <div class="item" data-value="{{.Name}}">
+                                                                               <span class="truncate">
+                                                                                       {{svg "octicon-git-pull-request" 16 "mr-2"}}<span title="{{.ShortName}}">#{{.ShortName}}</span>
+                                                                               </span>
+                                                                       </div>
+                                                               {{else if eq $refGroup "tags"}}
+                                                                       <div class="item" data-value="{{.Name}}">
+                                                                               <span class="truncate">
+                                                                                       {{svg "octicon-tag" 16 "mr-2"}}<span title="{{.ShortName}}">{{.ShortName}}</span>
+                                                                               </span>
+                                                                       </div>
+                                                               {{else if eq $refGroup "remotes"}}
+                                                                       <div class="item" data-value="{{.Name}}">
+                                                                               <span class="truncate">
+                                                                                       {{svg "octicon-cross-reference" 16 "mr-2"}}<span title="{{.ShortName}}">{{.ShortName}}</span>
+                                                                               </span>
+                                                                       </div>
+                                                               {{else if eq $refGroup "heads"}}
+                                                                       <div class="item" data-value="{{.Name}}">
+                                                                               <span class="truncate">
+                                                                                       {{svg "octicon-git-branch" 16 "mr-2"}}<span title="{{.ShortName}}">{{.ShortName}}</span>
+                                                                               </span>
+                                                                       </div>
+                                                               {{end}}
+                                                       {{end}}
+                                               </div>
                                        </div>
+                                       <button id="flow-color-monochrome" class="ui labelled icon button{{if eq .Mode "monochrome"}} active{{end}}" title="{{.i18n.Tr "repo.commit_graph.monochrome"}}">{{svg "material-invert-colors" 16 "mr-2"}}{{.i18n.Tr "repo.commit_graph.monochrome"}}</button>
+                                       <button id="flow-color-colored" class="ui labelled icon button{{if ne .Mode "monochrome"}} active{{end}}" title="{{.i18n.Tr "repo.commit_graph.color"}}">{{svg "material-palette" 16 "mr-2"}}{{.i18n.Tr "repo.commit_graph.color"}}</button>
                                </div>
                        </h2>
                        <div class="ui dividing"></div>
-                       <div id="rel-container">
-                               <svg viewbox="{{Mul .Graph.MinColumn 5}} {{Mul .Graph.MinRow 10}} {{Add (Mul .Graph.Width 5) 5}} {{Mul .Graph.Height 10}}" width="{{Add (Mul .Graph.Width 10) 10}}px">
-                                       {{range $flowid, $flow := .Graph.Flows}}
-                                               <g id="flow-{{$flow.ID}}" class="flow-group flow-color-{{$flow.ColorNumber}} flow-color-16-{{$flow.Color16}}" data-flow="{{$flow.ID}}" data-color="{{$flow.ColorNumber}}">
-                                                       <path d="{{range $i, $glyph := $flow.Glyphs -}}
-                                                               {{- if or (eq $glyph.Glyph '*') (eq $glyph.Glyph '|') -}}
-                                                                       M {{Add (Mul $glyph.Column 5) 5}} {{Add (Mul $glyph.Row 10) 0}} v 10 {{/* */ -}}
-                                                               {{- else if eq $glyph.Glyph '/' -}}
-                                                                       M {{Add (Mul $glyph.Column 5) 10}} {{Add (Mul $glyph.Row 10) 0}} l -10 10 {{/* */ -}}
-                                                               {{- else if eq $glyph.Glyph '\\' -}}
-                                                                       M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 10) 0}} l 10 10 {{/* */ -}}
-                                                               {{- else if or (eq $glyph.Glyph '-') (eq $glyph.Glyph '.') -}}
-                                                                       M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 10) 10}} h 5 {{/* */ -}}
-                                                               {{- else if eq $glyph.Glyph '_' -}}
-                                                                       M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 10) 10}} h 10 {{/* */ -}}
-                                                               {{- end -}}
-                                                       {{- end}}" stroke-width="1" fill="none" id="flow-{{$flow.ID}}-path" stroke-linecap="round"/>
-                                                       {{range $flow.Commits}}
-                                                               <circle class="flow-commit" cx="{{Add (Mul .Column 5) 5}}" cy="{{Add (Mul .Row 10) 5}}" r="2.5" stroke="none" id="flow-commit-{{.Rev}}" data-rev="{{.Rev}}"/>
-                                                       {{end}}
-                                               </g>
-                                       {{end}}
-                               </svg>
-                       </div>
-                       <div id="rev-container">
-                               <ul id="rev-list">
-                                       {{ range .Graph.Commits }}
-                                               <li id="commit-{{.Rev}}" data-flow="{{.Flow}}">
-                                                       {{ if .OnlyRelation }}
-                                                               <span />
-                                                       {{ else }}
-                                                               <code id="{{.ShortRev}}">
-                                                                       <a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{.Rev}}">{{ .ShortRev}}</a>
-                                                               </code>
-                                                               <strong> {{.Branch}}</strong>
-                                                               <span>{{RenderCommitMessage .Subject $.RepoLink $.Repository.ComposeMetas}}</span> by
-                                                               <span class="author">{{.Author}}</span>
-                                                               <span class="time">{{.Date}}</span>
-                                                       {{ end }}
-                                               </li>
-                                       {{ end }}
-                               </ul>
-                       </div>
+                       <div class="ui segment loading hide" id="loading-indicator"></div>
+                       {{ template "repo/graph/svgcontainer" .}}
+                       {{ template "repo/graph/commits" .}}
                </div>
        </div>
 </div>
-{{template "base/paginate" .}}
+<div id="pagination">
+       {{template "base/paginate" .}}
+</div>
 {{template "base/footer" .}}
diff --git a/templates/repo/graph/commits.tmpl b/templates/repo/graph/commits.tmpl
new file mode 100644 (file)
index 0000000..108aa0a
--- /dev/null
@@ -0,0 +1,80 @@
+<div id="rev-container">
+       <ul id="rev-list">
+               {{ range $commitI, $commit := .Graph.Commits }}
+                       <li id="commit-{{$commit.Rev}}" data-flow="{{$commit.Flow}}">
+                               {{ if $commit.OnlyRelation }}
+                                       <span />
+                               {{ else }}
+                                       <span class="sha" id="{{$commit.ShortRev}}">
+                                               {{$class := "ui sha label"}}
+                                               {{if $commit.Commit.Signature}}
+                                                       {{$class = (printf "%s%s" $class " isSigned")}}
+                                                       {{if $commit.Verification.Verified}}
+                                                               {{if eq $commit.Verification.TrustStatus "trusted"}}
+                                                                       {{$class = (printf "%s%s" $class " isVerified")}}
+                                                               {{else if eq $commit.Verification.TrustStatus "untrusted"}}
+                                                                       {{$class = (printf "%s%s" $class " isVerifiedUntrusted")}}
+                                                               {{else}}
+                                                                       {{$class = (printf "%s%s" $class " isVerifiedUnmatched")}}
+                                                               {{end}}
+                                                       {{else if $commit.Verification.Warning}}
+                                                               {{$class = (printf "%s%s" $class " isWarning")}}
+                                                       {{end}}
+                                               {{end}}
+                                               <a href="{{AppSubUrl}}/{{$.Username}}/{{$.Reponame}}/commit/{{$commit.Rev}}" rel="nofollow" class="{{$class}}">
+                                                       <span class="shortsha">{{ShortSha $commit.Commit.ID.String}}</span>
+                                                       {{- if $commit.Commit.Signature -}}
+                                                               <span class="shortsha-pad"></span>{{template "repo/shabox_badge" dict "root" $ "verification" $commit.Verification}}
+                                                       {{- end -}}
+                                               </a>
+                                       </span>
+                                       <span class="message df ac mr-2">{{RenderCommitMessage $commit.Subject $.RepoLink $.Repository.ComposeMetas}}</span>
+                                       <span class="tags df ac">
+                                               {{range $commit.Refs}}
+                                                       {{$refGroup := .RefGroup}}
+                                                       {{if eq $refGroup "pull"}}
+                                                               {{if $.HidePRRefs}}
+                                                                       {{if (containGeneric $.SelectedBranches .Name) }}
+                                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/pulls/{{.ShortName|PathEscape}}">
+                                                                                       {{svg "octicon-git-pull-request" 16 "mr-2"}}#{{.ShortName}}
+                                                                               </a>
+                                                                       {{end}}
+                                                               {{else}}
+                                                                       <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/pulls/{{.ShortName|PathEscape}}">
+                                                                               {{svg "octicon-git-pull-request" 16 "mr-2"}}#{{.ShortName}}
+                                                                       </a>
+                                                               {{end}}
+                                                       {{else if eq $refGroup "tags"}}
+                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/src/tag/{{.ShortName|PathEscape}}">
+                                                                       {{svg "octicon-tag" 16 "mr-2"}}{{.ShortName}}
+                                                               </a>
+                                                       {{else if eq $refGroup "remotes"}}
+                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/src/commit/{{$commit.Rev}}">
+                                                                       {{svg "octicon-cross-reference" 16 "mr-2"}}{{.ShortName}}
+                                                               </a>
+                                                       {{else if eq $refGroup "heads"}}
+                                                               <a class="ui labelled icon button basic tiny" href="{{$.RepoLink}}/src/branch/{{.ShortName|PathEscape}}">
+                                                                       {{svg "octicon-git-branch" 16 "mr-2"}}{{.ShortName}}
+                                                               </a>
+                                                       {{else}}
+                                                               <!-- Unknown ref type {{.Name}} -->
+                                                       {{end}}
+                                               {{end}}
+                                       </span>
+                                       <span class="author df ac mr-2">
+                                               {{$userName := $commit.Commit.Author.Name}}
+                                               {{if $commit.User}}
+                                                       {{if $commit.User.FullName}}
+                                                               {{$userName = $commit.User.FullName}}
+                                                       {{end}}
+                                                       <img class="ui avatar image" src="{{$commit.User.RelAvatarLink}}" alt=""/><a href="{{AppSubUrl}}/{{$commit.User.Name}}">{{$userName}}</a>
+                                               {{else}}
+                                                       <img class="ui avatar image" src="{{AvatarLink $commit.Commit.Author.Email}}" alt=""/>{{$userName}}
+                                               {{end}}
+                                       </span>
+                                       <span class="time df ac">{{$commit.Date}}</span>
+                               {{ end }}
+                       </li>
+               {{ end }}
+       </ul>
+</div>
diff --git a/templates/repo/graph/div.tmpl b/templates/repo/graph/div.tmpl
new file mode 100644 (file)
index 0000000..c0bd4e2
--- /dev/null
@@ -0,0 +1,7 @@
+<div>
+       {{template "repo/graph/svgcontainer" .}}
+       {{template "repo/graph/commits" .}}
+       <div id="pagination">
+               {{template "base/paginate" .}}
+       </div>
+</div>
diff --git a/templates/repo/graph/svgcontainer.tmpl b/templates/repo/graph/svgcontainer.tmpl
new file mode 100644 (file)
index 0000000..6e6046c
--- /dev/null
@@ -0,0 +1,24 @@
+<div id="rel-container">
+       <svg viewbox="{{Mul .Graph.MinColumn 5}} {{Mul .Graph.MinRow 12}} {{Add (Mul .Graph.Width 5) 5}} {{Mul .Graph.Height 12}}" width="{{Add (Mul .Graph.Width 10) 10}}px">
+               {{range $flowid, $flow := .Graph.Flows}}
+                       <g id="flow-{{$flow.ID}}" class="flow-group flow-color-{{$flow.ColorNumber}} flow-color-16-{{$flow.Color16}}" data-flow="{{$flow.ID}}" data-color="{{$flow.ColorNumber}}">
+                               <path d="{{range $i, $glyph := $flow.Glyphs -}}
+                                       {{- if or (eq $glyph.Glyph '*') (eq $glyph.Glyph '|') -}}
+                                               M {{Add (Mul $glyph.Column 5) 5}} {{Add (Mul $glyph.Row 12) 0}} v 12 {{/* */ -}}
+                                       {{- else if eq $glyph.Glyph '/' -}}
+                                               M {{Add (Mul $glyph.Column 5) 10}} {{Add (Mul $glyph.Row 12) 0}} l -10 12 {{/* */ -}}
+                                       {{- else if eq $glyph.Glyph '\\' -}}
+                                               M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 12) 0}} l 10 12 {{/* */ -}}
+                                       {{- else if or (eq $glyph.Glyph '-') (eq $glyph.Glyph '.') -}}
+                                               M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 12) 12}} h 5 {{/* */ -}}
+                                       {{- else if eq $glyph.Glyph '_' -}}
+                                               M {{Add (Mul $glyph.Column 5) 0}} {{Add (Mul $glyph.Row 12) 12}} h 10 {{/* */ -}}
+                                       {{- end -}}
+                               {{- end}}" stroke-width="1" fill="none" id="flow-{{$flow.ID}}-path" stroke-linecap="round"/>
+                               {{range $flow.Commits}}
+                                       <circle class="flow-commit" cx="{{Add (Mul .Column 5) 5}}" cy="{{Add (Mul .Row 12) 6}}" r="2.5" stroke="none" id="flow-commit-{{.Rev}}" data-rev="{{.Rev}}"/>
+                               {{end}}
+                       </g>
+               {{end}}
+       </svg>
+</div>
index 655cfb77c2228c67e4f28fb39fbeb5576c1a62ce..570d16059f586a7db9ee5896a81e6da7671b8878 100644 (file)
@@ -46,6 +46,57 @@ export default async function initGitGraph() {
       window.history.replaceState({}, '', window.location.pathname);
     }
   });
+  const url = new URL(window.location);
+  const params = url.searchParams;
+  const updateGraph = async () => {
+    const queryString = params.toString();
+    const ajaxUrl = new URL(url);
+    ajaxUrl.searchParams.set('div-only', 'true');
+    window.history.replaceState({}, '', queryString ? `?${queryString}` : window.location.pathname);
+    $('#pagination').empty();
+    $('#rel-container').addClass('hide');
+    $('#rev-container').addClass('hide');
+    $('#loading-indicator').removeClass('hide');
+
+    const div = $(await $.ajax(String(ajaxUrl)));
+    $('#pagination').html(div.find('#pagination').html());
+    $('#rel-container').html(div.find('#rel-container').html());
+    $('#rev-container').html(div.find('#rev-container').html());
+    $('#loading-indicator').addClass('hide');
+    $('#rel-container').removeClass('hide');
+    $('#rev-container').removeClass('hide');
+  };
+  const dropdownSelected = params.getAll('branch');
+  if (params.has('hide-pr-refs') && params.get('hide-pr-refs') === 'true') {
+    dropdownSelected.splice(0, 0, '...flow-hide-pr-refs');
+  }
+
+  $('#flow-select-refs-dropdown').dropdown('set selected', dropdownSelected);
+  $('#flow-select-refs-dropdown').dropdown({
+    clearable: true,
+    onRemove(toRemove) {
+      if (toRemove === '...flow-hide-pr-refs') {
+        params.delete('hide-pr-refs');
+      } else {
+        const branches = params.getAll('branch');
+        params.delete('branch');
+        for (const branch of branches) {
+          if (branch !== toRemove) {
+            params.append('branch', branch);
+          }
+        }
+      }
+      updateGraph();
+    },
+    onAdd(toAdd) {
+      if (toAdd === '...flow-hide-pr-refs') {
+        params.set('hide-pr-refs', true);
+      } else {
+        params.append('branch', toAdd);
+      }
+      updateGraph();
+    },
+  });
   $('#git-graph-container').on('mouseenter', '#rev-list li', (e) => {
     const flow = $(e.currentTarget).data('flow');
     if (flow === 0) return;
index 7a757fd9220941b39fece5d04ecb2ce3d5cec373..29eca15d24a08ac4ee3ae1d9cb797c4d0fe8be5a 100644 (file)
@@ -1391,6 +1391,10 @@ table th[data-sortt-desc] {
   }
 }
 
+.dropdown .ui.label {
+  margin-left: 0 !important;
+}
+
 .ui.dropdown .menu .item {
   border-radius: 0;
 }
index 0a2772a79e3bf585645a69ae99fe4b8fb842076d..e77fbc05a747b3f63cac73eba8824343da98d339 100644 (file)
 
   #commits-table td.sha .sha.label,
   #repo-files-table .sha.label,
+  #rev-list .sha.label,
   .timeline-item.commits-list .singular-commit .sha.label {
     border: 1px solid #bbbbbb;
 
index da81b13352d48865f839d4c99f20d97569373672..ee170fba7fe796665df127cfab55af2b1ba11ed8 100644 (file)
@@ -1,8 +1,21 @@
 #git-graph-container {
   float: left;
   display: block;
-  overflow-x: auto;
+  overflow-x: scroll;
   width: 100%;
+  min-height: 350px;
+
+  > .ui.segment.loading {
+    border: 0;
+    z-index: 1;
+    min-height: 246px;
+  }
+
+  h2 {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
 
   .color-buttons {
     margin-right: 0;
     padding-bottom: 10px;
   }
 
+  #flow-select-refs-dropdown {
+    border-top-right-radius: 0;
+    border-bottom-right-radius: 0;
+    min-width: 250px;
+    border-right: none;
+
+    .ui.label {
+      max-width: 180px;
+      display: inline-flex !important;
+      align-items: center;
+
+      .truncate {
+        display: inline-block;
+        max-width: 140px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        vertical-align: top;
+        white-space: nowrap;
+      }
+    }
+
+    .dropdown.icon {
+      display: none;
+    }
+
+    .default.text {
+      padding-top: 4px;
+      padding-bottom: 4px;
+    }
+
+    input.search {
+      position: relative;
+      top: 1px;
+    }
+  }
+
   li {
     list-style-type: none;
-    height: 20px;
-    line-height: 20px;
+    height: 24px;
+    line-height: 24px;
     white-space: nowrap;
+    display: flex;
+    align-items: center;
 
     .node-relation {
       font-family: "Bitstream Vera Sans Mono", "Courier", monospace;
       font-size: 80%;
     }
 
-    a {
-      color: #000000;
-    }
-
     a:hover {
       text-decoration: underline;
     }
 
   #rev-list {
     margin: 0;
-    padding: 0 5px;
-    min-width: 95%;
+    padding: 0;
+    width: 100%;
 
-    li.highlight,
-    li.hover {
+    li.highlight.hover {
       background-color: rgba(0, 0, 0, .05);
     }
 
-    li.highlight.hover {
-      background-color: rgba(0, 0, 0, .1);
+    .tags a.button {
+      padding: 2px 4px;
+    }
+
+    .sha.label {
+      padding-top: 5px;
+      padding-bottom: 3px;
+    }
+
+    .sha.label .shortsha {
+      padding-top: 0;
+    }
+
+    .sha.label .shortsha-pad {
+      padding-right: 10px;
+    }
+
+    .sha.label .ui.detail.icon.button {
+      padding-top: 3px;
+      margin-top: -5px;
+      padding-bottom: 1px;
+    }
+
+    .author .ui.avatar.image {
+      width: auto;
+      height: 18px;
     }
   }
 
index c7fd7e4a234ac61449024f9bbf84cfaa9b024d26..5b0cbb5e96e920638451a80e59a2908d964daae1 100644 (file)
@@ -1360,10 +1360,6 @@ td.blob-hunk {
   }
 }
 
-input {
-  background: #2e323e;
-}
-
 .settings .key.list .item:not(:first-child) {
   border-top: 1px solid var(--color-secondary);
 }
@@ -1608,6 +1604,12 @@ a.blob-excerpt:hover {
   color: #dbdbdb;
 }
 
+.ui.active.label {
+  background: #393d4a;
+  border-color: #393d4a;
+  color: #dbdbdb;
+}
+
 a.ui.label:hover,
 a.ui.labels .label:hover {
   background-color: #505667 !important;
@@ -1617,6 +1619,7 @@ a.ui.labels .label:hover {
 .sha.label,
 .repository #repo-files-table .sha.label,
 .repository #commits-table td.sha .sha.label,
+#rev-list .sha.label,
 .repository .timeline-item.commits-list .singular-commit .sha.label,
 .repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label {
   border-color: #505667;
@@ -1624,6 +1627,7 @@ a.ui.labels .label:hover {
 
 .sha.label.isSigned .detail.icon,
 .repository #commits-table td.sha .sha.label.isSigned .detail.icon,
+#rev-list .sha.label.isSigned .detail.icon,
 .repository #repo-files-table .sha.label.isSigned .detail.icon,
 .repository .timeline-item.commits-list .singular-commit .sha.label.isSigned .detail.icon,
 .repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned .detail.icon {
@@ -1743,14 +1747,6 @@ a.ui.labels .label:hover {
   color: var(--color-secondary-dark-6);
 }
 
-#git-graph-container li a {
-  color: #c79575;
-}
-
-#git-graph-container li .author {
-  color: #c79575;
-}
-
 .ui.header .sub.header {
   color: var(--color-secondary-dark-6);
 }
@@ -1970,6 +1966,10 @@ a.ui.labels .label:hover {
   }
 }
 
+.ui.loading.segment:before {
+  background: #353945;
+}
+
 .ui.popup {
   background-color: #383c4a;
   color: var(--color-secondary-dark-6);
@@ -2053,6 +2053,10 @@ img[src$="/img/matrix.svg"] {
   filter: invert(80%);
 }
 
+#git-graph-container li .time {
+  color: #6a737d;
+}
+
 #git-graph-container.monochrome #rel-container .flow-group {
   stroke: dimgrey;
   fill: dimgrey;
@@ -2077,11 +2081,6 @@ img[src$="/img/matrix.svg"] {
   }
 }
 
-#git-graph-container #rev-list li.highlight,
-#git-graph-container #rev-list li.hover {
-  background-color: rgba(255, 255, 255, .05);
-}
-
 #git-graph-container #rev-list li.highlight.hover {
   background-color: rgba(255, 255, 255, .1);
 }