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.
		
		
		
		
		
			
		
			
				
					
					
						
							209 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							209 lines
						
					
					
						
							4.9 KiB
						
					
					
				| package plumbing
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	refPrefix       = "refs/"
 | |
| 	refHeadPrefix   = refPrefix + "heads/"
 | |
| 	refTagPrefix    = refPrefix + "tags/"
 | |
| 	refRemotePrefix = refPrefix + "remotes/"
 | |
| 	refNotePrefix   = refPrefix + "notes/"
 | |
| 	symrefPrefix    = "ref: "
 | |
| )
 | |
| 
 | |
| // RefRevParseRules are a set of rules to parse references into short names.
 | |
| // These are the same rules as used by git in shorten_unambiguous_ref.
 | |
| // See: https://github.com/git/git/blob/e0aaa1b6532cfce93d87af9bc813fb2e7a7ce9d7/refs.c#L417
 | |
| var RefRevParseRules = []string{
 | |
| 	"refs/%s",
 | |
| 	"refs/tags/%s",
 | |
| 	"refs/heads/%s",
 | |
| 	"refs/remotes/%s",
 | |
| 	"refs/remotes/%s/HEAD",
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	ErrReferenceNotFound = errors.New("reference not found")
 | |
| )
 | |
| 
 | |
| // ReferenceType reference type's
 | |
| type ReferenceType int8
 | |
| 
 | |
| const (
 | |
| 	InvalidReference  ReferenceType = 0
 | |
| 	HashReference     ReferenceType = 1
 | |
| 	SymbolicReference ReferenceType = 2
 | |
| )
 | |
| 
 | |
| func (r ReferenceType) String() string {
 | |
| 	switch r {
 | |
| 	case InvalidReference:
 | |
| 		return "invalid-reference"
 | |
| 	case HashReference:
 | |
| 		return "hash-reference"
 | |
| 	case SymbolicReference:
 | |
| 		return "symbolic-reference"
 | |
| 	}
 | |
| 
 | |
| 	return ""
 | |
| }
 | |
| 
 | |
| // ReferenceName reference name's
 | |
| type ReferenceName string
 | |
| 
 | |
| // NewBranchReferenceName returns a reference name describing a branch based on
 | |
| // his short name.
 | |
| func NewBranchReferenceName(name string) ReferenceName {
 | |
| 	return ReferenceName(refHeadPrefix + name)
 | |
| }
 | |
| 
 | |
| // NewNoteReferenceName returns a reference name describing a note based on his
 | |
| // short name.
 | |
| func NewNoteReferenceName(name string) ReferenceName {
 | |
| 	return ReferenceName(refNotePrefix + name)
 | |
| }
 | |
| 
 | |
| // NewRemoteReferenceName returns a reference name describing a remote branch
 | |
| // based on his short name and the remote name.
 | |
| func NewRemoteReferenceName(remote, name string) ReferenceName {
 | |
| 	return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, name))
 | |
| }
 | |
| 
 | |
| // NewRemoteHEADReferenceName returns a reference name describing a the HEAD
 | |
| // branch of a remote.
 | |
| func NewRemoteHEADReferenceName(remote string) ReferenceName {
 | |
| 	return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, HEAD))
 | |
| }
 | |
| 
 | |
| // NewTagReferenceName returns a reference name describing a tag based on short
 | |
| // his name.
 | |
| func NewTagReferenceName(name string) ReferenceName {
 | |
| 	return ReferenceName(refTagPrefix + name)
 | |
| }
 | |
| 
 | |
| // IsBranch check if a reference is a branch
 | |
| func (r ReferenceName) IsBranch() bool {
 | |
| 	return strings.HasPrefix(string(r), refHeadPrefix)
 | |
| }
 | |
| 
 | |
| // IsNote check if a reference is a note
 | |
| func (r ReferenceName) IsNote() bool {
 | |
| 	return strings.HasPrefix(string(r), refNotePrefix)
 | |
| }
 | |
| 
 | |
| // IsRemote check if a reference is a remote
 | |
| func (r ReferenceName) IsRemote() bool {
 | |
| 	return strings.HasPrefix(string(r), refRemotePrefix)
 | |
| }
 | |
| 
 | |
| // IsTag check if a reference is a tag
 | |
| func (r ReferenceName) IsTag() bool {
 | |
| 	return strings.HasPrefix(string(r), refTagPrefix)
 | |
| }
 | |
| 
 | |
| func (r ReferenceName) String() string {
 | |
| 	return string(r)
 | |
| }
 | |
| 
 | |
| // Short returns the short name of a ReferenceName
 | |
| func (r ReferenceName) Short() string {
 | |
| 	s := string(r)
 | |
| 	res := s
 | |
| 	for _, format := range RefRevParseRules {
 | |
| 		_, err := fmt.Sscanf(s, format, &res)
 | |
| 		if err == nil {
 | |
| 			continue
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return res
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	HEAD   ReferenceName = "HEAD"
 | |
| 	Master ReferenceName = "refs/heads/master"
 | |
| )
 | |
| 
 | |
| // 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 {
 | |
| 	n := ReferenceName(name)
 | |
| 
 | |
| 	if strings.HasPrefix(target, symrefPrefix) {
 | |
| 		target := ReferenceName(target[len(symrefPrefix):])
 | |
| 		return NewSymbolicReference(n, target)
 | |
| 	}
 | |
| 
 | |
| 	return NewHashReference(n, NewHash(target))
 | |
| }
 | |
| 
 | |
| // 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
 | |
| }
 | |
| 
 | |
| // Strings dump a reference as a [2]string
 | |
| func (r *Reference) Strings() [2]string {
 | |
| 	var o [2]string
 | |
| 	o[0] = r.Name().String()
 | |
| 
 | |
| 	switch r.Type() {
 | |
| 	case HashReference:
 | |
| 		o[1] = r.Hash().String()
 | |
| 	case SymbolicReference:
 | |
| 		o[1] = symrefPrefix + r.Target().String()
 | |
| 	}
 | |
| 
 | |
| 	return o
 | |
| }
 | |
| 
 | |
| func (r *Reference) String() string {
 | |
| 	s := r.Strings()
 | |
| 	return fmt.Sprintf("%s %s", s[1], s[0])
 | |
| }
 | |
| 
 |