diff options
-rw-r--r-- | core/reference.go | 124 | ||||
-rw-r--r-- | core/reference_test.go | 57 |
2 files changed, 181 insertions, 0 deletions
diff --git a/core/reference.go b/core/reference.go new file mode 100644 index 0000000..9114b58 --- /dev/null +++ b/core/reference.go @@ -0,0 +1,124 @@ +package core + +import "strings" + +const ( + refPrefix = "refs/" + refHeadPrefix = refPrefix + "heads/" + refTagPrefix = refPrefix + "tags/" + refRemotePrefix = refPrefix + "remotes/" + refNotePrefix = refPrefix + "notes/" + symrefPrefix = "ref: " +) + +// ReferenceType reference type's +type ReferenceType int8 + +const ( + InvalidReference ReferenceType = 0 + HashReference ReferenceType = 1 + SymbolicReference ReferenceType = 2 +) + +// ReferenceName reference name's +type ReferenceName string + +const ( + HEAD ReferenceName = "HEAD" +) + +// Reference is a representation of git reference +type Reference struct { + t ReferenceType + n ReferenceName + h Hash + target ReferenceName +} + +// NewReferenceFromStrings creates a reference from name and target as string, +// the resulting reference can be a SymbolicReference or a HashReference base +// on the target provided +func NewReferenceFromStrings(name, target string) *Reference { + r := &Reference{n: ReferenceName(name)} + + if strings.HasPrefix(target, symrefPrefix) { + r.t = SymbolicReference + r.target = ReferenceName(target[len(symrefPrefix):]) + return r + } + + r.t = HashReference + r.h = NewHash(target) + return r +} + +// NewSymbolicReference creates a new SymbolicReference reference +func NewSymbolicReference(n, target ReferenceName) *Reference { + return &Reference{ + t: SymbolicReference, + n: n, + target: target, + } +} + +// NewHashReference creates a new HashReference reference +func NewHashReference(n ReferenceName, h Hash) *Reference { + return &Reference{ + t: HashReference, + n: n, + h: h, + } +} + +// Type return the type of a reference +func (r *Reference) Type() ReferenceType { + return r.t +} + +// Name return the name of a reference +func (r *Reference) Name() ReferenceName { + return r.n +} + +// Hash return the hash of a hash reference +func (r *Reference) Hash() Hash { + return r.h +} + +// Target return the target of a symbolic reference +func (r *Reference) Target() ReferenceName { + return r.target +} + +// IsBranch check if a reference is a branch +func (r *Reference) IsBranch() bool { + return strings.HasPrefix(string(r.n), refHeadPrefix) +} + +// IsNote check if a reference is a note +func (r *Reference) IsNote() bool { + return strings.HasPrefix(string(r.n), refNotePrefix) +} + +// IsRemote check if a reference is a remote +func (r *Reference) IsRemote() bool { + return strings.HasPrefix(string(r.n), refRemotePrefix) +} + +// IsTag check if a reference is a tag +func (r *Reference) IsTag() bool { + return strings.HasPrefix(string(r.n), refTagPrefix) +} + +// ReferenceStorage generic storage of references +type ReferenceStorage interface { + Set(Reference) error + Get(ReferenceName) (Reference, error) + Iter(ObjectType) (ReferenceIter, error) +} + +// ReferenceIter is a generic closable interface for iterating over references +type ReferenceIter interface { + Next() (Reference, error) + Close() +} diff --git a/core/reference_test.go b/core/reference_test.go new file mode 100644 index 0000000..05d20b4 --- /dev/null +++ b/core/reference_test.go @@ -0,0 +1,57 @@ +package core + +import . "gopkg.in/check.v1" + +type ReferenceSuite struct{} + +var _ = Suite(&ReferenceSuite{}) + +const ( + ExampleReferenceName ReferenceName = "refs/heads/v4" +) + +func (s *ReferenceSuite) TestNewReferenceFromStrings(c *C) { + r := NewReferenceFromStrings("refs/heads/v4", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") + c.Assert(r.Type(), Equals, HashReference) + c.Assert(r.Name(), Equals, ExampleReferenceName) + c.Assert(r.Hash(), Equals, NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) + + r = NewReferenceFromStrings("HEAD", "ref: refs/heads/v4") + c.Assert(r.Type(), Equals, SymbolicReference) + c.Assert(r.Name(), Equals, HEAD) + c.Assert(r.Target(), Equals, ExampleReferenceName) +} + +func (s *ReferenceSuite) TestNewSymbolicReference(c *C) { + r := NewSymbolicReference(HEAD, ExampleReferenceName) + c.Assert(r.Type(), Equals, SymbolicReference) + c.Assert(r.Name(), Equals, HEAD) + c.Assert(r.Target(), Equals, ExampleReferenceName) +} + +func (s *ReferenceSuite) TestNewHashReference(c *C) { + r := NewHashReference(ExampleReferenceName, NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) + c.Assert(r.Type(), Equals, HashReference) + c.Assert(r.Name(), Equals, ExampleReferenceName) + c.Assert(r.Hash(), Equals, NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) +} + +func (s *ReferenceSuite) TestIsBranch(c *C) { + r := NewHashReference(ExampleReferenceName, ZeroHash) + c.Assert(r.IsBranch(), Equals, true) +} + +func (s *ReferenceSuite) TestIsNote(c *C) { + r := NewHashReference(ReferenceName("refs/notes/foo"), ZeroHash) + c.Assert(r.IsNote(), Equals, true) +} + +func (s *ReferenceSuite) TestIsRemote(c *C) { + r := NewHashReference(ReferenceName("refs/remotes/origin/master"), ZeroHash) + c.Assert(r.IsRemote(), Equals, true) +} + +func (s *ReferenceSuite) TestIsTag(c *C) { + r := NewHashReference(ReferenceName("refs/tags/v3.1."), ZeroHash) + c.Assert(r.IsTag(), Equals, true) +} |