Add branch iterator #66

Merged
jezell merged 9 commits from branch-iterator into master 2014-04-26 13:25:26 -05:00
7 changed files with 115 additions and 34 deletions
Showing only changes of commit fc999289a2 - Show all commits

121
git.go
View File

@ -15,14 +15,78 @@ import (
"unsafe"
)
type ErrorClass int
const (
ITEROVER = C.GIT_ITEROVER
EEXISTS = C.GIT_EEXISTS
ENOTFOUND = C.GIT_ENOTFOUND
ErrClassNone ErrorClass = C.GITERR_NONE
ErrClassNoMemory = C.GITERR_NOMEMORY
ErrClassOs = C.GITERR_OS
ErrClassInvalid = C.GITERR_INVALID
ErrClassReference = C.GITERR_REFERENCE
ErrClassZlib = C.GITERR_ZLIB
ErrClassRepository = C.GITERR_REPOSITORY
ErrClassConfig = C.GITERR_CONFIG
ErrClassRegex = C.GITERR_REGEX
ErrClassOdb = C.GITERR_ODB
ErrClassIndex = C.GITERR_INDEX
ErrClassObject = C.GITERR_OBJECT
ErrClassNet = C.GITERR_NET
ErrClassTag = C.GITERR_TAG
ErrClassTree = C.GITERR_TREE
ErrClassIndexer = C.GITERR_INDEXER
ErrClassSSL = C.GITERR_SSL
ErrClassSubmodule = C.GITERR_SUBMODULE
ErrClassThread = C.GITERR_THREAD
ErrClassStash = C.GITERR_STASH
ErrClassCheckout = C.GITERR_CHECKOUT
ErrClassFetchHead = C.GITERR_FETCHHEAD
ErrClassMerge = C.GITERR_MERGE
ErrClassSsh = C.GITERR_SSH
ErrClassFilter = C.GITERR_FILTER
ErrClassRevert = C.GITERR_REVERT
ErrClassCallback = C.GITERR_CALLBACK
)
var (
ErrIterOver = errors.New("Iteration is over")
type ErrorCode int
const (
// No error
ErrOk ErrorCode = C.GIT_OK
// Generic error
ErrGeneric = C.GIT_ERROR
// Requested object could not be found
ErrNotFound = C.GIT_ENOTFOUND
// Object exists preventing operation
ErrExists = C.GIT_EEXISTS
// More than one object matches
ErrAmbigious = C.GIT_EAMBIGUOUS
// Output buffer too short to hold data
ErrBuffs = C.GIT_EBUFS
// GIT_EUSER is a special error that is never generated by libgit2
// code. You can return it from a callback (e.g to stop an iteration)
// to know that it was generated by the callback and not by libgit2.
ErrUser = C.GIT_EUSER
// Operation not allowed on bare repository
ErrBareRepo = C.GIT_EBAREREPO
// HEAD refers to branch with no commits
ErrUnbornBranch = C.GIT_EUNBORNBRANCH
// Merge in progress prevented operation
ErrUnmerged = C.GIT_EUNMERGED
// Reference was not fast-forwardable
ErrNonFastForward = C.GIT_ENONFASTFORWARD
// Name/ref spec was not in a valid format
ErrInvalidSpec = C.GIT_EINVALIDSPEC
// Merge conflicts prevented operation
ErrMergeConflict = C.GIT_EMERGECONFLICT
// Lock file prevented operation
ErrLocked = C.GIT_ELOCKED
// Reference value does not match expected
ErrModified = C.GIT_EMODIFIED
// Internal only
ErrPassthrough = C.GIT_PASSTHROUGH
// Signals end of iteration with iterator
ErrIterOver = C.GIT_ITEROVER
)
func init() {
@ -64,6 +128,10 @@ func NewOid(s string) (*Oid, error) {
return nil, error
}
if len(slice) != 20 {
return nil, &GitError{"Invalid Oid", ErrClassNone, ErrGeneric}
}
copy(o[:], slice[:20])
return o, nil
}
@ -124,29 +192,50 @@ func ShortenOids(ids []*Oid, minlen int) (int, error) {
}
type GitError struct {
Message string
Class int
ErrorCode int
Message string
Class ErrorClass
Code ErrorCode
}
func (e GitError) Error() string {
return e.Message
}
func IsNotExist(err error) bool {
return err.(*GitError).ErrorCode == C.GIT_ENOTFOUND
func IsErrorClass(err error, c ErrorClass) bool {
if err == nil {
return false
}
if gitError, ok := err.(*GitError); ok {
return gitError.Class == c
}
return false
}
func IsExist(err error) bool {
return err.(*GitError).ErrorCode == C.GIT_EEXISTS
func IsErrorCode(err error, c ErrorCode) bool {
if err == nil {
return false
}
if gitError, ok := err.(*GitError); ok {
return gitError.Code == c
}
return false
}
func MakeGitError(errorCode C.int) error {
err := C.giterr_last()
if err == nil {
return &GitError{"No message", C.GITERR_INVALID, C.GIT_ERROR}
var errMessage string
var errClass ErrorClass
if errorCode != ErrIterOver {
err := C.giterr_last()
if err != nil {
errMessage = C.GoString(err.message)
errClass = ErrorClass(err.klass)
} else {
errClass = ErrClassInvalid
}
}
return &GitError{C.GoString(err.message), int(err.klass), int(errorCode)}
return &GitError{errMessage, errClass, ErrorCode(errorCode)}
}
func MakeGitError2(err int) error {

View File

@ -62,3 +62,10 @@ func TestOidZero(t *testing.T) {
t.Error("Zero Oid is not zero")
}
}
func TestEmptyOid(t *testing.T) {
_, err := NewOid("")
if err == nil || !IsErrorCode(err, ErrGeneric) {
t.Fatal("Should have returned invalid error")
}
}

View File

@ -266,10 +266,6 @@ func (v *IndexConflictIterator) Next() (IndexConflict, error) {
defer runtime.UnlockOSThread()
ecode := C.git_index_conflict_next(&cancestor, &cour, &ctheir, v.ptr)
if ecode == C.GIT_ITEROVER {
return IndexConflict{}, ErrIterOver
}
if ecode < 0 {
return IndexConflict{}, MakeGitError(ecode)
}

View File

@ -1,7 +1,6 @@
package git
import (
"log"
"os"
"testing"
"time"
@ -45,7 +44,6 @@ func Test_Push_ToRemote(t *testing.T) {
checkFatal(t, err)
err = push.StatusForeach(func(ref string, msg string) int {
log.Printf("%s -> %s", ref, msg)
return 0
})
checkFatal(t, err)

View File

@ -261,9 +261,6 @@ func (v *ReferenceNameIterator) Next() (string, error) {
defer runtime.UnlockOSThread()
ret := C.git_reference_next_name(&ptr, v.ptr)
if ret == ITEROVER {
return "", ErrIterOver
}
if ret < 0 {
return "", MakeGitError(ret)
}
@ -276,9 +273,6 @@ func (v *ReferenceNameIterator) Next() (string, error) {
func (v *ReferenceIterator) Next() (*Reference, error) {
var ptr *C.git_reference
ret := C.git_reference_next(&ptr, v.ptr)
if ret == ITEROVER {
return nil, ErrIterOver
}
if ret < 0 {
return nil, MakeGitError(ret)
}

View File

@ -112,7 +112,7 @@ func TestReferenceIterator(t *testing.T) {
list = append(list, name)
name, err = nameIter.Next()
}
if err != ErrIterOver {
if !IsErrorCode(err, ErrIterOver) {
t.Fatal("Iteration not over")
}
@ -128,7 +128,7 @@ func TestReferenceIterator(t *testing.T) {
count++
_, err = iter.Next()
}
if err != ErrIterOver {
if !IsErrorCode(err, ErrIterOver) {
t.Fatal("Iteration not over")
}

View File

@ -7,7 +7,6 @@ package git
import "C"
import (
"io"
"runtime"
"unsafe"
)
@ -158,8 +157,6 @@ func (v *RevWalk) Next(id *Oid) (err error) {
ret := C.git_revwalk_next(id.toC(), v.ptr)
switch {
case ret == ITEROVER:
err = io.EOF
case ret < 0:
err = MakeGitError(ret)
}
@ -173,7 +170,7 @@ func (v *RevWalk) Iterate(fun RevWalkIterator) (err error) {
oid := new(Oid)
for {
err = v.Next(oid)
if err == io.EOF {
if IsErrorCode(err, ErrIterOver) {
return nil
}
if err != nil {