Skip to content

Commit

Permalink
Make gogit Repository.GetBranchNames consistent
Browse files Browse the repository at this point in the history
nogogit GetBranchNames() lists branches sorted in reverse commit date
order. On the other hand the gogit implementation doesn't apply any
ordering resulting in unpredictable behaviour. In my case, the unit
tests requiring particular order fail

    repo_branch_test.go:24:
                Error Trace:
               ./gitea/modules/git/repo_branch_test.go:24
                Error:          elements differ

                                extra elements in list A:
                                ([]interface {}) (len=1) {
                                 (string) (len=6) "master"
                                }

                                extra elements in list B:
                                ([]interface {}) (len=1) {
                                 (string) (len=7) "branch1"
                                }

                                listA:
                                ([]string) (len=2) {
                                 (string) (len=6) "master",
                                 (string) (len=7) "branch2"
                                }

                                listB:
                                ([]string) (len=2) {
                                 (string) (len=7) "branch1",
                                 (string) (len=7) "branch2"
                                }
                Test:           TestRepository_GetBranches

To fix this, we sort branches based on their commit date in gogit
implementation.

Fixes: #28318
  • Loading branch information
AdamMajer committed Dec 4, 2023
1 parent ec1feed commit b5406ec
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions modules/git/repo_branch_gogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package git

import (
"context"
"sort"
"strings"

"github.com/go-git/go-git/v5/plumbing"
Expand Down Expand Up @@ -52,32 +53,46 @@ func (repo *Repository) IsBranchExist(name string) bool {

// GetBranches returns branches from the repository, skipping "skip" initial branches and
// returning at most "limit" branches, or all branches if "limit" is 0.
// Branches are returned with sort of `-commiterdate` as the nogogit
// implementation. This requires full fetch, sort and then the
// skip/limit applies later as gogit returns in undefined order.
func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
var branchNames []string
type BranchData struct {
name string
committerDate int64
}
var branchData []BranchData

branches, err := repo.gogitRepo.Branches()
branchIter, err := repo.gogitRepo.Branches()
if err != nil {
return nil, 0, err
}

i := 0
count := 0
_ = branches.ForEach(func(branch *plumbing.Reference) error {
count++
if i < skip {
i++
return nil
} else if limit != 0 && count > skip+limit {
_ = branchIter.ForEach(func(branch *plumbing.Reference) error {
obj, err := repo.gogitRepo.CommitObject(branch.Hash())
if err != nil {
// skip branch if can't find commit
return nil
}

branchNames = append(branchNames, strings.TrimPrefix(branch.Name().String(), BranchPrefix))
branchData = append(branchData, BranchData{strings.TrimPrefix(branch.Name().String(), BranchPrefix), obj.Committer.When.Unix()})
return nil
})

// TODO: Sort?
sort.Slice(branchData, func(i, j int) bool {
return !(branchData[i].committerDate < branchData[j].committerDate)
})

var branchNames []string
maxPos := len(branchData)
if limit > 0 {
maxPos = min(skip+limit, maxPos)
}
for i := skip; i < maxPos; i++ {
branchNames = append(branchNames, branchData[i].name)
}

return branchNames, count, nil
return branchNames, len(branchData), nil
}

// WalkReferences walks all the references from the repository
Expand Down

0 comments on commit b5406ec

Please sign in to comment.