Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Number of commits ahead/behind in branch overview #6695

Merged
merged 12 commits into from May 5, 2019
Merged
9 changes: 9 additions & 0 deletions models/repo.go
Expand Up @@ -2558,3 +2558,12 @@ func (repo *Repository) GetUserFork(userID int64) (*Repository, error) {
}
return &forkedRepo, nil
}

// CountDivergingCommits determines how many commits a branch is ahead or behind the repository's base branch
func (repo *Repository) CountDivergingCommits(branch string) (*git.DivergeObject, error) {
saitho marked this conversation as resolved.
Show resolved Hide resolved
divergence, err := git.GetDivergingCommits(repo.RepoPath(), repo.DefaultBranch, branch)
if err != nil {
return nil, err
}
return &divergence, nil
}
39 changes: 39 additions & 0 deletions modules/git/repo.go
Expand Up @@ -9,9 +9,11 @@ import (
"bytes"
"container/list"
"errors"
"fmt"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -306,3 +308,40 @@ func GetLatestCommitTime(repoPath string) (time.Time, error) {
commitTime := strings.TrimSpace(stdout)
return time.Parse(GitTimeLayout, commitTime)
}

// DivergeObject represents commit count diverging commits
type DivergeObject struct {
Ahead int
Behind int
}

func checkDivergence(repoPath string, baseBranch string, targetBranch string) (int, error) {
branches := fmt.Sprintf("%s..%s", baseBranch, targetBranch)
cmd := NewCommand("rev-list", "--count", branches)
stdout, err := cmd.RunInDir(repoPath)
if err != nil {
return -1, err
}
outInteger, errInteger := strconv.Atoi(strings.Trim(stdout, "\n"))
if errInteger != nil {
return -1, errInteger
}
return outInteger, nil
}

// GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch
func GetDivergingCommits(repoPath string, baseBranch string, targetBranch string) (DivergeObject, error) {
// $(git rev-list --count master..feature) commits ahead of master
ahead, errorAhead := checkDivergence(repoPath, baseBranch, targetBranch)
if errorAhead != nil {
return DivergeObject{}, errorAhead
}

// $(git rev-list --count feature..master) commits behind master
behind, errorBehind := checkDivergence(repoPath, targetBranch, baseBranch)
if errorBehind != nil {
return DivergeObject{}, errorBehind
}

return DivergeObject{ahead, behind}, nil
}
7 changes: 7 additions & 0 deletions modules/templates/helper.go
Expand Up @@ -219,6 +219,13 @@ func NewFuncMap() []template.FuncMap {
}
return dict, nil
},
"percentage": func(n int, values ...int) float32 {
var sum = 0
for i := 0; i < len(values); i++ {
sum += values[i]
}
return float32(n) * 100 / float32(sum)
},
}}
}

Expand Down
2 changes: 1 addition & 1 deletion public/css/index.css

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions public/less/_repository.less
Expand Up @@ -963,6 +963,42 @@
margin-top: 1px!important;
}

&.branches {
.commit-divergence {
.bar-group {
position: relative;
float: left;
padding-bottom: 6px;
width: 90px;

&:last-child {
border-left: 1px solid #b4b4b4;
}
}
.count {
margin: 0 3px;
&.count-ahead {
text-align: left;
}
&.count-behind {
text-align: right;
}
}
.bar {
height: 4px;
position: absolute;
background-color: #d4d4d5;

&.bar-behind {
right: 0;
}
&.bar-ahead {
left: 0;
}
}
}
}

&.commits {
.header {
.search {
Expand Down
19 changes: 15 additions & 4 deletions routers/repo/branch.go
Expand Up @@ -28,6 +28,8 @@ type Branch struct {
IsProtected bool
IsDeleted bool
DeletedBranch *models.DeletedBranch
CommitsAhead int
CommitsBehind int
}

// Branches render repository branch page
Expand Down Expand Up @@ -168,16 +170,25 @@ func loadBranches(ctx *context.Context) []*Branch {
return nil
}

isProtected, err := ctx.Repo.Repository.IsProtectedBranch(rawBranches[i].Name, ctx.User)
branchName := rawBranches[i].Name
isProtected, err := ctx.Repo.Repository.IsProtectedBranch(branchName, ctx.User)
if err != nil {
ctx.ServerError("IsProtectedBranch", err)
return nil
}

divergence, divergenceError := ctx.Repo.Repository.CountDivergingCommits(branchName)
if divergenceError != nil {
ctx.ServerError("CountDivergingCommits", divergenceError)
return nil
}

branches[i] = &Branch{
Name: rawBranches[i].Name,
Commit: commit,
IsProtected: isProtected,
Name: branchName,
Commit: commit,
IsProtected: isProtected,
CommitsAhead: divergence.Ahead,
CommitsBehind: divergence.Behind,
}
}

Expand Down
15 changes: 14 additions & 1 deletion templates/repo/branch/list.tmpl
Expand Up @@ -26,7 +26,8 @@
<table class="ui very basic striped fixed table single line">
<thead>
<tr>
<th class="nine wide">{{.i18n.Tr "repo.branch.name"}}</th>
<th class="seven wide">{{.i18n.Tr "repo.branch.name"}}</th>
<th class="two wide"></th>
{{if and $.IsWriter (not $.IsMirror)}}
<th class="one wide right aligned">{{.i18n.Tr "repo.branch.delete_head"}}</th>
{{end}}
Expand All @@ -45,6 +46,18 @@
<p class="time">{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
</td>
{{end}}
<td class="ui">
<div class="commit-divergence">
<div class="bar-group">
<div class="count count-behind">{{.CommitsBehind}}</div>
<div class="bar bar-behind" style="width: {{percentage .CommitsBehind .CommitsBehind .CommitsAhead}}%"></div>
</div>
<div class="bar-group">
<div class="count count-ahead">{{.CommitsAhead}}</div>
<div class="bar bar-ahead" style="width: {{percentage .CommitsAhead .CommitsBehind .CommitsAhead}}%"></div>
</div>
</div>
</td>
{{if and $.IsWriter (not $.IsMirror)}}
<td class="right aligned">
{{if .IsProtected}}
Expand Down