objects.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package gig
  2. import (
  3. "encoding/hex"
  4. "fmt"
  5. "io"
  6. "os"
  7. "strings"
  8. "time"
  9. )
  10. //SHA1 is the object identifying checksum of
  11. // the object data
  12. type SHA1 [20]byte
  13. func (oid SHA1) String() string {
  14. return hex.EncodeToString(oid[:])
  15. }
  16. //ParseSHA1 expects a string with a hex encoded sha1.
  17. //It will trim the string of newline and space before
  18. //parsing.
  19. func ParseSHA1(input string) (sha SHA1, err error) {
  20. data, err := hex.DecodeString(strings.Trim(input, " \n"))
  21. if err != nil {
  22. return
  23. } else if len(data) != 20 {
  24. err = fmt.Errorf("git: sha1 must be 20 bytes")
  25. return
  26. }
  27. copy(sha[:], data)
  28. return
  29. }
  30. //Signature is a combination of who (Name, Email) and when (Date, Offset).
  31. //Used by Commit, Tag to link an action (committer, author, tagger, ...)
  32. //with a person in a point in time.
  33. type Signature struct {
  34. Name string
  35. Email string
  36. Date time.Time
  37. Offset *time.Location
  38. }
  39. func (s Signature) String() string {
  40. return fmt.Sprintf("%s <%s> %d %s", s.Name, s.Email, s.Date.Unix(), s.Offset)
  41. }
  42. //ObjectType is to the git object type
  43. type ObjectType byte
  44. //The defined bits match the ones used in
  45. //the git pack file format.
  46. const (
  47. _ = iota
  48. ObjCommit = ObjectType(iota)
  49. ObjTree
  50. ObjBlob
  51. ObjTag
  52. ObjOFSDelta = ObjectType(0x6)
  53. ObjRefDelta = ObjectType(0x7)
  54. )
  55. //ParseObjectType takes a string and converts it
  56. //to the corresponding ObjectType or error if
  57. //the string doesn't match any type.
  58. func ParseObjectType(s string) (ObjectType, error) {
  59. s = strings.Trim(s, "\n ")
  60. switch s {
  61. case "commit":
  62. return ObjCommit, nil
  63. case "tree":
  64. return ObjTree, nil
  65. case "blob":
  66. return ObjBlob, nil
  67. case "tag":
  68. return ObjTag, nil
  69. }
  70. return ObjectType(0), fmt.Errorf("git: unknown object: %q", s)
  71. }
  72. func (ot ObjectType) String() string {
  73. switch ot {
  74. case ObjCommit:
  75. return "commit"
  76. case ObjTree:
  77. return "tree"
  78. case ObjBlob:
  79. return "blob"
  80. case ObjTag:
  81. return "tag"
  82. case ObjOFSDelta:
  83. return "delta-ofs"
  84. case ObjRefDelta:
  85. return "delta-ref"
  86. }
  87. return "unknown"
  88. }
  89. //IsStandardObject checks if an object is
  90. //one of the four common objects such as
  91. //commit, tree, blob, tag.
  92. func IsStandardObject(ot ObjectType) bool {
  93. return ot > 0 && ot < 5
  94. }
  95. //IsDeltaObject checks if an object is a
  96. //delta object, i.e. OFSDelta or RefDelta
  97. func IsDeltaObject(ot ObjectType) bool {
  98. return ot == ObjOFSDelta || ot == ObjRefDelta
  99. }
  100. //Object represents a git object. It has
  101. //information common to all git objects,
  102. //like their type and their size. Also,
  103. //all git objects should be closed via
  104. //Close().
  105. type Object interface {
  106. Type() ObjectType
  107. Size() int64
  108. io.WriterTo
  109. io.Closer
  110. }
  111. type gitObject struct {
  112. otype ObjectType
  113. size int64
  114. source io.ReadCloser
  115. }
  116. func (o *gitObject) Type() ObjectType {
  117. return o.otype
  118. }
  119. func (o *gitObject) Size() int64 {
  120. return o.size
  121. }
  122. func (o *gitObject) Close() error {
  123. if o.source == nil {
  124. return nil
  125. }
  126. return o.source.Close()
  127. }
  128. //Commit represents one git commit.
  129. type Commit struct {
  130. gitObject
  131. Tree SHA1
  132. Parent []SHA1
  133. Author Signature
  134. Committer Signature
  135. Message string
  136. GPGSig string
  137. }
  138. //Date returns the commit timestamps (with the correct location).
  139. func (c *Commit) Date() time.Time {
  140. return c.Committer.Date.In(c.Committer.Offset)
  141. }
  142. //Tree represents the git tree object.
  143. type Tree struct {
  144. gitObject
  145. entry *TreeEntry
  146. err error
  147. }
  148. //TreeEntry holds information about a single
  149. //entry in the git Tree object.
  150. type TreeEntry struct {
  151. Mode os.FileMode
  152. Type ObjectType
  153. ID SHA1
  154. Name string
  155. }
  156. //Next advances the pointer to the next TreeEntry
  157. //within the Tree object. Returns false if it was
  158. //pointing to the last element (EOF condition), or
  159. //if there was an error while advacing. Use Err()
  160. //to resolve between the to conditions.
  161. func (tree *Tree) Next() bool {
  162. tree.entry, tree.err = parseTreeEntry(tree.source)
  163. return tree.err == nil
  164. }
  165. //Err returns the last error non-EOF error encountered.
  166. func (tree *Tree) Err() error {
  167. if err := tree.err; err != nil && err != io.EOF {
  168. return err
  169. }
  170. return nil
  171. }
  172. //Entry returns the current TreeEntry.
  173. func (tree *Tree) Entry() *TreeEntry {
  174. return tree.entry
  175. }
  176. //Blob represents a git blob object.
  177. type Blob struct {
  178. gitObject
  179. }
  180. func (b *Blob) Read(data []byte) (n int, err error) {
  181. n, err = b.source.Read(data)
  182. return
  183. }
  184. func MakeAnnexBlob(fp *os.File, size int64) *Blob {
  185. return &Blob{gitObject{otype: ObjBlob, size: size, source: fp}}
  186. }
  187. //Tag represents a git tag object.
  188. type Tag struct {
  189. gitObject
  190. Object SHA1
  191. ObjType ObjectType
  192. Tag string
  193. Tagger Signature
  194. Message string
  195. GPGSig string
  196. }