summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Calavera <[email protected]>2014-10-24 12:12:07 -0700
committerDavid Calavera <[email protected]>2014-10-24 17:28:10 -0700
commitf6fa1a38abf7be7d4546b736e6db1ae7229e972f (patch)
treee46111b0be8194b5ab35920e0f1fcd7e4330a1c0
parent41008af54cfc2af3a5ea56dff169c95d2b50dda6 (diff)
Add Remote#Ls.
Allow filtering heads by name.
-rw-r--r--remote.go72
-rw-r--r--remote_test.go43
2 files changed, 109 insertions, 6 deletions
diff --git a/remote.go b/remote.go
index 2ce3be8..139e71b 100644
--- a/remote.go
+++ b/remote.go
@@ -9,9 +9,11 @@ extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks);
*/
import "C"
import (
- "unsafe"
- "runtime"
"crypto/x509"
+ "reflect"
+ "runtime"
+ "strings"
+ "unsafe"
)
type TransferProgress struct {
@@ -39,6 +41,8 @@ const (
RemoteCompletionDownload RemoteCompletion = C.GIT_REMOTE_COMPLETION_DOWNLOAD
RemoteCompletionIndexing = C.GIT_REMOTE_COMPLETION_INDEXING
RemoteCompletionError = C.GIT_REMOTE_COMPLETION_ERROR
+
+ RemoteFetchDirection = C.GIT_DIRECTION_FETCH
)
type TransportMessageCallback func(str string) int
@@ -58,7 +62,7 @@ type RemoteCallbacks struct {
}
type Remote struct {
- ptr *C.git_remote
+ ptr *C.git_remote
callbacks RemoteCallbacks
}
@@ -95,6 +99,18 @@ type HostkeyCertificate struct {
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) {
C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION)
if callbacks == nil {
@@ -195,7 +211,6 @@ func certificateCheckCallback(_cert *C.git_cert, _valid C.int, _host *C.char, da
return -1 // we don't support anything else atm
}
-
return callbacks.CertificateCheckCallback(&cert, valid, host)
}
@@ -548,3 +563,52 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error {
}
return nil
}
+
+func (o *Remote) Ls(filterRefs ...string) ([]RemoteHead, error) {
+ if ret := C.git_remote_connect(o.ptr, RemoteFetchDirection); ret != 0 {
+ return nil, MakeGitError(ret)
+ }
+
+ 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
+
+ if len(filterRefs) > 0 {
+ for _, s := range goSlice {
+ head := newRemoteHeadFromC(s)
+
+ for _, r := range filterRefs {
+ if strings.Contains(head.Name, r) {
+ heads = append(heads, head)
+ break
+ }
+ }
+ }
+ } else {
+ heads = make([]RemoteHead, size)
+ for i, s := range goSlice {
+ heads[i] = newRemoteHeadFromC(s)
+ }
+ }
+
+ return heads, nil
+}
diff --git a/remote_test.go b/remote_test.go
index d1ad1e8..70e53ce 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -46,7 +46,6 @@ func TestListRemotes(t *testing.T) {
compareStringList(t, expected, actual)
}
-
func assertHostname(cert *Certificate, valid bool, hostname string, t *testing.T) int {
if hostname != "github.com" {
t.Fatal("Hostname does not match")
@@ -65,7 +64,7 @@ func TestCertificateCheck(t *testing.T) {
checkFatal(t, err)
callbacks := RemoteCallbacks{
- CertificateCheckCallback: func (cert *Certificate, valid bool, hostname string) int {
+ CertificateCheckCallback: func(cert *Certificate, valid bool, hostname string) int {
return assertHostname(cert, valid, hostname, t)
},
}
@@ -75,3 +74,43 @@ func TestCertificateCheck(t *testing.T) {
err = remote.Fetch([]string{}, nil, "")
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)
+
+ 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)
+
+ 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")
+ }
+}