summaryrefslogtreecommitdiff
path: root/clone.go
diff options
context:
space:
mode:
authorCarlos Martín Nieto <[email protected]>2015-09-18 10:52:37 +0200
committerCarlos Martín Nieto <[email protected]>2015-09-18 10:52:37 +0200
commit0522886781055d59b780e00fddf3c8f7c9e118dc (patch)
tree797b7644292addcd518dbfea092aa9f3fd1e1e6c /clone.go
parentb3e7705c48f038ef335204a2a9e1ee829784c30e (diff)
parentebf7f15bf9c585102b1c39f6bec5f61a37d18802 (diff)
Merge remote-tracking branch 'origin/master' into next
Diffstat (limited to 'clone.go')
-rw-r--r--clone.go60
1 files changed, 50 insertions, 10 deletions
diff --git a/clone.go b/clone.go
index b5c5a5b..e80d14d 100644
--- a/clone.go
+++ b/clone.go
@@ -3,6 +3,7 @@ package git
/*
#include <git2.h>
+extern void _go_git_populate_remote_cb(git_clone_options *opts);
*/
import "C"
import (
@@ -10,13 +11,14 @@ import (
"unsafe"
)
+type RemoteCreateCallback func(repo *Repository, name, url string) (*Remote, ErrorCode)
+
type CloneOptions struct {
*CheckoutOpts
*FetchOptions
Bare bool
CheckoutBranch string
- RemoteCreateCallback C.git_remote_create_cb
- RemoteCreatePayload unsafe.Pointer
+ RemoteCreateCallback RemoteCreateCallback
}
func Clone(url string, path string, options *CloneOptions) (*Repository, error) {
@@ -28,6 +30,7 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
copts := (*C.git_clone_options)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_clone_options{}))))
populateCloneOptions(copts, options)
+ defer freeCloneOptions(copts)
if len(options.CheckoutBranch) != 0 {
copts.checkout_branch = C.CString(options.CheckoutBranch)
@@ -35,11 +38,10 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+
var ptr *C.git_repository
ret := C.git_clone(&ptr, curl, cpath, copts)
freeCheckoutOpts(&copts.checkout_opts)
- C.free(unsafe.Pointer(copts.checkout_branch))
- C.free(unsafe.Pointer(copts))
if ret < 0 {
return nil, MakeGitError(ret)
@@ -48,6 +50,33 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error)
return newRepositoryFromC(ptr), nil
}
+//export remoteCreateCallback
+func remoteCreateCallback(cremote unsafe.Pointer, crepo unsafe.Pointer, cname, curl *C.char, payload unsafe.Pointer) C.int {
+ name := C.GoString(cname)
+ url := C.GoString(curl)
+ repo := newRepositoryFromC((*C.git_repository)(crepo))
+ // We don't own this repository, so make sure we don't try to free it
+ runtime.SetFinalizer(repo, nil)
+
+ if opts, ok := pointerHandles.Get(payload).(CloneOptions); ok {
+ remote, err := opts.RemoteCreateCallback(repo, name, url)
+ // clear finalizer as the calling C function will
+ // free the remote itself
+ runtime.SetFinalizer(remote, nil)
+
+ if err == ErrOk && remote != nil {
+ cptr := (**C.git_remote)(cremote)
+ *cptr = remote.ptr
+ } else if err == ErrOk && remote == nil {
+ panic("no remote created by callback")
+ }
+
+ return C.int(err)
+ } else {
+ panic("invalid remote create callback")
+ }
+}
+
func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) {
C.git_clone_init_options(ptr, C.GIT_CLONE_OPTIONS_VERSION)
@@ -59,12 +88,23 @@ func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) {
ptr.bare = cbool(opts.Bare)
if opts.RemoteCreateCallback != nil {
- ptr.remote_cb = opts.RemoteCreateCallback
- defer C.free(unsafe.Pointer(opts.RemoteCreateCallback))
+ // Go v1.1 does not allow to assign a C function pointer
+ C._go_git_populate_remote_cb(ptr)
+ ptr.remote_cb_payload = pointerHandles.Track(*opts)
+ }
+}
- if opts.RemoteCreatePayload != nil {
- ptr.remote_cb_payload = opts.RemoteCreatePayload
- defer C.free(opts.RemoteCreatePayload)
- }
+func freeCloneOptions(ptr *C.git_clone_options) {
+ if ptr == nil {
+ return
}
+
+ freeCheckoutOpts(&ptr.checkout_opts)
+
+ if ptr.remote_cb_payload != nil {
+ pointerHandles.Untrack(ptr.remote_cb_payload)
+ }
+
+ C.free(unsafe.Pointer(ptr.checkout_branch))
+ C.free(unsafe.Pointer(ptr))
}