205 lines
4.0 KiB
Go
205 lines
4.0 KiB
Go
package git
|
|
|
|
/*
|
|
#cgo pkg-config: libgit2
|
|
#include <git2.h>
|
|
#include <git2/errors.h>
|
|
|
|
extern int _go_git_remote_ls(git_remote *remote, void *payload);
|
|
extern int _go_git_remote_set_callbacks(git_remote *remote, void *payload);
|
|
*/
|
|
import "C"
|
|
import (
|
|
"runtime"
|
|
"unsafe"
|
|
)
|
|
|
|
type RemoteDirection int
|
|
|
|
const (
|
|
RemoteDirectionFetch RemoteDirection = C.GIT_DIRECTION_FETCH
|
|
RemoteDirectionPush = C.GIT_DIRECTION_PUSH
|
|
)
|
|
|
|
type AutotagOption int
|
|
|
|
const (
|
|
AutotagAuto AutotagOption = C.GIT_REMOTE_DOWNLOAD_TAGS_AUTO
|
|
AutotagNone = C.GIT_REMOTE_DOWNLOAD_TAGS_NONE
|
|
AutotagAll = C.GIT_REMOTE_DOWNLOAD_TAGS_ALL
|
|
)
|
|
|
|
type Remote struct {
|
|
Name string
|
|
Url string
|
|
ptr *C.git_remote
|
|
}
|
|
|
|
func (r *Remote) Connect(direction RemoteDirection) error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
ret := C.git_remote_connect(r.ptr, C.git_direction(direction))
|
|
if ret < 0 {
|
|
return LastError()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Remote) IsConnected() bool {
|
|
return C.git_remote_connected(r.ptr) != 0
|
|
}
|
|
|
|
func (r *Remote) Disconnect() {
|
|
C.git_remote_disconnect(r.ptr)
|
|
}
|
|
|
|
func (r *Remote) Autotag() AutotagOption {
|
|
return AutotagOption(C.git_remote_autotag(r.ptr))
|
|
}
|
|
|
|
func (r *Remote) SetAutotag(opt AutotagOption) {
|
|
C.git_remote_set_autotag(r.ptr, C.git_remote_autotag_option_t(opt))
|
|
}
|
|
|
|
func (r *Remote) Stop() {
|
|
C.git_remote_stop(r.ptr)
|
|
}
|
|
|
|
func (r *Remote) Save() error {
|
|
runtime.LockOSThread()
|
|
defer runtime.UnlockOSThread()
|
|
|
|
ret := C.git_remote_save(r.ptr)
|
|
if ret < 0 {
|
|
return LastError()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Remote) Ls() ([]*RemoteHead, error) {
|
|
var data headlistData
|
|
|
|
ret := C._go_git_remote_ls(r.ptr, unsafe.Pointer(&data))
|
|
if ret < 0 {
|
|
return nil, LastError()
|
|
}
|
|
|
|
return data.slice, nil
|
|
}
|
|
|
|
func (r *Remote) SetCallbacks(callbacks *RemoteCallbacks) {
|
|
C._go_git_remote_set_callbacks(r.ptr, unsafe.Pointer(callbacks))
|
|
}
|
|
|
|
//export remoteProgress
|
|
func remoteProgress(str *C.char, length C.int, data unsafe.Pointer) int {
|
|
callbacks := (*RemoteCallbacks)(data)
|
|
if callbacks.Progress != nil {
|
|
return callbacks.Progress(C.GoBytes(unsafe.Pointer(str), length))
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
//export updateTips
|
|
func updateTips(str *C.char, a, b *C.git_oid, data unsafe.Pointer) int {
|
|
callbacks := (*RemoteCallbacks)(data)
|
|
goa, gob := newOidFromC(a), newOidFromC(b)
|
|
if callbacks.UpdateTips != nil {
|
|
return callbacks.UpdateTips(C.GoString(str), goa, gob)
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func (r *Remote) Download() (error) {
|
|
ret := C.git_remote_download(r.ptr)
|
|
if ret < 0 {
|
|
LastError()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type ProgressCb func([]byte) int
|
|
type UpdateTipsCb func(string, *Oid, *Oid) int
|
|
|
|
//export RemoteCallbacks
|
|
type RemoteCallbacks struct {
|
|
Progress ProgressCb
|
|
UpdateTips UpdateTipsCb
|
|
}
|
|
|
|
type headlistData struct {
|
|
slice []*RemoteHead
|
|
}
|
|
|
|
//export remoteHeadlistCb
|
|
func remoteHeadlistCb(rhead *C.git_remote_head, dataptr unsafe.Pointer) int {
|
|
data := (*headlistData)(dataptr)
|
|
|
|
head := newRemoteHeadFromC(rhead)
|
|
data.slice = append(data.slice, head)
|
|
|
|
return 0
|
|
}
|
|
|
|
func (r *Remote) Free() {
|
|
runtime.SetFinalizer(r, nil)
|
|
C.git_remote_free(r.ptr)
|
|
}
|
|
|
|
func newRemoteFromC(ptr *C.git_remote) *Remote {
|
|
remote := &Remote{
|
|
ptr: ptr,
|
|
Name: C.GoString(C.git_remote_name(ptr)),
|
|
Url: C.GoString(C.git_remote_url(ptr)),
|
|
}
|
|
|
|
runtime.SetFinalizer(remote, (*Remote).Free)
|
|
|
|
return remote
|
|
}
|
|
|
|
// remote heads
|
|
|
|
// RemoteHead represents a reference available in the remote repository.
|
|
type RemoteHead struct {
|
|
Local bool
|
|
Oid Oid
|
|
Loid Oid
|
|
Name string
|
|
}
|
|
|
|
func newRemoteHeadFromC(ptr *C.git_remote_head) *RemoteHead {
|
|
head := &RemoteHead {
|
|
Local: ptr.local != 0,
|
|
Name: C.GoString(ptr.name),
|
|
}
|
|
|
|
CopyOid(&head.Oid, &ptr.oid)
|
|
CopyOid(&head.Loid, &ptr.loid)
|
|
|
|
return head
|
|
}
|
|
|
|
// These belong to the git_remote namespace but don't require any remote
|
|
|
|
func UrlIsValid(url string) bool {
|
|
curl := C.CString(url)
|
|
defer C.free(unsafe.Pointer(curl))
|
|
|
|
return C.git_remote_valid_url(curl) != 0
|
|
}
|
|
|
|
|
|
func UrlIsSupported(url string) bool {
|
|
curl := C.CString(url)
|
|
defer C.free(unsafe.Pointer(curl))
|
|
|
|
return C.git_remote_supported_url(curl) != 0
|
|
}
|