Skip to content

Commit

Permalink
Make gogit Repository.GetBranchNames consistent (#28348) (#28386)
Browse files Browse the repository at this point in the history
Backport #28348 by @AdamMajer

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

Co-authored-by: Adam Majer <amajer@suse.de>
  • Loading branch information
GiteaBot and AdamMajer authored Dec 7, 2023
1 parent b56a9f6 commit 272ae03
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 272ae03

Please sign in to comment.