| package git |
| |
| /* |
| #include <git2.h> |
| #include <git2/errors.h> |
| |
| extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); |
| |
| */ |
| import "C" |
| import "unsafe" |
| import "runtime" |
| |
| type TransferProgress struct { |
| TotalObjects uint |
| IndexedObjects uint |
| ReceivedObjects uint |
| LocalObjects uint |
| TotalDeltas uint |
| ReceivedBytes uint |
| } |
| |
| func newTransferProgressFromC(c *C.git_transfer_progress) TransferProgress { |
| return TransferProgress{ |
| TotalObjects: uint(c.total_objects), |
| IndexedObjects: uint(c.indexed_objects), |
| ReceivedObjects: uint(c.received_objects), |
| LocalObjects: uint(c.local_objects), |
| TotalDeltas: uint(c.total_deltas), |
| ReceivedBytes: uint(c.received_bytes)} |
| } |
| |
| type RemoteCompletion uint |
| |
| const ( |
| RemoteCompletionDownload RemoteCompletion = C.GIT_REMOTE_COMPLETION_DOWNLOAD |
| RemoteCompletionIndexing = C.GIT_REMOTE_COMPLETION_INDEXING |
| RemoteCompletionError = C.GIT_REMOTE_COMPLETION_ERROR |
| ) |
| |
| type ProgressCallback func(str string) int |
| type CompletionCallback func(RemoteCompletion) int |
| type CredentialsCallback func(url string, username_from_url string, allowed_types CredType) (int, *Cred) |
| type TransferProgressCallback func(stats TransferProgress) int |
| type UpdateTipsCallback func(refname string, a *Oid, b *Oid) int |
| |
| type RemoteCallbacks struct { |
| ProgressCallback |
| CompletionCallback |
| CredentialsCallback |
| TransferProgressCallback |
| UpdateTipsCallback |
| } |
| |
| type Remote struct { |
| ptr *C.git_remote |
| } |
| |
| func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { |
| C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION) |
| if callbacks == nil { |
| return |
| } |
| C._go_git_setup_callbacks(ptr) |
| ptr.payload = unsafe.Pointer(callbacks) |
| } |
| |
| //export progressCallback |
| func progressCallback(_str *C.char, _len C.int, data unsafe.Pointer) int { |
| callbacks := (*RemoteCallbacks)(data) |
| if callbacks.ProgressCallback == nil { |
| return 0 |
| } |
| str := C.GoStringN(_str, _len) |
| return callbacks.ProgressCallback(str) |
| } |
| |
| //export completionCallback |
| func completionCallback(completion_type C.git_remote_completion_type, data unsafe.Pointer) int { |
| callbacks := (*RemoteCallbacks)(data) |
| if callbacks.CompletionCallback == nil { |
| return 0 |
| } |
| return callbacks.CompletionCallback((RemoteCompletion)(completion_type)) |
| } |
| |
| //export credentialsCallback |
| func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C.char, allowed_types uint, data unsafe.Pointer) int { |
| callbacks := (*RemoteCallbacks)(data) |
| if callbacks.CredentialsCallback == nil { |
| return 0 |
| } |
| url := C.GoString(_url) |
| username_from_url := C.GoString(_username_from_url) |
| ret, cred := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types)) |
| *_cred = cred.ptr |
| return ret |
| } |
| |
| //export transferProgressCallback |
| func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointer) int { |
| callbacks := (*RemoteCallbacks)(data) |
| if callbacks.TransferProgressCallback == nil { |
| return 0 |
| } |
| return callbacks.TransferProgressCallback(newTransferProgressFromC(stats)) |
| } |
| |
| //export updateTipsCallback |
| func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data unsafe.Pointer) int { |
| callbacks := (*RemoteCallbacks)(data) |
| if callbacks.UpdateTipsCallback == nil { |
| return 0 |
| } |
| refname := C.GoString(_refname) |
| a := newOidFromC(_a) |
| b := newOidFromC(_b) |
| return callbacks.UpdateTipsCallback(refname, a, b) |
| } |
| |
| func RemoteIsValidName(name string) bool { |
| cname := C.CString(name) |
| defer C.free(unsafe.Pointer(cname)) |
| if C.git_remote_is_valid_name(cname) == 1 { |
| return true |
| } |
| return false |
| } |
| |
| func (r *Remote) Free() { |
| runtime.SetFinalizer(r, nil) |
| C.git_remote_free(r.ptr) |
| } |
| |
| func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) { |
| remote := &Remote{} |
| |
| cname := C.CString(name) |
| defer C.free(unsafe.Pointer(cname)) |
| curl := C.CString(url) |
| defer C.free(unsafe.Pointer(curl)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_create(&remote.ptr, repo.ptr, cname, curl) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| runtime.SetFinalizer(remote, (*Remote).Free) |
| return remote, nil |
| } |
| |
| func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch string) (*Remote, error) { |
| remote := &Remote{} |
| |
| cname := C.CString(name) |
| defer C.free(unsafe.Pointer(cname)) |
| curl := C.CString(url) |
| defer C.free(unsafe.Pointer(curl)) |
| cfetch := C.CString(fetch) |
| defer C.free(unsafe.Pointer(cfetch)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_create_with_fetchspec(&remote.ptr, repo.ptr, cname, curl, cfetch) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| runtime.SetFinalizer(remote, (*Remote).Free) |
| return remote, nil |
| } |
| |
| func (repo *Repository) CreateRemoteInMemory(fetch string, url string) (*Remote, error) { |
| remote := &Remote{} |
| |
| curl := C.CString(url) |
| defer C.free(unsafe.Pointer(curl)) |
| cfetch := C.CString(fetch) |
| defer C.free(unsafe.Pointer(cfetch)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_create_inmemory(&remote.ptr, repo.ptr, cfetch, curl) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| runtime.SetFinalizer(remote, (*Remote).Free) |
| return remote, nil |
| } |
| |
| func (repo *Repository) LoadRemote(name string) (*Remote, error) { |
| remote := &Remote{} |
| |
| cname := C.CString(name) |
| defer C.free(unsafe.Pointer(cname)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_load(&remote.ptr, repo.ptr, cname) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| runtime.SetFinalizer(remote, (*Remote).Free) |
| return remote, nil |
| } |
| |
| func (o *Remote) Save() error { |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_save(o.ptr) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) Owner() Repository { |
| return Repository{C.git_remote_owner(o.ptr)} |
| } |
| |
| func (o *Remote) Name() string { |
| return C.GoString(C.git_remote_name(o.ptr)) |
| } |
| |
| func (o *Remote) Url() string { |
| return C.GoString(C.git_remote_url(o.ptr)) |
| } |
| |
| func (o *Remote) PushUrl() string { |
| return C.GoString(C.git_remote_pushurl(o.ptr)) |
| } |
| |
| func (o *Remote) SetUrl(url string) error { |
| curl := C.CString(url) |
| defer C.free(unsafe.Pointer(curl)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_set_url(o.ptr, curl) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) SetPushUrl(url string) error { |
| curl := C.CString(url) |
| defer C.free(unsafe.Pointer(curl)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_set_pushurl(o.ptr, curl) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) AddFetch(refspec string) error { |
| crefspec := C.CString(refspec) |
| defer C.free(unsafe.Pointer(crefspec)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_add_fetch(o.ptr, crefspec) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func sptr(p uintptr) *C.char { |
| return *(**C.char)(unsafe.Pointer(p)) |
| } |
| |
| func makeStringsFromCStrings(x **C.char, l int) []string { |
| s := make([]string, l) |
| i := 0 |
| for p := uintptr(unsafe.Pointer(x)); i < l; p += unsafe.Sizeof(uintptr(0)) { |
| s[i] = C.GoString(sptr(p)) |
| i++ |
| } |
| return s |
| } |
| |
| func makeCStringsFromStrings(s []string) **C.char { |
| l := len(s) |
| x := (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(l)))) |
| i := 0 |
| for p := uintptr(unsafe.Pointer(x)); i < l; p += unsafe.Sizeof(uintptr(0)) { |
| *(**C.char)(unsafe.Pointer(p)) = C.CString(s[i]) |
| i++ |
| } |
| return x |
| } |
| |
| func freeStrarray(arr *C.git_strarray) { |
| count := int(arr.count) |
| size := unsafe.Sizeof(unsafe.Pointer(nil)) |
| |
| i := 0 |
| for p := uintptr(unsafe.Pointer(arr.strings)); i < count; p += size { |
| C.free(unsafe.Pointer(sptr(p))) |
| i++ |
| } |
| |
| C.free(unsafe.Pointer(arr.strings)) |
| } |
| |
| func (o *Remote) FetchRefspecs() ([]string, error) { |
| crefspecs := C.git_strarray{} |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_get_fetch_refspecs(&crefspecs, o.ptr) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| defer C.git_strarray_free(&crefspecs) |
| |
| refspecs := makeStringsFromCStrings(crefspecs.strings, int(crefspecs.count)) |
| return refspecs, nil |
| } |
| |
| func (o *Remote) SetFetchRefspecs(refspecs []string) error { |
| crefspecs := C.git_strarray{} |
| crefspecs.count = C.size_t(len(refspecs)) |
| crefspecs.strings = makeCStringsFromStrings(refspecs) |
| defer freeStrarray(&crefspecs) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_set_fetch_refspecs(o.ptr, &crefspecs) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) AddPush(refspec string) error { |
| crefspec := C.CString(refspec) |
| defer C.free(unsafe.Pointer(crefspec)) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_add_push(o.ptr, crefspec) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) PushRefspecs() ([]string, error) { |
| crefspecs := C.git_strarray{} |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_get_push_refspecs(&crefspecs, o.ptr) |
| if ret < 0 { |
| return nil, MakeGitError(ret) |
| } |
| defer C.git_strarray_free(&crefspecs) |
| refspecs := makeStringsFromCStrings(crefspecs.strings, int(crefspecs.count)) |
| return refspecs, nil |
| } |
| |
| func (o *Remote) SetPushRefspecs(refspecs []string) error { |
| crefspecs := C.git_strarray{} |
| crefspecs.count = C.size_t(len(refspecs)) |
| crefspecs.strings = makeCStringsFromStrings(refspecs) |
| defer freeStrarray(&crefspecs) |
| |
| runtime.LockOSThread() |
| defer runtime.UnlockOSThread() |
| |
| ret := C.git_remote_set_push_refspecs(o.ptr, &crefspecs) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |
| |
| func (o *Remote) ClearRefspecs() { |
| C.git_remote_clear_refspecs(o.ptr) |
| } |
| |
| func (o *Remote) RefspecCount() uint { |
| return uint(C.git_remote_refspec_count(o.ptr)) |
| } |
| |
| func (o *Remote) Fetch(sig *Signature, msg string) error { |
| |
| var csig *C.git_signature = nil |
| if sig != nil { |
| csig = sig.toC() |
| defer C.free(unsafe.Pointer(csig)) |
| } |
| |
| var cmsg *C.char |
| if msg == "" { |
| cmsg = nil |
| } else { |
| cmsg = C.CString(msg) |
| defer C.free(unsafe.Pointer(cmsg)) |
| } |
| ret := C.git_remote_fetch(o.ptr, csig, cmsg) |
| if ret < 0 { |
| return MakeGitError(ret) |
| } |
| return nil |
| } |