123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- package gig
- import (
- "encoding/hex"
- "fmt"
- "io"
- "os"
- "strings"
- "time"
- )
- //SHA1 is the object identifying checksum of
- // the object data
- type SHA1 [20]byte
- func (oid SHA1) String() string {
- return hex.EncodeToString(oid[:])
- }
- //ParseSHA1 expects a string with a hex encoded sha1.
- //It will trim the string of newline and space before
- //parsing.
- func ParseSHA1(input string) (sha SHA1, err error) {
- data, err := hex.DecodeString(strings.Trim(input, " \n"))
- if err != nil {
- return
- } else if len(data) != 20 {
- err = fmt.Errorf("git: sha1 must be 20 bytes")
- return
- }
- copy(sha[:], data)
- return
- }
- //Signature is a combination of who (Name, Email) and when (Date, Offset).
- //Used by Commit, Tag to link an action (committer, author, tagger, ...)
- //with a person in a point in time.
- type Signature struct {
- Name string
- Email string
- Date time.Time
- Offset *time.Location
- }
- func (s Signature) String() string {
- return fmt.Sprintf("%s <%s> %d %s", s.Name, s.Email, s.Date.Unix(), s.Offset)
- }
- //ObjectType is to the git object type
- type ObjectType byte
- //The defined bits match the ones used in
- //the git pack file format.
- const (
- _ = iota
- ObjCommit = ObjectType(iota)
- ObjTree
- ObjBlob
- ObjTag
- ObjOFSDelta = ObjectType(0x6)
- ObjRefDelta = ObjectType(0x7)
- )
- //ParseObjectType takes a string and converts it
- //to the corresponding ObjectType or error if
- //the string doesn't match any type.
- func ParseObjectType(s string) (ObjectType, error) {
- s = strings.Trim(s, "\n ")
- switch s {
- case "commit":
- return ObjCommit, nil
- case "tree":
- return ObjTree, nil
- case "blob":
- return ObjBlob, nil
- case "tag":
- return ObjTag, nil
- }
- return ObjectType(0), fmt.Errorf("git: unknown object: %q", s)
- }
- func (ot ObjectType) String() string {
- switch ot {
- case ObjCommit:
- return "commit"
- case ObjTree:
- return "tree"
- case ObjBlob:
- return "blob"
- case ObjTag:
- return "tag"
- case ObjOFSDelta:
- return "delta-ofs"
- case ObjRefDelta:
- return "delta-ref"
- }
- return "unknown"
- }
- //IsStandardObject checks if an object is
- //one of the four common objects such as
- //commit, tree, blob, tag.
- func IsStandardObject(ot ObjectType) bool {
- return ot > 0 && ot < 5
- }
- //IsDeltaObject checks if an object is a
- //delta object, i.e. OFSDelta or RefDelta
- func IsDeltaObject(ot ObjectType) bool {
- return ot == ObjOFSDelta || ot == ObjRefDelta
- }
- //Object represents a git object. It has
- //information common to all git objects,
- //like their type and their size. Also,
- //all git objects should be closed via
- //Close().
- type Object interface {
- Type() ObjectType
- Size() int64
- io.WriterTo
- io.Closer
- }
- type gitObject struct {
- otype ObjectType
- size int64
- source io.ReadCloser
- }
- func (o *gitObject) Type() ObjectType {
- return o.otype
- }
- func (o *gitObject) Size() int64 {
- return o.size
- }
- func (o *gitObject) Close() error {
- if o.source == nil {
- return nil
- }
- return o.source.Close()
- }
- //Commit represents one git commit.
- type Commit struct {
- gitObject
- Tree SHA1
- Parent []SHA1
- Author Signature
- Committer Signature
- Message string
- GPGSig string
- }
- //Date returns the commit timestamps (with the correct location).
- func (c *Commit) Date() time.Time {
- return c.Committer.Date.In(c.Committer.Offset)
- }
- //Tree represents the git tree object.
- type Tree struct {
- gitObject
- entry *TreeEntry
- err error
- }
- //TreeEntry holds information about a single
- //entry in the git Tree object.
- type TreeEntry struct {
- Mode os.FileMode
- Type ObjectType
- ID SHA1
- Name string
- }
- //Next advances the pointer to the next TreeEntry
- //within the Tree object. Returns false if it was
- //pointing to the last element (EOF condition), or
- //if there was an error while advacing. Use Err()
- //to resolve between the to conditions.
- func (tree *Tree) Next() bool {
- tree.entry, tree.err = parseTreeEntry(tree.source)
- return tree.err == nil
- }
- //Err returns the last error non-EOF error encountered.
- func (tree *Tree) Err() error {
- if err := tree.err; err != nil && err != io.EOF {
- return err
- }
- return nil
- }
- //Entry returns the current TreeEntry.
- func (tree *Tree) Entry() *TreeEntry {
- return tree.entry
- }
- //Blob represents a git blob object.
- type Blob struct {
- gitObject
- }
- func (b *Blob) Read(data []byte) (n int, err error) {
- n, err = b.source.Read(data)
- return
- }
- func MakeAnnexBlob(fp *os.File, size int64) *Blob {
- return &Blob{gitObject{otype: ObjBlob, size: size, source: fp}}
- }
- //Tag represents a git tag object.
- type Tag struct {
- gitObject
- Object SHA1
- ObjType ObjectType
- Tag string
- Tagger Signature
- Message string
- GPGSig string
- }
|