diff --git a/git.go b/git.go index 8159244..2afbfaa 100644 --- a/git.go +++ b/git.go @@ -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 { diff --git a/git_test.go b/git_test.go index 6542ca0..f4515a6 100644 --- a/git_test.go +++ b/git_test.go @@ -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") + } +} diff --git a/index.go b/index.go index d3178a2..f20dc31 100644 --- a/index.go +++ b/index.go @@ -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) } diff --git a/push_test.go b/push_test.go index c1e6a22..65f4dd2 100644 --- a/push_test.go +++ b/push_test.go @@ -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) diff --git a/reference.go b/reference.go index e165f2a..98facc2 100644 --- a/reference.go +++ b/reference.go @@ -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) } diff --git a/reference_test.go b/reference_test.go index bc970bf..3e72ae7 100644 --- a/reference_test.go +++ b/reference_test.go @@ -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") } diff --git a/walk.go b/walk.go index f7c147d..9e07411 100644 --- a/walk.go +++ b/walk.go @@ -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 {