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

210 lines
4.9KB

  1. package plumbing
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. )
  7. const (
  8. refPrefix = "refs/"
  9. refHeadPrefix = refPrefix + "heads/"
  10. refTagPrefix = refPrefix + "tags/"
  11. refRemotePrefix = refPrefix + "remotes/"
  12. refNotePrefix = refPrefix + "notes/"
  13. symrefPrefix = "ref: "
  14. )
  15. // RefRevParseRules are a set of rules to parse references into short names.
  16. // These are the same rules as used by git in shorten_unambiguous_ref.
  17. // See: https://github.com/git/git/blob/e0aaa1b6532cfce93d87af9bc813fb2e7a7ce9d7/refs.c#L417
  18. var RefRevParseRules = []string{
  19. "refs/%s",
  20. "refs/tags/%s",
  21. "refs/heads/%s",
  22. "refs/remotes/%s",
  23. "refs/remotes/%s/HEAD",
  24. }
  25. var (
  26. ErrReferenceNotFound = errors.New("reference not found")
  27. )
  28. // ReferenceType reference type's
  29. type ReferenceType int8
  30. const (
  31. InvalidReference ReferenceType = 0
  32. HashReference ReferenceType = 1
  33. SymbolicReference ReferenceType = 2
  34. )
  35. func (r ReferenceType) String() string {
  36. switch r {
  37. case InvalidReference:
  38. return "invalid-reference"
  39. case HashReference:
  40. return "hash-reference"
  41. case SymbolicReference:
  42. return "symbolic-reference"
  43. }
  44. return ""
  45. }
  46. // ReferenceName reference name's
  47. type ReferenceName string
  48. // NewBranchReferenceName returns a reference name describing a branch based on
  49. // his short name.
  50. func NewBranchReferenceName(name string) ReferenceName {
  51. return ReferenceName(refHeadPrefix + name)
  52. }
  53. // NewNoteReferenceName returns a reference name describing a note based on his
  54. // short name.
  55. func NewNoteReferenceName(name string) ReferenceName {
  56. return ReferenceName(refNotePrefix + name)
  57. }
  58. // NewRemoteReferenceName returns a reference name describing a remote branch
  59. // based on his short name and the remote name.
  60. func NewRemoteReferenceName(remote, name string) ReferenceName {
  61. return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, name))
  62. }
  63. // NewRemoteHEADReferenceName returns a reference name describing a the HEAD
  64. // branch of a remote.
  65. func NewRemoteHEADReferenceName(remote string) ReferenceName {
  66. return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, HEAD))
  67. }
  68. // NewTagReferenceName returns a reference name describing a tag based on short
  69. // his name.
  70. func NewTagReferenceName(name string) ReferenceName {
  71. return ReferenceName(refTagPrefix + name)
  72. }
  73. // IsBranch check if a reference is a branch
  74. func (r ReferenceName) IsBranch() bool {
  75. return strings.HasPrefix(string(r), refHeadPrefix)
  76. }
  77. // IsNote check if a reference is a note
  78. func (r ReferenceName) IsNote() bool {
  79. return strings.HasPrefix(string(r), refNotePrefix)
  80. }
  81. // IsRemote check if a reference is a remote
  82. func (r ReferenceName) IsRemote() bool {
  83. return strings.HasPrefix(string(r), refRemotePrefix)
  84. }
  85. // IsTag check if a reference is a tag
  86. func (r ReferenceName) IsTag() bool {
  87. return strings.HasPrefix(string(r), refTagPrefix)
  88. }
  89. func (r ReferenceName) String() string {
  90. return string(r)
  91. }
  92. // Short returns the short name of a ReferenceName
  93. func (r ReferenceName) Short() string {
  94. s := string(r)
  95. res := s
  96. for _, format := range RefRevParseRules {
  97. _, err := fmt.Sscanf(s, format, &res)
  98. if err == nil {
  99. continue
  100. }
  101. }
  102. return res
  103. }
  104. const (
  105. HEAD ReferenceName = "HEAD"
  106. Master ReferenceName = "refs/heads/master"
  107. )
  108. // Reference is a representation of git reference
  109. type Reference struct {
  110. t ReferenceType
  111. n ReferenceName
  112. h Hash
  113. target ReferenceName
  114. }
  115. // NewReferenceFromStrings creates a reference from name and target as string,
  116. // the resulting reference can be a SymbolicReference or a HashReference base
  117. // on the target provided
  118. func NewReferenceFromStrings(name, target string) *Reference {
  119. n := ReferenceName(name)
  120. if strings.HasPrefix(target, symrefPrefix) {
  121. target := ReferenceName(target[len(symrefPrefix):])
  122. return NewSymbolicReference(n, target)
  123. }
  124. return NewHashReference(n, NewHash(target))
  125. }
  126. // NewSymbolicReference creates a new SymbolicReference reference
  127. func NewSymbolicReference(n, target ReferenceName) *Reference {
  128. return &Reference{
  129. t: SymbolicReference,
  130. n: n,
  131. target: target,
  132. }
  133. }
  134. // NewHashReference creates a new HashReference reference
  135. func NewHashReference(n ReferenceName, h Hash) *Reference {
  136. return &Reference{
  137. t: HashReference,
  138. n: n,
  139. h: h,
  140. }
  141. }
  142. // Type return the type of a reference
  143. func (r *Reference) Type() ReferenceType {
  144. return r.t
  145. }
  146. // Name return the name of a reference
  147. func (r *Reference) Name() ReferenceName {
  148. return r.n
  149. }
  150. // Hash return the hash of a hash reference
  151. func (r *Reference) Hash() Hash {
  152. return r.h
  153. }
  154. // Target return the target of a symbolic reference
  155. func (r *Reference) Target() ReferenceName {
  156. return r.target
  157. }
  158. // Strings dump a reference as a [2]string
  159. func (r *Reference) Strings() [2]string {
  160. var o [2]string
  161. o[0] = r.Name().String()
  162. switch r.Type() {
  163. case HashReference:
  164. o[1] = r.Hash().String()
  165. case SymbolicReference:
  166. o[1] = symrefPrefix + r.Target().String()
  167. }
  168. return o
  169. }
  170. func (r *Reference) String() string {
  171. s := r.Strings()
  172. return fmt.Sprintf("%s %s", s[1], s[0])
  173. }
上海开阖软件有限公司 沪ICP备12045867号-1