commit
9c6db70fc2
84
remote.go
84
remote.go
|
@ -9,9 +9,11 @@ extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks);
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
"unsafe"
|
|
||||||
"runtime"
|
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TransferProgress struct {
|
type TransferProgress struct {
|
||||||
|
@ -34,11 +36,15 @@ func newTransferProgressFromC(c *C.git_transfer_progress) TransferProgress {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoteCompletion uint
|
type RemoteCompletion uint
|
||||||
|
type ConnectDirection uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RemoteCompletionDownload RemoteCompletion = C.GIT_REMOTE_COMPLETION_DOWNLOAD
|
RemoteCompletionDownload RemoteCompletion = C.GIT_REMOTE_COMPLETION_DOWNLOAD
|
||||||
RemoteCompletionIndexing = C.GIT_REMOTE_COMPLETION_INDEXING
|
RemoteCompletionIndexing = C.GIT_REMOTE_COMPLETION_INDEXING
|
||||||
RemoteCompletionError = C.GIT_REMOTE_COMPLETION_ERROR
|
RemoteCompletionError = C.GIT_REMOTE_COMPLETION_ERROR
|
||||||
|
|
||||||
|
ConnectDirectionFetch ConnectDirection = C.GIT_DIRECTION_FETCH
|
||||||
|
ConnectDirectionPush = C.GIT_DIRECTION_PUSH
|
||||||
)
|
)
|
||||||
|
|
||||||
type TransportMessageCallback func(str string) int
|
type TransportMessageCallback func(str string) int
|
||||||
|
@ -95,6 +101,18 @@ type HostkeyCertificate struct {
|
||||||
HashSHA1 [20]byte
|
HashSHA1 [20]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RemoteHead struct {
|
||||||
|
Id *Oid
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRemoteHeadFromC(ptr *C.git_remote_head) RemoteHead {
|
||||||
|
return RemoteHead{
|
||||||
|
Id: newOidFromC(&ptr.oid),
|
||||||
|
Name: C.GoString(ptr.name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) {
|
func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) {
|
||||||
C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION)
|
C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION)
|
||||||
if callbacks == nil {
|
if callbacks == nil {
|
||||||
|
@ -195,7 +213,6 @@ func certificateCheckCallback(_cert *C.git_cert, _valid C.int, _host *C.char, da
|
||||||
return -1 // we don't support anything else atm
|
return -1 // we don't support anything else atm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return callbacks.CertificateCheckCallback(&cert, valid, host)
|
return callbacks.CertificateCheckCallback(&cert, valid, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,3 +565,64 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Remote) ConnectFetch() error {
|
||||||
|
return o.Connect(ConnectDirectionFetch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Remote) ConnectPush() error {
|
||||||
|
return o.Connect(ConnectDirectionPush)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Remote) Connect(direction ConnectDirection) error {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
if ret := C.git_remote_connect(o.ptr, C.git_direction(direction)); ret != 0 {
|
||||||
|
return MakeGitError(ret)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Remote) Ls(filterRefs ...string) ([]RemoteHead, error) {
|
||||||
|
|
||||||
|
var refs **C.git_remote_head
|
||||||
|
var length C.size_t
|
||||||
|
|
||||||
|
if ret := C.git_remote_ls(&refs, &length, o.ptr); ret != 0 {
|
||||||
|
return nil, MakeGitError(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
size := int(length)
|
||||||
|
|
||||||
|
if size == 0 {
|
||||||
|
return make([]RemoteHead, 0), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
hdr := reflect.SliceHeader{
|
||||||
|
Data: uintptr(unsafe.Pointer(refs)),
|
||||||
|
Len: size,
|
||||||
|
Cap: size,
|
||||||
|
}
|
||||||
|
|
||||||
|
goSlice := *(*[]*C.git_remote_head)(unsafe.Pointer(&hdr))
|
||||||
|
|
||||||
|
var heads []RemoteHead
|
||||||
|
|
||||||
|
for _, s := range goSlice {
|
||||||
|
head := newRemoteHeadFromC(s)
|
||||||
|
|
||||||
|
if len(filterRefs) > 0 {
|
||||||
|
for _, r := range filterRefs {
|
||||||
|
if strings.Contains(head.Name, r) {
|
||||||
|
heads = append(heads, head)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
heads = append(heads, head)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return heads, nil
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,6 @@ func TestListRemotes(t *testing.T) {
|
||||||
compareStringList(t, expected, actual)
|
compareStringList(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func assertHostname(cert *Certificate, valid bool, hostname string, t *testing.T) int {
|
func assertHostname(cert *Certificate, valid bool, hostname string, t *testing.T) int {
|
||||||
if hostname != "github.com" {
|
if hostname != "github.com" {
|
||||||
t.Fatal("Hostname does not match")
|
t.Fatal("Hostname does not match")
|
||||||
|
@ -75,3 +74,61 @@ func TestCertificateCheck(t *testing.T) {
|
||||||
err = remote.Fetch([]string{}, nil, "")
|
err = remote.Fetch([]string{}, nil, "")
|
||||||
checkFatal(t, err)
|
checkFatal(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoteConnect(t *testing.T) {
|
||||||
|
repo := createTestRepo(t)
|
||||||
|
defer os.RemoveAll(repo.Workdir())
|
||||||
|
defer repo.Free()
|
||||||
|
|
||||||
|
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
err = remote.ConnectFetch()
|
||||||
|
checkFatal(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteLs(t *testing.T) {
|
||||||
|
repo := createTestRepo(t)
|
||||||
|
defer os.RemoveAll(repo.Workdir())
|
||||||
|
defer repo.Free()
|
||||||
|
|
||||||
|
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
err = remote.ConnectFetch()
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
heads, err := remote.Ls()
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
if len(heads) == 0 {
|
||||||
|
t.Error("Expected remote heads")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteLsFiltering(t *testing.T) {
|
||||||
|
repo := createTestRepo(t)
|
||||||
|
defer os.RemoveAll(repo.Workdir())
|
||||||
|
defer repo.Free()
|
||||||
|
|
||||||
|
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
err = remote.ConnectFetch()
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
heads, err := remote.Ls("master")
|
||||||
|
checkFatal(t, err)
|
||||||
|
|
||||||
|
if len(heads) != 1 {
|
||||||
|
t.Fatalf("Expected one head for master but I got %d", len(heads))
|
||||||
|
}
|
||||||
|
|
||||||
|
if heads[0].Id == nil {
|
||||||
|
t.Fatalf("Expected head to have an Id, but it's nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if heads[0].Name == "" {
|
||||||
|
t.Fatalf("Expected head to have a name, but it's empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue