Add pager to the branches page (#14202)
* Add pager to the branches page * override pageSize if bigger than max * Make branches commit range configurable Co-authored-by: zeripath <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
parent
8d0e331c0a
commit
0c0445c97a
|
@ -1098,6 +1098,10 @@ MAX_GIT_DIFF_LINES = 1000
|
||||||
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
|
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
|
||||||
; Max number of files shown in diff view
|
; Max number of files shown in diff view
|
||||||
MAX_GIT_DIFF_FILES = 100
|
MAX_GIT_DIFF_FILES = 100
|
||||||
|
; Set the default commits range size
|
||||||
|
COMMITS_RANGE_SIZE = 50
|
||||||
|
; Set the default branches range size
|
||||||
|
BRANCHES_RANGE_SIZE = 20
|
||||||
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
; Arguments for command 'git gc', e.g. "--aggressive --auto"
|
||||||
; see more on http://git-scm.com/docs/git-gc/
|
; see more on http://git-scm.com/docs/git-gc/
|
||||||
GC_ARGS =
|
GC_ARGS =
|
||||||
|
|
|
@ -752,6 +752,8 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false`
|
||||||
- `MAX_GIT_DIFF_LINES`: **100**: Max number of lines allowed of a single file in diff view.
|
- `MAX_GIT_DIFF_LINES`: **100**: Max number of lines allowed of a single file in diff view.
|
||||||
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
- `MAX_GIT_DIFF_LINE_CHARACTERS`: **5000**: Max character count per line highlighted in diff view.
|
||||||
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
- `MAX_GIT_DIFF_FILES`: **100**: Max number of files shown in diff view.
|
||||||
|
- `COMMITS_RANGE_SIZE`: **50**: Set the default commits range size
|
||||||
|
- `BRANCHES_RANGE_SIZE`: **20**: Set the default branches range size
|
||||||
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
- `GC_ARGS`: **\<empty\>**: Arguments for command `git gc`, e.g. `--aggressive --auto`. See more on http://git-scm.com/docs/git-gc/
|
||||||
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
|
- `ENABLE_AUTO_GIT_WIRE_PROTOCOL`: **true**: If use git wire protocol version 2 when git version >= 2.18, default is true, set to false when you always want git wire protocol version 1
|
||||||
- `PULL_REQUEST_PUSH_MESSAGE`: **true**: Respond to pushes to a non-default branch with a URL for creating a Pull Request (if the repository has them enabled)
|
- `PULL_REQUEST_PUSH_MESSAGE`: **true**: Respond to pushes to a non-default branch with a URL for creating a Pull Request (if the repository has them enabled)
|
||||||
|
|
|
@ -110,6 +110,9 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
|
||||||
// CommitsRangeSize the default commits range size
|
// CommitsRangeSize the default commits range size
|
||||||
var CommitsRangeSize = 50
|
var CommitsRangeSize = 50
|
||||||
|
|
||||||
|
// BranchesRangeSize the default branches range size
|
||||||
|
var BranchesRangeSize = 20
|
||||||
|
|
||||||
func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) (*list.List, error) {
|
func (repo *Repository) commitsByRange(id SHA1, page, pageSize int) (*list.List, error) {
|
||||||
stdout, err := NewCommand("log", id.String(), "--skip="+strconv.Itoa((page-1)*pageSize),
|
stdout, err := NewCommand("log", id.String(), "--skip="+strconv.Itoa((page-1)*pageSize),
|
||||||
"--max-count="+strconv.Itoa(pageSize), prettyLogFormat).RunInDirBytes(repo.Path)
|
"--max-count="+strconv.Itoa(pageSize), prettyLogFormat).RunInDirBytes(repo.Path)
|
||||||
|
|
|
@ -19,6 +19,8 @@ var (
|
||||||
MaxGitDiffLines int
|
MaxGitDiffLines int
|
||||||
MaxGitDiffLineCharacters int
|
MaxGitDiffLineCharacters int
|
||||||
MaxGitDiffFiles int
|
MaxGitDiffFiles int
|
||||||
|
CommitsRangeSize int
|
||||||
|
BranchesRangeSize int
|
||||||
VerbosePush bool
|
VerbosePush bool
|
||||||
VerbosePushDelay time.Duration
|
VerbosePushDelay time.Duration
|
||||||
GCArgs []string `ini:"GC_ARGS" delim:" "`
|
GCArgs []string `ini:"GC_ARGS" delim:" "`
|
||||||
|
@ -37,6 +39,8 @@ var (
|
||||||
MaxGitDiffLines: 1000,
|
MaxGitDiffLines: 1000,
|
||||||
MaxGitDiffLineCharacters: 5000,
|
MaxGitDiffLineCharacters: 5000,
|
||||||
MaxGitDiffFiles: 100,
|
MaxGitDiffFiles: 100,
|
||||||
|
CommitsRangeSize: 50,
|
||||||
|
BranchesRangeSize: 20,
|
||||||
VerbosePush: true,
|
VerbosePush: true,
|
||||||
VerbosePushDelay: 5 * time.Second,
|
VerbosePushDelay: 5 * time.Second,
|
||||||
GCArgs: []string{},
|
GCArgs: []string{},
|
||||||
|
@ -91,5 +95,8 @@ func newGit() {
|
||||||
args = append(args, "Version 2") // for focus color
|
args = append(args, "Version 2") // for focus color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
git.CommitsRangeSize = Git.CommitsRangeSize
|
||||||
|
git.BranchesRangeSize = Git.BranchesRangeSize
|
||||||
|
|
||||||
log.Info(format, args...)
|
log.Info(format, args...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,25 @@ func Branches(ctx *context.Context) {
|
||||||
ctx.Data["PageIsViewCode"] = true
|
ctx.Data["PageIsViewCode"] = true
|
||||||
ctx.Data["PageIsBranches"] = true
|
ctx.Data["PageIsBranches"] = true
|
||||||
|
|
||||||
ctx.Data["Branches"] = loadBranches(ctx)
|
page := ctx.QueryInt("page")
|
||||||
|
if page <= 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pageSize := ctx.QueryInt("limit")
|
||||||
|
if pageSize <= 0 || pageSize > git.BranchesRangeSize {
|
||||||
|
pageSize = git.BranchesRangeSize
|
||||||
|
}
|
||||||
|
|
||||||
|
branches, branchesCount := loadBranches(ctx, page, pageSize)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["Branches"] = branches
|
||||||
|
pager := context.NewPagination(int(branchesCount), git.BranchesRangeSize, page, 5)
|
||||||
|
pager.SetDefaultParams(ctx)
|
||||||
|
ctx.Data["Page"] = pager
|
||||||
|
|
||||||
ctx.HTML(200, tplBranch)
|
ctx.HTML(200, tplBranch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,17 +194,25 @@ func deleteBranch(ctx *context.Context, branchName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadBranches(ctx *context.Context) []*Branch {
|
// loadBranches loads branches from the repository limited by page & pageSize.
|
||||||
|
// NOTE: May write to context on error. page & pageSize must be > 0
|
||||||
|
func loadBranches(ctx *context.Context, page, pageSize int) ([]*Branch, int) {
|
||||||
|
defaultBranch, err := repo_module.GetBranch(ctx.Repo.Repository, ctx.Repo.Repository.DefaultBranch)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetDefaultBranch", err)
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
rawBranches, err := repo_module.GetBranches(ctx.Repo.Repository)
|
rawBranches, err := repo_module.GetBranches(ctx.Repo.Repository)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranches", err)
|
ctx.ServerError("GetBranches", err)
|
||||||
return nil
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
protectedBranches, err := ctx.Repo.Repository.GetProtectedBranches()
|
protectedBranches, err := ctx.Repo.Repository.GetProtectedBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetProtectedBranches", err)
|
ctx.ServerError("GetProtectedBranches", err)
|
||||||
return nil
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
repoIDToRepo := map[int64]*models.Repository{}
|
repoIDToRepo := map[int64]*models.Repository{}
|
||||||
|
@ -195,100 +221,129 @@ func loadBranches(ctx *context.Context) []*Branch {
|
||||||
repoIDToGitRepo := map[int64]*git.Repository{}
|
repoIDToGitRepo := map[int64]*git.Repository{}
|
||||||
repoIDToGitRepo[ctx.Repo.Repository.ID] = ctx.Repo.GitRepo
|
repoIDToGitRepo[ctx.Repo.Repository.ID] = ctx.Repo.GitRepo
|
||||||
|
|
||||||
branches := make([]*Branch, len(rawBranches))
|
var totalNumOfBranches = len(rawBranches)
|
||||||
for i := range rawBranches {
|
var startIndex = (page - 1) * pageSize
|
||||||
commit, err := rawBranches[i].GetCommit()
|
if startIndex > totalNumOfBranches {
|
||||||
if err != nil {
|
startIndex = totalNumOfBranches - 1
|
||||||
ctx.ServerError("GetCommit", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var isProtected bool
|
|
||||||
branchName := rawBranches[i].Name
|
|
||||||
for _, b := range protectedBranches {
|
|
||||||
if b.BranchName == branchName {
|
|
||||||
isProtected = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, git.BranchPrefix+branchName)
|
|
||||||
if divergenceError != nil {
|
|
||||||
ctx.ServerError("CountDivergingCommits", divergenceError)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pr, err := models.GetLatestPullRequestByHeadInfo(ctx.Repo.Repository.ID, branchName)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("GetLatestPullRequestByHeadInfo", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
headCommit := commit.ID.String()
|
|
||||||
|
|
||||||
mergeMovedOn := false
|
|
||||||
if pr != nil {
|
|
||||||
pr.HeadRepo = ctx.Repo.Repository
|
|
||||||
if err := pr.LoadIssue(); err != nil {
|
|
||||||
ctx.ServerError("pr.LoadIssue", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok {
|
|
||||||
pr.BaseRepo = repo
|
|
||||||
} else if err := pr.LoadBaseRepo(); err != nil {
|
|
||||||
ctx.ServerError("pr.LoadBaseRepo", err)
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo
|
|
||||||
}
|
|
||||||
pr.Issue.Repo = pr.BaseRepo
|
|
||||||
|
|
||||||
if pr.HasMerged {
|
|
||||||
baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID]
|
|
||||||
if !ok {
|
|
||||||
baseGitRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath())
|
|
||||||
if err != nil {
|
|
||||||
ctx.ServerError("OpenRepository", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
defer baseGitRepo.Close()
|
|
||||||
repoIDToGitRepo[pr.BaseRepoID] = baseGitRepo
|
|
||||||
}
|
|
||||||
pullCommit, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
|
||||||
if err != nil && !git.IsErrNotExist(err) {
|
|
||||||
ctx.ServerError("GetBranchCommitID", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err == nil && headCommit != pullCommit {
|
|
||||||
// the head has moved on from the merge - we shouldn't delete
|
|
||||||
mergeMovedOn = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isIncluded := divergence.Ahead == 0 && ctx.Repo.Repository.DefaultBranch != branchName
|
|
||||||
|
|
||||||
branches[i] = &Branch{
|
|
||||||
Name: branchName,
|
|
||||||
Commit: commit,
|
|
||||||
IsProtected: isProtected,
|
|
||||||
IsIncluded: isIncluded,
|
|
||||||
CommitsAhead: divergence.Ahead,
|
|
||||||
CommitsBehind: divergence.Behind,
|
|
||||||
LatestPullRequest: pr,
|
|
||||||
MergeMovedOn: mergeMovedOn,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
var endIndex = startIndex + pageSize
|
||||||
|
if endIndex > totalNumOfBranches {
|
||||||
|
endIndex = totalNumOfBranches - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var branches []*Branch
|
||||||
|
for i := startIndex; i < endIndex; i++ {
|
||||||
|
var branch = loadOneBranch(ctx, rawBranches[i], protectedBranches, repoIDToRepo, repoIDToGitRepo)
|
||||||
|
if branch == nil {
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if branch.Name == ctx.Repo.Repository.DefaultBranch {
|
||||||
|
// Skip default branch
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
branches = append(branches, branch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always add the default branch
|
||||||
|
branches = append(branches, loadOneBranch(ctx, defaultBranch, protectedBranches, repoIDToRepo, repoIDToGitRepo))
|
||||||
|
|
||||||
if ctx.Repo.CanWrite(models.UnitTypeCode) {
|
if ctx.Repo.CanWrite(models.UnitTypeCode) {
|
||||||
deletedBranches, err := getDeletedBranches(ctx)
|
deletedBranches, err := getDeletedBranches(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("getDeletedBranches", err)
|
ctx.ServerError("getDeletedBranches", err)
|
||||||
return nil
|
return nil, 0
|
||||||
}
|
}
|
||||||
branches = append(branches, deletedBranches...)
|
branches = append(branches, deletedBranches...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return branches
|
return branches, len(rawBranches) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadOneBranch(ctx *context.Context, rawBranch *git.Branch, protectedBranches []*models.ProtectedBranch,
|
||||||
|
repoIDToRepo map[int64]*models.Repository,
|
||||||
|
repoIDToGitRepo map[int64]*git.Repository) *Branch {
|
||||||
|
|
||||||
|
commit, err := rawBranch.GetCommit()
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetCommit", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
branchName := rawBranch.Name
|
||||||
|
var isProtected bool
|
||||||
|
for _, b := range protectedBranches {
|
||||||
|
if b.BranchName == branchName {
|
||||||
|
isProtected = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
divergence, divergenceError := repofiles.CountDivergingCommits(ctx.Repo.Repository, git.BranchPrefix+branchName)
|
||||||
|
if divergenceError != nil {
|
||||||
|
ctx.ServerError("CountDivergingCommits", divergenceError)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
pr, err := models.GetLatestPullRequestByHeadInfo(ctx.Repo.Repository.ID, branchName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("GetLatestPullRequestByHeadInfo", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
headCommit := commit.ID.String()
|
||||||
|
|
||||||
|
mergeMovedOn := false
|
||||||
|
if pr != nil {
|
||||||
|
pr.HeadRepo = ctx.Repo.Repository
|
||||||
|
if err := pr.LoadIssue(); err != nil {
|
||||||
|
ctx.ServerError("pr.LoadIssue", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok {
|
||||||
|
pr.BaseRepo = repo
|
||||||
|
} else if err := pr.LoadBaseRepo(); err != nil {
|
||||||
|
ctx.ServerError("pr.LoadBaseRepo", err)
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo
|
||||||
|
}
|
||||||
|
pr.Issue.Repo = pr.BaseRepo
|
||||||
|
|
||||||
|
if pr.HasMerged {
|
||||||
|
baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID]
|
||||||
|
if !ok {
|
||||||
|
baseGitRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath())
|
||||||
|
if err != nil {
|
||||||
|
ctx.ServerError("OpenRepository", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer baseGitRepo.Close()
|
||||||
|
repoIDToGitRepo[pr.BaseRepoID] = baseGitRepo
|
||||||
|
}
|
||||||
|
pullCommit, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||||
|
if err != nil && !git.IsErrNotExist(err) {
|
||||||
|
ctx.ServerError("GetBranchCommitID", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err == nil && headCommit != pullCommit {
|
||||||
|
// the head has moved on from the merge - we shouldn't delete
|
||||||
|
mergeMovedOn = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isIncluded := divergence.Ahead == 0 && ctx.Repo.Repository.DefaultBranch != branchName
|
||||||
|
return &Branch{
|
||||||
|
Name: branchName,
|
||||||
|
Commit: commit,
|
||||||
|
IsProtected: isProtected,
|
||||||
|
IsIncluded: isIncluded,
|
||||||
|
CommitsAhead: divergence.Ahead,
|
||||||
|
CommitsBehind: divergence.Behind,
|
||||||
|
LatestPullRequest: pr,
|
||||||
|
MergeMovedOn: mergeMovedOn,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDeletedBranches(ctx *context.Context) ([]*Branch, error) {
|
func getDeletedBranches(ctx *context.Context) ([]*Branch, error) {
|
||||||
|
|
|
@ -127,6 +127,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{{template "base/paginate" .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue