summaryrefslogtreecommitdiff
path: root/reference.go
diff options
context:
space:
mode:
Diffstat (limited to 'reference.go')
-rw-r--r--reference.go188
1 files changed, 176 insertions, 12 deletions
diff --git a/reference.go b/reference.go
index 820d166..a2f1636 100644
--- a/reference.go
+++ b/reference.go
@@ -1,7 +1,6 @@
package git
/*
-#cgo pkg-config: libgit2
#include <git2.h>
#include <git2/errors.h>
*/
@@ -11,9 +10,11 @@ import (
"unsafe"
)
-var (
- SYMBOLIC = C.GIT_REF_SYMBOLIC
- OID = C.GIT_REF_OID
+type ReferenceType int
+
+const (
+ ReferenceSymbolic ReferenceType = C.GIT_REF_SYMBOLIC
+ ReferenceOid = C.GIT_REF_OID
)
type Reference struct {
@@ -27,12 +28,22 @@ func newReferenceFromC(ptr *C.git_reference) *Reference {
return ref
}
-func (v *Reference) SetSymbolicTarget(target string) (*Reference, error) {
+func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) (*Reference, error) {
var ptr *C.git_reference
+
ctarget := C.CString(target)
defer C.free(unsafe.Pointer(ctarget))
- ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget)
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ csig := sig.toC()
+ defer C.free(unsafe.Pointer(csig))
+
+ cmsg := C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+
+ ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, csig, cmsg)
if ret < 0 {
return nil, LastError()
}
@@ -40,10 +51,19 @@ func (v *Reference) SetSymbolicTarget(target string) (*Reference, error) {
return newReferenceFromC(ptr), nil
}
-func (v *Reference) SetTarget(target *Oid) (*Reference, error) {
+func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Reference, error) {
var ptr *C.git_reference
- ret := C.git_reference_set_target(&ptr, v.ptr, target.toC())
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ csig := sig.toC()
+ defer C.free(unsafe.Pointer(csig))
+
+ cmsg := C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+
+ ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), csig, cmsg)
if ret < 0 {
return nil, LastError()
}
@@ -54,6 +74,9 @@ func (v *Reference) SetTarget(target *Oid) (*Reference, error) {
func (v *Reference) Resolve() (*Reference, error) {
var ptr *C.git_reference
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
ret := C.git_reference_resolve(&ptr, v.ptr)
if ret < 0 {
return nil, LastError()
@@ -62,12 +85,21 @@ func (v *Reference) Resolve() (*Reference, error) {
return newReferenceFromC(ptr), nil
}
-func (v *Reference) Rename(name string, force bool) (*Reference, error) {
+func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) (*Reference, error) {
var ptr *C.git_reference
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
- ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force))
+ csig := sig.toC()
+ defer C.free(unsafe.Pointer(csig))
+
+ cmsg := C.CString(msg)
+ defer C.free(unsafe.Pointer(cmsg))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), csig, cmsg)
if ret < 0 {
return nil, LastError()
@@ -90,6 +122,9 @@ func (v *Reference) SymbolicTarget() string {
}
func (v *Reference) Delete() error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
ret := C.git_reference_delete(v.ptr)
if ret < 0 {
@@ -103,11 +138,140 @@ func (v *Reference) Name() string {
return C.GoString(C.git_reference_name(v.ptr))
}
-func (v *Reference) Type() int {
- return int(C.git_reference_type(v.ptr))
+func (v *Reference) Type() ReferenceType {
+ return ReferenceType(C.git_reference_type(v.ptr))
+}
+
+func (v *Reference) IsBranch() bool {
+ return C.git_reference_is_branch(v.ptr) == 1
+}
+
+func (v *Reference) IsRemote() bool {
+ return C.git_reference_is_remote(v.ptr) == 1
+}
+
+func (v *Reference) IsTag() bool {
+ return C.git_reference_is_tag(v.ptr) == 1
}
func (v *Reference) Free() {
runtime.SetFinalizer(v, nil)
C.git_reference_free(v.ptr)
}
+
+type ReferenceIterator struct {
+ ptr *C.git_reference_iterator
+ repo *Repository
+}
+
+// NewReferenceIterator creates a new iterator over reference names
+func (repo *Repository) NewReferenceIterator() (*ReferenceIterator, error) {
+ var ptr *C.git_reference_iterator
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_iterator_new(&ptr, repo.ptr)
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ iter := &ReferenceIterator{repo: repo, ptr: ptr}
+ runtime.SetFinalizer(iter, (*ReferenceIterator).Free)
+ return iter, nil
+}
+
+// NewReferenceIteratorGlob creates an iterator over reference names
+// that match the speicified glob. The glob is of the usual fnmatch
+// type.
+func (repo *Repository) NewReferenceIteratorGlob(glob string) (*ReferenceIterator, error) {
+ cstr := C.CString(glob)
+ defer C.free(unsafe.Pointer(cstr))
+ var ptr *C.git_reference_iterator
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_iterator_glob_new(&ptr, repo.ptr, cstr)
+ if ret < 0 {
+ return nil, LastError()
+ }
+
+ iter := &ReferenceIterator{repo: repo, ptr: ptr}
+ runtime.SetFinalizer(iter, (*ReferenceIterator).Free)
+ return iter, nil
+}
+
+// NextName retrieves the next reference name. If the iteration is over,
+// the returned error is git.ErrIterOver
+func (v *ReferenceIterator) NextName() (string, error) {
+ var ptr *C.char
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_reference_next_name(&ptr, v.ptr)
+ if ret == ITEROVER {
+ return "", ErrIterOver
+ }
+ if ret < 0 {
+ return "", LastError()
+ }
+
+ return C.GoString(ptr), nil
+}
+
+// Create a channel from the iterator. You can use range on the
+// returned channel to iterate over all the references names. The channel
+// will be closed in case any error is found.
+func (v *ReferenceIterator) NameIter() <-chan string {
+ ch := make(chan string)
+ go func() {
+ defer close(ch)
+ name, err := v.NextName()
+ for err == nil {
+ ch <- name
+ name, err = v.NextName()
+ }
+ }()
+
+ return ch
+}
+
+// Next retrieves the next reference. If the iterationis over, the
+// returned error is git.ErrIterOver
+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, LastError()
+ }
+
+ return newReferenceFromC(ptr), nil
+}
+
+// Create a channel from the iterator. You can use range on the
+// returned channel to iterate over all the references names. The channel
+// will be closed in case any error is found.
+func (v *ReferenceIterator) Iter() <-chan *Reference {
+ ch := make(chan *Reference)
+ go func() {
+ defer close(ch)
+ name, err := v.Next()
+ for err == nil {
+ ch <- name
+ name, err = v.Next()
+ }
+ }()
+
+ return ch
+}
+
+// Free the reference iterator
+func (v *ReferenceIterator) Free() {
+ runtime.SetFinalizer(v, nil)
+ C.git_reference_iterator_free(v.ptr)
+}