diff --git a/object.go b/object.go index 10f5f7c..f351640 100644 --- a/object.go +++ b/object.go @@ -100,6 +100,13 @@ func allocObject(cobj *C.git_object, repo *Repository) Object { } runtime.SetFinalizer(blob, (*Blob).Free) return blob + case ObjectTag: + tag := &Tag{ + gitObject: obj, + cast_ptr: (*C.git_tag)(cobj), + } + runtime.SetFinalizer(tag, (*Tag).Free) + return tag } return nil diff --git a/repository.go b/repository.go index 2354f99..c380de1 100644 --- a/repository.go +++ b/repository.go @@ -164,6 +164,15 @@ func (v *Repository) LookupBlob(id *Oid) (*Blob, error) { return obj.(*Blob), nil } +func (v *Repository) LookupTag(id *Oid) (*Tag, error) { + obj, err := v.lookupType(id, ObjectTag) + if err != nil { + return nil, err + } + + return obj.(*Tag), nil +} + func (v *Repository) LookupReference(name string) (*Reference, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) @@ -356,6 +365,30 @@ func (v *Repository) CreateCommit( return oid, nil } +func (v *Repository) CreateTag( + name string, commit *Commit, tagger *Signature, message string) (*Oid, error) { + + oid := new(Oid) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + cmessage := C.CString(message) + defer C.free(unsafe.Pointer(cmessage)) + + taggerSig := tagger.toC() + defer C.git_signature_free(taggerSig) + + ctarget := commit.gitObject.ptr + + ret := C.git_tag_create(oid.toC(), v.ptr, cname, ctarget, taggerSig, cmessage, 0) + if ret < 0 { + return nil, MakeGitError(ret) + } + + return oid, nil +} + func (v *Odb) Free() { runtime.SetFinalizer(v, nil) C.git_odb_free(v.ptr) diff --git a/tag.go b/tag.go new file mode 100644 index 0000000..89ac8bd --- /dev/null +++ b/tag.go @@ -0,0 +1,44 @@ +package git + +/* +#include +*/ +import "C" + +// Tag +type Tag struct { + gitObject + cast_ptr *C.git_tag +} + +func (t Tag) Message() string { + return C.GoString(C.git_tag_message(t.cast_ptr)) +} + +func (t Tag) Name() string { + return C.GoString(C.git_tag_name(t.cast_ptr)) +} + +func (t Tag) Tagger() *Signature { + cast_ptr := C.git_tag_tagger(t.cast_ptr) + return newSignatureFromC(cast_ptr) +} + +func (t Tag) Target() Object { + var ptr *C.git_object + ret := C.git_tag_target(&ptr, t.cast_ptr) + + if ret != 0 { + return nil + } + + return allocObject(ptr, t.repo) +} + +func (t Tag) TargetId() *Oid { + return newOidFromC(C.git_tag_target_id(t.cast_ptr)) +} + +func (t Tag) TargetType() ObjectType { + return ObjectType(C.git_tag_target_type(t.cast_ptr)) +} diff --git a/tag_test.go b/tag_test.go new file mode 100644 index 0000000..5ebd53d --- /dev/null +++ b/tag_test.go @@ -0,0 +1,45 @@ +package git + +import ( + "os" + "time" + "testing" +) + +func TestCreateTag(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + commitId, _ := seedTestRepo(t, repo) + + commit, err := repo.LookupCommit(commitId) + checkFatal(t, err) + + tagId := createTestTag(t, repo, commit) + + tag, err := repo.LookupTag(tagId) + checkFatal(t, err) + + compareStrings(t, "v0.0.0", tag.Name()) + compareStrings(t, "This is a tag", tag.Message()) + compareStrings(t, commitId.String(), tag.TargetId().String()) +} + +func compareStrings(t *testing.T, expected, value string) { + if value != expected { + t.Fatalf("expected '%v', actual '%v'", expected, value) + } +} + +func createTestTag(t *testing.T, repo *Repository, commit *Commit) *Oid { + loc, err := time.LoadLocation("Europe/Berlin") + checkFatal(t, err) + sig := &Signature{ + Name: "Rand Om Hacker", + Email: "random@hacker.com", + When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc), + } + + tagId, err := repo.CreateTag("v0.0.0", commit, sig, "This is a tag") + checkFatal(t, err) + return tagId +}