add push, refine remotes
This commit is contained in:
parent
e2db9b16cd
commit
374e2112df
15
git_test.go
15
git_test.go
|
@ -1,8 +1,8 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,17 @@ func createTestRepo(t *testing.T) *Repository {
|
|||
checkFatal(t, err)
|
||||
|
||||
tmpfile := "README"
|
||||
err = ioutil.WriteFile(path + "/" + tmpfile, []byte("foo\n"), 0644)
|
||||
err = ioutil.WriteFile(path+"/"+tmpfile, []byte("foo\n"), 0644)
|
||||
checkFatal(t, err)
|
||||
|
||||
return repo
|
||||
}
|
||||
|
||||
func createBareTestRepo(t *testing.T) *Repository {
|
||||
// figure out where we can create the test repo
|
||||
path, err := ioutil.TempDir("", "git2go")
|
||||
checkFatal(t, err)
|
||||
repo, err := InitRepository(path, true)
|
||||
checkFatal(t, err)
|
||||
|
||||
return repo
|
||||
|
@ -44,4 +54,3 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) {
|
|||
|
||||
return commitId, treeId
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
package git
|
||||
|
||||
/*
|
||||
#include <git2.h>
|
||||
#include <git2/errors.h>
|
||||
|
||||
int _go_git_push_status_foreach(git_push *push, void *data);
|
||||
int _go_git_push_set_callbacks(git_push *push, void *packbuilder_progress_data, void *transfer_progress_data);
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Push struct {
|
||||
ptr *C.git_push
|
||||
|
||||
packbuilderProgress *PackbuilderProgressCallback
|
||||
transferProgress *PushTransferProgressCallback
|
||||
}
|
||||
|
||||
func newPushFromC(cpush *C.git_push) *Push {
|
||||
p := &Push{ptr: cpush}
|
||||
runtime.SetFinalizer(p, (*Push).Free)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Push) Free() {
|
||||
runtime.SetFinalizer(p, nil)
|
||||
C.git_push_free(p.ptr)
|
||||
}
|
||||
|
||||
func (remote *Remote) NewPush() (*Push, error) {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
var cpush *C.git_push
|
||||
ret := C.git_push_new(&cpush, remote.ptr)
|
||||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
return newPushFromC(cpush), nil
|
||||
}
|
||||
|
||||
func (p *Push) Finish() error {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_push_finish(p.ptr)
|
||||
if ret < 0 {
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Push) UnpackOk() bool {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_push_unpack_ok(p.ptr)
|
||||
if ret == 0 {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *Push) UpdateTips(sig *Signature, msg string) error {
|
||||
|
||||
var csig *C.git_signature = nil
|
||||
if sig != nil {
|
||||
csig = sig.toC()
|
||||
defer C.free(unsafe.Pointer(csig))
|
||||
}
|
||||
|
||||
cmsg := C.CString(msg)
|
||||
defer C.free(unsafe.Pointer(cmsg))
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_push_update_tips(p.ptr, csig, cmsg)
|
||||
if ret < 0 {
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Push) AddRefspec(refspec string) error {
|
||||
|
||||
crefspec := C.CString(refspec)
|
||||
defer C.free(unsafe.Pointer(crefspec))
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_push_add_refspec(p.ptr, crefspec)
|
||||
if ret < 0 {
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PushOptions struct {
|
||||
Version uint
|
||||
PbParallelism uint
|
||||
}
|
||||
|
||||
func (p *Push) SetOptions(opts PushOptions) error {
|
||||
copts := C.git_push_options{version: C.uint(opts.Version), pb_parallelism: C.uint(opts.PbParallelism)}
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C.git_push_set_options(p.ptr, &copts)
|
||||
if ret < 0 {
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type StatusForeachFunc func(ref string, msg string) int
|
||||
|
||||
//export statusForeach
|
||||
func statusForeach(_ref *C.char, _msg *C.char, _data unsafe.Pointer) C.int {
|
||||
ref := C.GoString(_ref)
|
||||
msg := C.GoString(_msg)
|
||||
|
||||
cb := (*StatusForeachFunc)(_data)
|
||||
|
||||
return C.int((*cb)(ref, msg))
|
||||
}
|
||||
|
||||
func (p *Push) StatusForeach(callback StatusForeachFunc) error {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
ret := C._go_git_push_status_foreach(p.ptr, unsafe.Pointer(&callback))
|
||||
if ret < 0 {
|
||||
return MakeGitError(ret)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
type PushCallbacks struct {
|
||||
PackbuilderProgress *PackbuilderProgressCallback
|
||||
TransferProgress *PushTransferProgressCallback
|
||||
}
|
||||
|
||||
type PackbuilderProgressCallback func(stage int, current uint, total uint) int
|
||||
type PushTransferProgressCallback func(current uint, total uint, bytes uint) int
|
||||
|
||||
//export packbuilderProgress
|
||||
func packbuilderProgress(stage C.int, current C.uint, total C.uint, data unsafe.Pointer) C.int {
|
||||
return C.int((*(*PackbuilderProgressCallback)(data))(int(stage), uint(current), uint(total)))
|
||||
}
|
||||
|
||||
//export pushTransferProgress
|
||||
func pushTransferProgress(current C.uint, total C.uint, bytes C.size_t, data unsafe.Pointer) C.int {
|
||||
return C.int((*(*PushTransferProgressCallback)(data))(uint(current), uint(total), uint(bytes)))
|
||||
}
|
||||
|
||||
func (p *Push) SetCallbacks(callbacks PushCallbacks) {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
// save callbacks so they don't get GC'd
|
||||
p.packbuilderProgress = callbacks.PackbuilderProgress
|
||||
p.transferProgress = callbacks.TransferProgress
|
||||
|
||||
C._go_git_push_set_callbacks(p.ptr, unsafe.Pointer(p.packbuilderProgress), unsafe.Pointer(p.transferProgress))
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_Push_ToRemote(t *testing.T) {
|
||||
repo := createBareTestRepo(t)
|
||||
repo2 := createTestRepo(t)
|
||||
|
||||
remote, err := repo2.CreateRemote("test_push", repo.Path())
|
||||
checkFatal(t, err)
|
||||
|
||||
index, err := repo2.Index()
|
||||
checkFatal(t, err)
|
||||
|
||||
index.AddByPath("README")
|
||||
|
||||
err = index.Write()
|
||||
checkFatal(t, err)
|
||||
|
||||
newTreeId, err := index.WriteTree()
|
||||
checkFatal(t, err)
|
||||
|
||||
tree, err := repo2.LookupTree(newTreeId)
|
||||
checkFatal(t, err)
|
||||
|
||||
sig := &Signature{Name: "Rand Om Hacker", Email: "random@hacker.com", When: time.Now()}
|
||||
// this should cause master branch to be created if it does not already exist
|
||||
_, err = repo2.CreateCommit("HEAD", sig, sig, "message", tree)
|
||||
checkFatal(t, err)
|
||||
|
||||
push, err := remote.NewPush()
|
||||
checkFatal(t, err)
|
||||
|
||||
err = push.AddRefspec("refs/heads/master")
|
||||
checkFatal(t, err)
|
||||
|
||||
err = push.Finish()
|
||||
checkFatal(t, err)
|
||||
|
||||
err = push.StatusForeach(func(ref string, msg string) int {
|
||||
log.Printf("%s -> %s", ref, msg)
|
||||
return 0
|
||||
})
|
||||
checkFatal(t, err)
|
||||
|
||||
if !push.UnpackOk() {
|
||||
t.Fatalf("unable to unpack")
|
||||
}
|
||||
|
||||
defer remote.Free()
|
||||
defer repo.Free()
|
||||
}
|
99
remote.go
99
remote.go
|
@ -40,27 +40,7 @@ type RemoteCallbacks struct {
|
|||
UpdateTipsCallback
|
||||
}
|
||||
|
||||
type Remote interface {
|
||||
Save() error
|
||||
Owner() Repository
|
||||
Name() string
|
||||
Url() string
|
||||
PushUrl() string
|
||||
|
||||
SetUrl(url string) error
|
||||
SetPushUrl(url string) error
|
||||
|
||||
AddFetch(refspec string) error
|
||||
GetFetchRefspecs() ([]string, error)
|
||||
SetFetchRefspecs(refspecs []string) error
|
||||
AddPush(refspec string) error
|
||||
GetPushRefspecs() ([]string, error)
|
||||
SetPushRefspecs(refspecs []string) error
|
||||
ClearRefspecs()
|
||||
RefspecCount() uint
|
||||
}
|
||||
|
||||
type gitRemote struct {
|
||||
type Remote struct {
|
||||
ptr *C.git_remote
|
||||
}
|
||||
|
||||
|
@ -161,13 +141,13 @@ func RemoteIsValidName(name string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func freeRemote(o *gitRemote) {
|
||||
C.git_remote_free(o.ptr)
|
||||
func (r *Remote) Free() {
|
||||
runtime.SetFinalizer(r, nil)
|
||||
C.git_remote_free(r.ptr)
|
||||
}
|
||||
|
||||
func CreateRemote(repo *Repository, name string, url string) (Remote, error) {
|
||||
remote := &gitRemote{}
|
||||
runtime.SetFinalizer(remote, freeRemote)
|
||||
func (repo *Repository) CreateRemote(name string, url string) (*Remote, error) {
|
||||
remote := &Remote{}
|
||||
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
@ -181,12 +161,12 @@ func CreateRemote(repo *Repository, name string, url string) (Remote, error) {
|
|||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
runtime.SetFinalizer(remote, (*Remote).Free)
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch string) (Remote, error) {
|
||||
remote := &gitRemote{}
|
||||
runtime.SetFinalizer(remote, freeRemote)
|
||||
func (repo *Repository) CreateRemoteWithFetchspec(name string, url string, fetch string) (*Remote, error) {
|
||||
remote := &Remote{}
|
||||
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
@ -202,12 +182,12 @@ func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch
|
|||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
runtime.SetFinalizer(remote, (*Remote).Free)
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func CreateRemoteInMemory(repo *Repository, fetch string, url string) (Remote, error) {
|
||||
remote := &gitRemote{}
|
||||
runtime.SetFinalizer(remote, freeRemote)
|
||||
func (repo *Repository) CreateRemoteInMemory(fetch string, url string) (*Remote, error) {
|
||||
remote := &Remote{}
|
||||
|
||||
curl := C.CString(url)
|
||||
defer C.free(unsafe.Pointer(curl))
|
||||
|
@ -221,12 +201,12 @@ func CreateRemoteInMemory(repo *Repository, fetch string, url string) (Remote, e
|
|||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
runtime.SetFinalizer(remote, (*Remote).Free)
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func LoadRemote(repo *Repository, name string) (Remote, error) {
|
||||
remote := &gitRemote{}
|
||||
runtime.SetFinalizer(remote, freeRemote)
|
||||
func (repo *Repository) LoadRemote(name string) (*Remote, error) {
|
||||
remote := &Remote{}
|
||||
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
|
@ -238,10 +218,11 @@ func LoadRemote(repo *Repository, name string) (Remote, error) {
|
|||
if ret < 0 {
|
||||
return nil, MakeGitError(ret)
|
||||
}
|
||||
runtime.SetFinalizer(remote, (*Remote).Free)
|
||||
return remote, nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) Save() error {
|
||||
func (o *Remote) Save() error {
|
||||
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
@ -253,23 +234,23 @@ func (o *gitRemote) Save() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) Owner() Repository {
|
||||
func (o *Remote) Owner() Repository {
|
||||
return Repository{C.git_remote_owner(o.ptr)}
|
||||
}
|
||||
|
||||
func (o *gitRemote) Name() string {
|
||||
func (o *Remote) Name() string {
|
||||
return C.GoString(C.git_remote_name(o.ptr))
|
||||
}
|
||||
|
||||
func (o *gitRemote) Url() string {
|
||||
func (o *Remote) Url() string {
|
||||
return C.GoString(C.git_remote_url(o.ptr))
|
||||
}
|
||||
|
||||
func (o *gitRemote) PushUrl() string {
|
||||
func (o *Remote) PushUrl() string {
|
||||
return C.GoString(C.git_remote_pushurl(o.ptr))
|
||||
}
|
||||
|
||||
func (o *gitRemote) SetUrl(url string) error {
|
||||
func (o *Remote) SetUrl(url string) error {
|
||||
curl := C.CString(url)
|
||||
defer C.free(unsafe.Pointer(curl))
|
||||
|
||||
|
@ -283,7 +264,7 @@ func (o *gitRemote) SetUrl(url string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) SetPushUrl(url string) error {
|
||||
func (o *Remote) SetPushUrl(url string) error {
|
||||
curl := C.CString(url)
|
||||
defer C.free(unsafe.Pointer(curl))
|
||||
|
||||
|
@ -297,7 +278,7 @@ func (o *gitRemote) SetPushUrl(url string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) AddFetch(refspec string) error {
|
||||
func (o *Remote) AddFetch(refspec string) error {
|
||||
crefspec := C.CString(refspec)
|
||||
defer C.free(unsafe.Pointer(crefspec))
|
||||
|
||||
|
@ -311,7 +292,7 @@ func (o *gitRemote) AddFetch(refspec string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) GetFetchRefspecs() ([]string, error) {
|
||||
func (o *Remote) GetFetchRefspecs() ([]string, error) {
|
||||
crefspecs := C.git_strarray{}
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
@ -330,7 +311,7 @@ func (o *gitRemote) GetFetchRefspecs() ([]string, error) {
|
|||
return refspecs, nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) SetFetchRefspecs(refspecs []string) error {
|
||||
func (o *Remote) SetFetchRefspecs(refspecs []string) error {
|
||||
crefspecs := C.git_strarray{}
|
||||
crefspecs.count = C.size_t(len(refspecs))
|
||||
crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count))))
|
||||
|
@ -349,7 +330,7 @@ func (o *gitRemote) SetFetchRefspecs(refspecs []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) AddPush(refspec string) error {
|
||||
func (o *Remote) AddPush(refspec string) error {
|
||||
crefspec := C.CString(refspec)
|
||||
defer C.free(unsafe.Pointer(crefspec))
|
||||
|
||||
|
@ -363,7 +344,7 @@ func (o *gitRemote) AddPush(refspec string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) GetPushRefspecs() ([]string, error) {
|
||||
func (o *Remote) GetPushRefspecs() ([]string, error) {
|
||||
crefspecs := C.git_strarray{}
|
||||
|
||||
runtime.LockOSThread()
|
||||
|
@ -382,7 +363,7 @@ func (o *gitRemote) GetPushRefspecs() ([]string, error) {
|
|||
return refspecs, nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) SetPushRefspecs(refspecs []string) error {
|
||||
func (o *Remote) SetPushRefspecs(refspecs []string) error {
|
||||
crefspecs := C.git_strarray{}
|
||||
crefspecs.count = C.size_t(len(refspecs))
|
||||
crefspecs.strings = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count))))
|
||||
|
@ -401,10 +382,28 @@ func (o *gitRemote) SetPushRefspecs(refspecs []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (o *gitRemote) ClearRefspecs() {
|
||||
func (o *Remote) ClearRefspecs() {
|
||||
C.git_remote_clear_refspecs(o.ptr)
|
||||
}
|
||||
|
||||
func (o *gitRemote) RefspecCount() uint {
|
||||
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))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
12
wrapper.c
12
wrapper.c
|
@ -51,4 +51,16 @@ char *_go_git_get_strarray_n(git_strarray *array, size_t n) {
|
|||
return array->strings[n];
|
||||
}
|
||||
|
||||
typedef int (*status_foreach_cb)(const char *ref, const char *msg, void *data);
|
||||
|
||||
int _go_git_push_status_foreach(git_push *push, void *data)
|
||||
{
|
||||
return git_push_status_foreach(push, (status_foreach_cb)statusForeach, data);
|
||||
}
|
||||
|
||||
int _go_git_push_set_callbacks(git_push *push, void *packbuilder_progress_data, void *transfer_progress_data)
|
||||
{
|
||||
return git_push_set_callbacks(push, packbuilderProgress, packbuilder_progress_data, pushTransferProgress, transfer_progress_data);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in New Issue