本站源代码
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.

241 lines
6.2KB

  1. package storer
  2. import (
  3. "errors"
  4. "io"
  5. "gopkg.in/src-d/go-git.v4/plumbing"
  6. )
  7. const MaxResolveRecursion = 1024
  8. // ErrMaxResolveRecursion is returned by ResolveReference is MaxResolveRecursion
  9. // is exceeded
  10. var ErrMaxResolveRecursion = errors.New("max. recursion level reached")
  11. // ReferenceStorer is a generic storage of references.
  12. type ReferenceStorer interface {
  13. SetReference(*plumbing.Reference) error
  14. // CheckAndSetReference sets the reference `new`, but if `old` is
  15. // not `nil`, it first checks that the current stored value for
  16. // `old.Name()` matches the given reference value in `old`. If
  17. // not, it returns an error and doesn't update `new`.
  18. CheckAndSetReference(new, old *plumbing.Reference) error
  19. Reference(plumbing.ReferenceName) (*plumbing.Reference, error)
  20. IterReferences() (ReferenceIter, error)
  21. RemoveReference(plumbing.ReferenceName) error
  22. CountLooseRefs() (int, error)
  23. PackRefs() error
  24. }
  25. // ReferenceIter is a generic closable interface for iterating over references.
  26. type ReferenceIter interface {
  27. Next() (*plumbing.Reference, error)
  28. ForEach(func(*plumbing.Reference) error) error
  29. Close()
  30. }
  31. type referenceFilteredIter struct {
  32. ff func(r *plumbing.Reference) bool
  33. iter ReferenceIter
  34. }
  35. // NewReferenceFilteredIter returns a reference iterator for the given reference
  36. // Iterator. This iterator will iterate only references that accomplish the
  37. // provided function.
  38. func NewReferenceFilteredIter(
  39. ff func(r *plumbing.Reference) bool, iter ReferenceIter) ReferenceIter {
  40. return &referenceFilteredIter{ff, iter}
  41. }
  42. // Next returns the next reference from the iterator. If the iterator has reached
  43. // the end it will return io.EOF as an error.
  44. func (iter *referenceFilteredIter) Next() (*plumbing.Reference, error) {
  45. for {
  46. r, err := iter.iter.Next()
  47. if err != nil {
  48. return nil, err
  49. }
  50. if iter.ff(r) {
  51. return r, nil
  52. }
  53. continue
  54. }
  55. }
  56. // ForEach call the cb function for each reference contained on this iter until
  57. // an error happens or the end of the iter is reached. If ErrStop is sent
  58. // the iteration is stopped but no error is returned. The iterator is closed.
  59. func (iter *referenceFilteredIter) ForEach(cb func(*plumbing.Reference) error) error {
  60. defer iter.Close()
  61. for {
  62. r, err := iter.Next()
  63. if err == io.EOF {
  64. break
  65. }
  66. if err != nil {
  67. return err
  68. }
  69. if err := cb(r); err != nil {
  70. if err == ErrStop {
  71. break
  72. }
  73. return err
  74. }
  75. }
  76. return nil
  77. }
  78. // Close releases any resources used by the iterator.
  79. func (iter *referenceFilteredIter) Close() {
  80. iter.iter.Close()
  81. }
  82. // ReferenceSliceIter implements ReferenceIter. It iterates over a series of
  83. // references stored in a slice and yields each one in turn when Next() is
  84. // called.
  85. //
  86. // The ReferenceSliceIter must be closed with a call to Close() when it is no
  87. // longer needed.
  88. type ReferenceSliceIter struct {
  89. series []*plumbing.Reference
  90. pos int
  91. }
  92. // NewReferenceSliceIter returns a reference iterator for the given slice of
  93. // objects.
  94. func NewReferenceSliceIter(series []*plumbing.Reference) ReferenceIter {
  95. return &ReferenceSliceIter{
  96. series: series,
  97. }
  98. }
  99. // Next returns the next reference from the iterator. If the iterator has
  100. // reached the end it will return io.EOF as an error.
  101. func (iter *ReferenceSliceIter) Next() (*plumbing.Reference, error) {
  102. if iter.pos >= len(iter.series) {
  103. return nil, io.EOF
  104. }
  105. obj := iter.series[iter.pos]
  106. iter.pos++
  107. return obj, nil
  108. }
  109. // ForEach call the cb function for each reference contained on this iter until
  110. // an error happens or the end of the iter is reached. If ErrStop is sent
  111. // the iteration is stop but no error is returned. The iterator is closed.
  112. func (iter *ReferenceSliceIter) ForEach(cb func(*plumbing.Reference) error) error {
  113. return forEachReferenceIter(iter, cb)
  114. }
  115. type bareReferenceIterator interface {
  116. Next() (*plumbing.Reference, error)
  117. Close()
  118. }
  119. func forEachReferenceIter(iter bareReferenceIterator, cb func(*plumbing.Reference) error) error {
  120. defer iter.Close()
  121. for {
  122. obj, err := iter.Next()
  123. if err != nil {
  124. if err == io.EOF {
  125. return nil
  126. }
  127. return err
  128. }
  129. if err := cb(obj); err != nil {
  130. if err == ErrStop {
  131. return nil
  132. }
  133. return err
  134. }
  135. }
  136. }
  137. // Close releases any resources used by the iterator.
  138. func (iter *ReferenceSliceIter) Close() {
  139. iter.pos = len(iter.series)
  140. }
  141. // MultiReferenceIter implements ReferenceIter. It iterates over several
  142. // ReferenceIter,
  143. //
  144. // The MultiReferenceIter must be closed with a call to Close() when it is no
  145. // longer needed.
  146. type MultiReferenceIter struct {
  147. iters []ReferenceIter
  148. }
  149. // NewMultiReferenceIter returns an reference iterator for the given slice of
  150. // EncodedObjectIters.
  151. func NewMultiReferenceIter(iters []ReferenceIter) ReferenceIter {
  152. return &MultiReferenceIter{iters: iters}
  153. }
  154. // Next returns the next reference from the iterator, if one iterator reach
  155. // io.EOF is removed and the next one is used.
  156. func (iter *MultiReferenceIter) Next() (*plumbing.Reference, error) {
  157. if len(iter.iters) == 0 {
  158. return nil, io.EOF
  159. }
  160. obj, err := iter.iters[0].Next()
  161. if err == io.EOF {
  162. iter.iters[0].Close()
  163. iter.iters = iter.iters[1:]
  164. return iter.Next()
  165. }
  166. return obj, err
  167. }
  168. // ForEach call the cb function for each reference contained on this iter until
  169. // an error happens or the end of the iter is reached. If ErrStop is sent
  170. // the iteration is stop but no error is returned. The iterator is closed.
  171. func (iter *MultiReferenceIter) ForEach(cb func(*plumbing.Reference) error) error {
  172. return forEachReferenceIter(iter, cb)
  173. }
  174. // Close releases any resources used by the iterator.
  175. func (iter *MultiReferenceIter) Close() {
  176. for _, i := range iter.iters {
  177. i.Close()
  178. }
  179. }
  180. // ResolveReference resolves a SymbolicReference to a HashReference.
  181. func ResolveReference(s ReferenceStorer, n plumbing.ReferenceName) (*plumbing.Reference, error) {
  182. r, err := s.Reference(n)
  183. if err != nil || r == nil {
  184. return r, err
  185. }
  186. return resolveReference(s, r, 0)
  187. }
  188. func resolveReference(s ReferenceStorer, r *plumbing.Reference, recursion int) (*plumbing.Reference, error) {
  189. if r.Type() != plumbing.SymbolicReference {
  190. return r, nil
  191. }
  192. if recursion > MaxResolveRecursion {
  193. return nil, ErrMaxResolveRecursion
  194. }
  195. t, err := s.Reference(r.Target())
  196. if err != nil {
  197. return nil, err
  198. }
  199. recursion++
  200. return resolveReference(s, t, recursion)
  201. }
上海开阖软件有限公司 沪ICP备12045867号-1