gitea源码

repo_branch_gogit.go 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. "sort"
  8. "strings"
  9. "github.com/go-git/go-git/v5/plumbing"
  10. "github.com/go-git/go-git/v5/plumbing/storer"
  11. )
  12. // IsObjectExist returns true if the given object exists in the repository.
  13. // FIXME: Inconsistent behavior with nogogit edition
  14. // Unlike the implementation of IsObjectExist in nogogit edition, it does not support short hashes here.
  15. // For example, IsObjectExist("153f451") will return false, but it will return true in nogogit edition.
  16. // To fix this, the solution could be adding support for short hashes in gogit edition if it's really needed.
  17. func (repo *Repository) IsObjectExist(name string) bool {
  18. if name == "" {
  19. return false
  20. }
  21. _, err := repo.gogitRepo.Object(plumbing.AnyObject, plumbing.NewHash(name))
  22. return err == nil
  23. }
  24. // IsReferenceExist returns true if given reference exists in the repository.
  25. // FIXME: Inconsistent behavior with nogogit edition
  26. // Unlike the implementation of IsObjectExist in nogogit edition, it does not support blob hashes here.
  27. // For example, IsObjectExist([existing_blob_hash]) will return false, but it will return true in nogogit edition.
  28. // To fix this, the solution could be refusing to support blob hashes in nogogit edition since a blob hash is not a reference.
  29. func (repo *Repository) IsReferenceExist(name string) bool {
  30. if name == "" {
  31. return false
  32. }
  33. _, err := repo.gogitRepo.ResolveRevision(plumbing.Revision(name))
  34. return err == nil
  35. }
  36. // IsBranchExist returns true if given branch exists in current repository.
  37. func (repo *Repository) IsBranchExist(name string) bool {
  38. if name == "" {
  39. return false
  40. }
  41. reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true)
  42. if err != nil {
  43. return false
  44. }
  45. return reference.Type() != plumbing.InvalidReference
  46. }
  47. // GetBranches returns branches from the repository, skipping "skip" initial branches and
  48. // returning at most "limit" branches, or all branches if "limit" is 0.
  49. // Branches are returned with sort of `-committerdate` as the nogogit
  50. // implementation. This requires full fetch, sort and then the
  51. // skip/limit applies later as gogit returns in undefined order.
  52. func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
  53. type BranchData struct {
  54. name string
  55. committerDate int64
  56. }
  57. var branchData []BranchData
  58. branchIter, err := repo.gogitRepo.Branches()
  59. if err != nil {
  60. return nil, 0, err
  61. }
  62. _ = branchIter.ForEach(func(branch *plumbing.Reference) error {
  63. obj, err := repo.gogitRepo.CommitObject(branch.Hash())
  64. if err != nil {
  65. // skip branch if can't find commit
  66. return nil
  67. }
  68. branchData = append(branchData, BranchData{strings.TrimPrefix(branch.Name().String(), BranchPrefix), obj.Committer.When.Unix()})
  69. return nil
  70. })
  71. sort.Slice(branchData, func(i, j int) bool {
  72. return !(branchData[i].committerDate < branchData[j].committerDate)
  73. })
  74. var branchNames []string
  75. maxPos := len(branchData)
  76. if limit > 0 {
  77. maxPos = min(skip+limit, maxPos)
  78. }
  79. for i := skip; i < maxPos; i++ {
  80. branchNames = append(branchNames, branchData[i].name)
  81. }
  82. return branchNames, len(branchData), nil
  83. }
  84. // WalkReferences walks all the references from the repository
  85. func (repo *Repository) WalkReferences(arg ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) {
  86. i := 0
  87. var iter storer.ReferenceIter
  88. var err error
  89. switch arg {
  90. case ObjectTag:
  91. iter, err = repo.gogitRepo.Tags()
  92. case ObjectBranch:
  93. iter, err = repo.gogitRepo.Branches()
  94. default:
  95. iter, err = repo.gogitRepo.References()
  96. }
  97. if err != nil {
  98. return i, err
  99. }
  100. defer iter.Close()
  101. err = iter.ForEach(func(ref *plumbing.Reference) error {
  102. if i < skip {
  103. i++
  104. return nil
  105. }
  106. err := walkfn(ref.Hash().String(), string(ref.Name()))
  107. i++
  108. if err != nil {
  109. return err
  110. }
  111. if limit != 0 && i >= skip+limit {
  112. return storer.ErrStop
  113. }
  114. return nil
  115. })
  116. return i, err
  117. }
  118. // GetRefsBySha returns all references filtered with prefix that belong to a sha commit hash
  119. func (repo *Repository) GetRefsBySha(sha, prefix string) ([]string, error) {
  120. var revList []string
  121. iter, err := repo.gogitRepo.References()
  122. if err != nil {
  123. return nil, err
  124. }
  125. err = iter.ForEach(func(ref *plumbing.Reference) error {
  126. if ref.Hash().String() == sha && strings.HasPrefix(string(ref.Name()), prefix) {
  127. revList = append(revList, string(ref.Name()))
  128. }
  129. return nil
  130. })
  131. return revList, err
  132. }