You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo_branch_gogit.go 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. //go:build gogit
  5. package git
  6. import (
  7. "context"
  8. "sort"
  9. "strings"
  10. "github.com/go-git/go-git/v5/plumbing"
  11. "github.com/go-git/go-git/v5/plumbing/storer"
  12. )
  13. // IsObjectExist returns true if given reference exists in the repository.
  14. func (repo *Repository) IsObjectExist(name string) bool {
  15. if name == "" {
  16. return false
  17. }
  18. _, err := repo.gogitRepo.ResolveRevision(plumbing.Revision(name))
  19. return err == nil
  20. }
  21. // IsReferenceExist returns true if given reference exists in the repository.
  22. func (repo *Repository) IsReferenceExist(name string) bool {
  23. if name == "" {
  24. return false
  25. }
  26. reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(name), true)
  27. if err != nil {
  28. return false
  29. }
  30. return reference.Type() != plumbing.InvalidReference
  31. }
  32. // IsBranchExist returns true if given branch exists in current repository.
  33. func (repo *Repository) IsBranchExist(name string) bool {
  34. if name == "" {
  35. return false
  36. }
  37. reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true)
  38. if err != nil {
  39. return false
  40. }
  41. return reference.Type() != plumbing.InvalidReference
  42. }
  43. // GetBranches returns branches from the repository, skipping "skip" initial branches and
  44. // returning at most "limit" branches, or all branches if "limit" is 0.
  45. // Branches are returned with sort of `-commiterdate` as the nogogit
  46. // implementation. This requires full fetch, sort and then the
  47. // skip/limit applies later as gogit returns in undefined order.
  48. func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
  49. type BranchData struct {
  50. name string
  51. committerDate int64
  52. }
  53. var branchData []BranchData
  54. branchIter, err := repo.gogitRepo.Branches()
  55. if err != nil {
  56. return nil, 0, err
  57. }
  58. _ = branchIter.ForEach(func(branch *plumbing.Reference) error {
  59. obj, err := repo.gogitRepo.CommitObject(branch.Hash())
  60. if err != nil {
  61. // skip branch if can't find commit
  62. return nil
  63. }
  64. branchData = append(branchData, BranchData{strings.TrimPrefix(branch.Name().String(), BranchPrefix), obj.Committer.When.Unix()})
  65. return nil
  66. })
  67. sort.Slice(branchData, func(i, j int) bool {
  68. return !(branchData[i].committerDate < branchData[j].committerDate)
  69. })
  70. var branchNames []string
  71. maxPos := len(branchData)
  72. if limit > 0 {
  73. maxPos = min(skip+limit, maxPos)
  74. }
  75. for i := skip; i < maxPos; i++ {
  76. branchNames = append(branchNames, branchData[i].name)
  77. }
  78. return branchNames, len(branchData), nil
  79. }
  80. // WalkReferences walks all the references from the repository
  81. // refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty.
  82. func WalkReferences(ctx context.Context, repoPath string, walkfn func(sha1, refname string) error) (int, error) {
  83. repo := RepositoryFromContext(ctx, repoPath)
  84. if repo == nil {
  85. var err error
  86. repo, err = OpenRepository(ctx, repoPath)
  87. if err != nil {
  88. return 0, err
  89. }
  90. defer repo.Close()
  91. }
  92. i := 0
  93. iter, err := repo.gogitRepo.References()
  94. if err != nil {
  95. return i, err
  96. }
  97. defer iter.Close()
  98. err = iter.ForEach(func(ref *plumbing.Reference) error {
  99. err := walkfn(ref.Hash().String(), string(ref.Name()))
  100. i++
  101. return err
  102. })
  103. return i, err
  104. }
  105. // WalkReferences walks all the references from the repository
  106. func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
  107. i := 0
  108. var iter storer.ReferenceIter
  109. var err error
  110. switch arg {
  111. case ObjectTag:
  112. iter, err = repo.gogitRepo.Tags()
  113. case ObjectBranch:
  114. iter, err = repo.gogitRepo.Branches()
  115. default:
  116. iter, err = repo.gogitRepo.References()
  117. }
  118. if err != nil {
  119. return i, err
  120. }
  121. defer iter.Close()
  122. err = iter.ForEach(func(ref *plumbing.Reference) error {
  123. if i < skip {
  124. i++
  125. return nil
  126. }
  127. err := walkfn(ref.Hash().String(), string(ref.Name()))
  128. i++
  129. if err != nil {
  130. return err
  131. }
  132. if limit != 0 && i >= skip+limit {
  133. return storer.ErrStop
  134. }
  135. return nil
  136. })
  137. return i, err
  138. }
  139. // GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash
  140. func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) {
  141. var revList []string
  142. iter, err := repo.gogitRepo.References()
  143. if err != nil {
  144. return nil, err
  145. }
  146. err = iter.ForEach(func(ref *plumbing.Reference) error {
  147. if ref.Hash().String() == sha && strings.HasPrefix(string(ref.Name()), prefix) {
  148. revList = append(revList, string(ref.Name()))
  149. }
  150. return nil
  151. })
  152. return revList, err
  153. }