diff options
| author | Carlos Martín Nieto <[email protected]> | 2015-09-18 10:52:37 +0200 |
|---|---|---|
| committer | Carlos Martín Nieto <[email protected]> | 2015-09-18 10:52:37 +0200 |
| commit | 0522886781055d59b780e00fddf3c8f7c9e118dc (patch) | |
| tree | 797b7644292addcd518dbfea092aa9f3fd1e1e6c /clone.go | |
| parent | b3e7705c48f038ef335204a2a9e1ee829784c30e (diff) | |
| parent | ebf7f15bf9c585102b1c39f6bec5f61a37d18802 (diff) | |
Merge remote-tracking branch 'origin/master' into next
Diffstat (limited to 'clone.go')
| -rw-r--r-- | clone.go | 60 |
1 files changed, 50 insertions, 10 deletions
@@ -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)) } |
