新增:分支列表按类型分组

This commit is contained in:
yystopf 2022-11-23 19:47:43 +08:00
parent ece7f6a672
commit 2c512957e5
4 changed files with 224 additions and 1 deletions

16
modules/convert/utils.go Normal file
View File

@ -0,0 +1,16 @@
package convert
import "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git"
func ToBranchType(index int) git.BranchKind {
switch index {
case 1:
return git.DefaultBranch
case 2:
return git.ProtectedBranch
case 3:
return git.OtherBranch
default:
return git.None
}
}

View File

@ -0,0 +1,83 @@
package git
import (
"context"
"strings"
"code.gitea.io/gitea/modules/git"
api "code.gitea.io/gitea/modules/structs"
)
type Branch struct {
*api.Branch
CommitID string `json:"commit_id"` // add configure
CommitTime string `json:"commit_time"` // add configure
DefaultBranch string `json:"default_branch"`
BranchKind int `json:"branch_kind"`
}
type BranchKind int
const (
None BranchKind = iota
DefaultBranch
ProtectedBranch
OtherBranch
)
func (bk BranchKind) Name() string {
return strings.ToLower(bk.Title())
}
func (bk BranchKind) Title() string {
switch bk {
case DefaultBranch:
return "default"
case ProtectedBranch:
return "protected"
case OtherBranch:
return "other"
}
return ""
}
type BranchesSlice struct {
BranchName string `json:"branch_name"`
// BranchKind int `json:"branch_kind"`
Branches []*Branch `json:"branches"`
}
// sort by branchkind
type SortBranch []*Branch
func (s SortBranch) Len() int { return len(s) }
func (s SortBranch) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortBranch) Less(i, j int) bool { return s[i].BranchKind < s[j].BranchKind }
// sort by CommiTime of the branch
type SortBranchTime []*Branch
func (s SortBranchTime) Len() int { return len(s) }
func (s SortBranchTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s SortBranchTime) Less(i, j int) bool { return s[i].CommitTime > s[j].CommitTime }
func GetBranchesByPathNoLimit(ctx context.Context, path string) ([]*git.Branch, int, error) {
gitRepo, err := git.OpenRepository(ctx, path)
if err != nil {
return nil, 0, err
}
defer gitRepo.Close()
brs, countAll, err := gitRepo.GetBranchNames(0, 0)
if err != nil {
return nil, 0, err
}
branches := make([]*git.Branch, len(brs))
for i := range brs {
branches[i] = &git.Branch{
Path: gitRepo.Path,
Name: brs[i],
}
}
return branches, countAll, nil
}

View File

@ -11,6 +11,7 @@ import (
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
@ -56,8 +57,10 @@ func Routers() *web.Route {
m.Group("/repos", func() {
m.Group("/{username}/{reponame}", func() {
m.Get("/branch_name_set", context.ReferencesGitRepo(), repo.BranchNameSet)
m.Get("/tag_name_set", context.ReferencesGitRepo(), repo.TagNameSet)
m.Group("/branches", func() {
m.Get("/branches_slice", context.ReferencesGitRepo(), repo.ListBranchesSlice)
}, reqRepoReader(unit_model.TypeCode))
m.Group("/wikies", func() {
m.Combo("").Get(repo.ListWikiPages).
Post(bind(hat_api.WikiOption{}), repo.CreateWiki)
@ -182,3 +185,13 @@ func bind(obj interface{}) http.HandlerFunc {
web.SetForm(ctx, theObj)
})
}
// reqRepoReader user should have specific read permission or be a repo admin or a site admin
func reqRepoReader(unitType unit_model.Type) func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.IsUserRepoReaderSpecific(unitType) && !ctx.IsUserRepoAdmin() && !ctx.IsUserSiteAdmin() {
ctx.Error(http.StatusForbidden, "reqRepoReader", "user should have specific read permission or be a repo admin or a site admin")
return
}
}
}

111
routers/hat/repo/branch.go Normal file
View File

@ -0,0 +1,111 @@
package repo
import (
"fmt"
"net/http"
"sort"
"time"
git_model "code.gitea.io/gitea/models/git"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
hat_convert "code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/convert"
"code.gitlink.org.cn/Gitlink/gitea_hat.git/modules/git"
"code.gitea.io/gitea/routers/api/v1/utils"
)
func ListBranchesSlice(ctx *context.APIContext) {
listOptions := utils.GetListOptions(ctx)
skip, _ := listOptions.GetStartEnd()
branches, totalNumOfBranches, err := ctx.Repo.GitRepo.GetBranches(0, 0)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetBranches", err)
return
}
apiBranches := make([]*git.Branch, len(branches))
for i, branch := range branches {
c, err := branch.GetCommit()
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetCommit", err)
return
}
branchProtection, err := git_model.GetProtectedBranchBy(ctx, ctx.Repo.Repository.ID, branch.Name)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchBy", err)
return
}
sBranch, err := convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin())
if err != nil {
ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err)
return
}
gitBranch := &git.Branch{}
gitBranch.Branch = sBranch
gitBranch.CommitID = c.ID.String()
gitBranch.CommitTime = c.Author.When.Format(time.RFC3339)
gitBranch.DefaultBranch = ctx.Repo.Repository.DefaultBranch
gitBranch.BranchKind = int(git.OtherBranch)
apiBranches[i] = gitBranch
if branchProtection != nil {
apiBranches[i].BranchKind = int(git.ProtectedBranch)
}
if branch.Name == ctx.Repo.Repository.DefaultBranch {
apiBranches[i].BranchKind = int(git.DefaultBranch)
}
sort.Sort(git.SortBranch(apiBranches))
branchSlice := paginate(apiBranches, skip, listOptions.Page)
BranchesSlice := BranchesSliceByProtection(ctx, branchSlice)
ctx.SetLinkHeader(int(totalNumOfBranches), listOptions.PageSize)
ctx.RespHeader().Set("X-Total-Count", fmt.Sprintf("%d", totalNumOfBranches))
ctx.RespHeader().Set("Access-Control-Expose-Headers", "X-Total-Count, Link")
ctx.JSON(http.StatusOK, &BranchesSlice)
}
}
func paginate(branchSlice []*git.Branch, skip, pageSize int) []*git.Branch {
limit := func() int {
if skip+pageSize > len(branchSlice) {
return len(branchSlice)
} else {
return skip + pageSize
}
}
start := func() int {
if skip > len(branchSlice) {
return len(branchSlice)
} else {
return skip
}
}
return branchSlice[start():limit()]
}
func BranchesSliceByProtection(ctx *context.APIContext, branchList []*git.Branch) []git.BranchesSlice {
// group by protection
sort.Sort(git.SortBranch(branchList))
branchSlice := make([]git.BranchesSlice, 0)
i := 0
var j int
for {
if i >= len(branchList) {
break
}
for j = i + 1; j < len(branchList) && (branchList[i].BranchKind == branchList[j].BranchKind); j++ {
}
// get the same branches
sameBranchSlice := branchList[i:j]
// sort by time
sort.Sort(git.SortBranchTime(sameBranchSlice))
branchSlice = append(branchSlice, git.BranchesSlice{
BranchName: hat_convert.ToBranchType(branchList[i].BranchKind).Name(),
Branches: sameBranchSlice,
})
i = j
}
return branchSlice
}