Add ability to peel any git object
Includes support for 'git_object_peel'.
This commit is contained in:
parent
c0c6caed3a
commit
17950c198b
26
object.go
26
object.go
|
@ -22,6 +22,7 @@ type Object interface {
|
||||||
Id() *Oid
|
Id() *Oid
|
||||||
Type() ObjectType
|
Type() ObjectType
|
||||||
Owner() *Repository
|
Owner() *Repository
|
||||||
|
Peel(t ObjectType) (Object, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type gitObject struct {
|
type gitObject struct {
|
||||||
|
@ -69,6 +70,31 @@ func (o *gitObject) Free() {
|
||||||
C.git_object_free(o.ptr)
|
C.git_object_free(o.ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peel recursively peels an object until an object of the specified type is met.
|
||||||
|
//
|
||||||
|
// If the query cannot be satisfied due to the object model, ErrInvalidSpec
|
||||||
|
// will be returned (e.g. trying to peel a blob to a tree).
|
||||||
|
//
|
||||||
|
// If you pass ObjectAny as the target type, then the object will be peeled
|
||||||
|
// until the type changes. A tag will be peeled until the referenced object
|
||||||
|
// is no longer a tag, and a commit will be peeled to a tree. Any other object
|
||||||
|
// type will return ErrInvalidSpec.
|
||||||
|
//
|
||||||
|
// If peeling a tag we discover an object which cannot be peeled to the target
|
||||||
|
// type due to the object model, an error will be returned.
|
||||||
|
func (o *gitObject) Peel(t ObjectType) (Object, error) {
|
||||||
|
var cobj *C.git_object
|
||||||
|
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
if err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t)); err < 0 {
|
||||||
|
return nil, MakeGitError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocObject(cobj, o.repo), nil
|
||||||
|
}
|
||||||
|
|
||||||
func allocObject(cobj *C.git_object, repo *Repository) Object {
|
func allocObject(cobj *C.git_object, repo *Repository) Object {
|
||||||
obj := gitObject{
|
obj := gitObject{
|
||||||
ptr: cobj,
|
ptr: cobj,
|
||||||
|
|
|
@ -102,3 +102,63 @@ func TestObjectOwner(t *testing.T) {
|
||||||
checkOwner(t, repo, commit)
|
checkOwner(t, repo, commit)
|
||||||
checkOwner(t, repo, tree)
|
checkOwner(t, repo, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestObjectPeel(t *testing.T) {
|
||||||
|
repo := createTestRepo(t)
|
||||||
|
defer cleanupTestRepo(t, repo)
|
||||||
|
|
||||||
|
commitID, treeID := seedTestRepo(t, repo)
|
||||||
|
|
||||||
|
var obj Object
|
||||||
|
|
||||||
|
commit, err := repo.LookupCommit(commitID)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
obj, err = commit.Peel(ObjectAny)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
if obj.Type() != ObjectTree {
|
||||||
|
t.Fatalf("Wrong object type when peeling a commit, expected tree, have %v", obj.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
obj, err = commit.Peel(ObjectTag)
|
||||||
|
|
||||||
|
if !IsErrorCode(err, ErrInvalidSpec) {
|
||||||
|
t.Fatalf("Wrong error when peeling a commit to a tag, expected ErrInvalidSpec, have %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree, err := repo.LookupTree(treeID)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
obj, err = tree.Peel(ObjectAny)
|
||||||
|
|
||||||
|
if !IsErrorCode(err, ErrInvalidSpec) {
|
||||||
|
t.Fatalf("Wrong error when peeling a tree, expected ErrInvalidSpec, have %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
entry := tree.EntryByName("README")
|
||||||
|
|
||||||
|
blob, err := repo.LookupBlob(entry.Id)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
obj, err = blob.Peel(ObjectAny)
|
||||||
|
|
||||||
|
if !IsErrorCode(err, ErrInvalidSpec) {
|
||||||
|
t.Fatalf("Wrong error when peeling a blob, expected ErrInvalidSpec, have %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tagID := createTestTag(t, repo, commit)
|
||||||
|
|
||||||
|
tag, err := repo.LookupTag(tagID)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
obj, err = tag.Peel(ObjectAny)
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
if obj.Type() != ObjectCommit {
|
||||||
|
t.Fatalf("Wrong object type when peeling a tag, expected commit, have %v", obj.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should test a tag that annotates a different object than a commit
|
||||||
|
// but it's impossible at the moment to tag such an object.
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue