From e825d66fba2cb4169c7f3b0a43c491cf9e8c0738 Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Sat, 4 Jan 2014 00:40:21 +0000 Subject: work in progress wrapping git_clone --- wrapper.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'wrapper.c') diff --git a/wrapper.c b/wrapper.c index 2af3974..ef05c2d 100644 --- a/wrapper.c +++ b/wrapper.c @@ -24,4 +24,18 @@ int _go_git_odb_foreach(git_odb *db, void *payload) { return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } + +void _setup_callbacks(git_remote_callbacks *callbacks) { + typedef int (*progress_cb)(const char *str, int len, void *data); + typedef int (*completion_cb)(git_remote_completion_type type, void *data); + typedef int (*credentials_cb)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); + typedef int (*transfer_progress_cb)(const git_transfer_progress *stats, void *data); + typedef int (*update_tips_cb)(const char *refname, const git_oid *a, const git_oid *b, void *data); + callbacks->progress = (progress_cb)progressCallback; + callbacks->completion = (completion_cb)completionCallback; + callbacks->credentials = (credentials_cb)credentialsCallback; + callbacks->transfer_progress = (transfer_progress_cb)transferProgressCallback; + callbacks->update_tips = (update_tips_cb)updateTipsCallback; +} + /* EOF */ -- cgit v1.2.3 From d1245446685ccdc632b6a9cee65391cbe4eac4df Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Mon, 6 Jan 2014 16:55:29 +0000 Subject: minor --- remote.go | 12 ++++-------- wrapper.c | 7 ++++++- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'wrapper.c') diff --git a/remote.go b/remote.go index ebf1fd4..0645291 100644 --- a/remote.go +++ b/remote.go @@ -4,12 +4,8 @@ package git #include #include -static git_remote_callbacks git_remote_callbacks_init() { - git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; - return ret; -} - -extern void _setup_callbacks(git_remote_callbacks *callbacks); +extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); +extern git_remote_callbacks _go_git_remote_callbacks_init(); */ import "C" @@ -41,11 +37,11 @@ type RemoteCallbacks struct { } func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { - *ptr = C.git_remote_callbacks_init() + *ptr = C._go_git_remote_callbacks_init() if callbacks == nil { return } - C._setup_callbacks(ptr) + C._go_git_setup_callbacks(ptr) ptr.payload = unsafe.Pointer(callbacks) } diff --git a/wrapper.c b/wrapper.c index ef05c2d..4543822 100644 --- a/wrapper.c +++ b/wrapper.c @@ -25,7 +25,7 @@ int _go_git_odb_foreach(git_odb *db, void *payload) return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } -void _setup_callbacks(git_remote_callbacks *callbacks) { +void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { typedef int (*progress_cb)(const char *str, int len, void *data); typedef int (*completion_cb)(git_remote_completion_type type, void *data); typedef int (*credentials_cb)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); @@ -38,4 +38,9 @@ void _setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } +git_remote_callbacks _go_git_remote_callbacks_init() { + git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; + return ret; +} + /* EOF */ -- cgit v1.2.3 From 32bf5f0a234e0c3cd00dc8eec349ee820f765f19 Mon Sep 17 00:00:00 2001 From: Jason Toffaletti Date: Mon, 6 Jan 2014 20:05:35 +0000 Subject: wip wrapping git_remote --- clone.go | 11 ++++ remote.go | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 8 +++ 3 files changed, 212 insertions(+) (limited to 'wrapper.c') diff --git a/clone.go b/clone.go index 672c325..425e179 100644 --- a/clone.go +++ b/clone.go @@ -37,6 +37,17 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) var copts C.git_clone_options populateCloneOptions(&copts, options) + // finish populating clone options here so we can defer CString free + if len(options.RemoteName) != 0 { + copts.remote_name = C.CString(options.RemoteName) + defer C.free(unsafe.Pointer(copts.remote_name)) + } + + if len(options.CheckoutBranch) != 0 { + copts.checkout_branch = C.CString(options.CheckoutBranch) + defer C.free(unsafe.Pointer(copts.checkout_branch)) + } + runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_clone(&repo.ptr, curl, cpath, &copts) diff --git a/remote.go b/remote.go index 0645291..5300c42 100644 --- a/remote.go +++ b/remote.go @@ -6,10 +6,13 @@ package git extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); extern git_remote_callbacks _go_git_remote_callbacks_init(); +extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); +extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); */ import "C" import "unsafe" +import "runtime" type TransferProgress struct { ptr *C.git_transfer_progress @@ -36,6 +39,30 @@ type RemoteCallbacks struct { UpdateTipsCallback } +type Remote interface { + Save() int + Owner() Repository + Name() string + Url() string + PushUrl() string + + SetUrl(url string) int + SetPushUrl(url string) int + + AddFetch(refspec string) int + GetFetchRefspecs() (err int, refspecs []string) + SetFetchRefspecs(refspecs []string) int + AddPush(refspec string) int + GetPushRefspecs() (err int, refspecs []string) + SetPushRefspecs(refspecs []string) int + ClearRefspecs() + RefspecCount() uint +} + +type gitRemote struct { + ptr *C.git_remote +} + func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { *ptr = C._go_git_remote_callbacks_init() if callbacks == nil { @@ -123,3 +150,169 @@ func (o TransferProgress) TotalDeltas() uint { func (o TransferProgress) ReceivedBytes() uint { return uint(o.ptr.received_bytes) } + +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 freeRemote(o *gitRemote) { + C.git_remote_free(o.ptr) +} + +func CreateRemote(repo *Repository, name string, url string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + + ret := C.git_remote_create(&remote.ptr, repo.ptr, cname, curl) + return int(ret), remote +} + +func CreateRemoteWithFetchspec(repo *Repository, name string, url string, fetch string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + 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)) + + ret := C.git_remote_create_with_fetchspec(&remote.ptr, repo.ptr, cname, curl, cfetch) + return int(ret), remote +} + +func CreateRemoteInMemory(repo *Repository, fetch string, url string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + cfetch := C.CString(fetch) + defer C.free(unsafe.Pointer(cfetch)) + + ret := C.git_remote_create_inmemory(&remote.ptr, repo.ptr, cfetch, curl) + return int(ret), remote +} + +func LoadRemote(repo *Repository, name string) (int, Remote) { + remote := &gitRemote{} + runtime.SetFinalizer(remote, freeRemote) + + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + + ret := C.git_remote_load(&remote.ptr, repo.ptr, cname) + return int(ret), remote +} + +func (o *gitRemote) Save() int { + return int(C.git_remote_save(o.ptr)) +} + +func (o *gitRemote) Owner() Repository { + return Repository{C.git_remote_owner(o.ptr)} +} + +func (o *gitRemote) Name() string { + return C.GoString(C.git_remote_name(o.ptr)) +} + +func (o *gitRemote) Url() string { + return C.GoString(C.git_remote_url(o.ptr)) +} + +func (o *gitRemote) PushUrl() string { + return C.GoString(C.git_remote_pushurl(o.ptr)) +} + +func (o *gitRemote) SetUrl(url string) int { + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + return int(C.git_remote_set_url(o.ptr, curl)) +} + +func (o *gitRemote) SetPushUrl(url string) int { + curl := C.CString(url) + defer C.free(unsafe.Pointer(curl)) + return int(C.git_remote_set_pushurl(o.ptr, curl)) +} + +func (o *gitRemote) AddFetch(refspec string) int { + crefspec := C.CString(refspec) + defer C.free(unsafe.Pointer(crefspec)) + return int(C.git_remote_add_fetch(o.ptr, crefspec)) +} + +func (o *gitRemote) GetFetchRefspecs() (err int, refspecs []string) { + crefspecs := C.git_strarray{} + err = int(C.git_remote_get_fetch_refspecs(&crefspecs, o.ptr)) + defer C.git_strarray_free(&crefspecs) + refspecs = make([]string, crefspecs.count) + + for i := 0; i < int(crefspecs.count); i++ { + refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) + } + return +} + +func (o *gitRemote) SetFetchRefspecs(refspecs []string) int { + 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)))) + for i, refspec := range refspecs { + C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) + } + defer C.git_strarray_free(&crefspecs) + + return int(C.git_remote_set_fetch_refspecs(o.ptr, &crefspecs)) +} + +func (o *gitRemote) AddPush(refspec string) int { + crefspec := C.CString(refspec) + defer C.free(unsafe.Pointer(crefspec)) + return int(C.git_remote_add_push(o.ptr, crefspec)) +} + +func (o *gitRemote) GetPushRefspecs() (err int, refspecs []string) { + crefspecs := C.git_strarray{} + err = int(C.git_remote_get_push_refspecs(&crefspecs, o.ptr)) + defer C.git_strarray_free(&crefspecs) + refspecs = make([]string, crefspecs.count) + + for i := 0; i < int(crefspecs.count); i++ { + refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) + } + return +} + +func (o *gitRemote) SetPushRefspecs(refspecs []string) int { + 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)))) + for i, refspec := range refspecs { + C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) + } + defer C.git_strarray_free(&crefspecs) + + return int(C.git_remote_set_push_refspecs(o.ptr, &crefspecs)) +} + +func (o *gitRemote) ClearRefspecs() { + C.git_remote_clear_refspecs(o.ptr) +} + +func (o *gitRemote) RefspecCount() uint { + return uint(C.git_remote_refspec_count(o.ptr)) +} + diff --git a/wrapper.c b/wrapper.c index 4543822..7519a96 100644 --- a/wrapper.c +++ b/wrapper.c @@ -43,4 +43,12 @@ git_remote_callbacks _go_git_remote_callbacks_init() { return ret; } +void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { + array->strings[n] = str; +} + +char *_go_git_get_strarray_n(git_strarray *array, size_t n) { + return array->strings[n]; +} + /* EOF */ -- cgit v1.2.3 From 374e2112dfc298fa5ecb0805624d75b3500cc345 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Thu, 27 Feb 2014 16:36:44 -0800 Subject: add push, refine remotes --- git_test.go | 15 ++++- push.go | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ push_test.go | 56 ++++++++++++++++++ remote.go | 99 ++++++++++++++++---------------- wrapper.c | 12 ++++ 5 files changed, 310 insertions(+), 53 deletions(-) create mode 100644 push.go create mode 100644 push_test.go (limited to 'wrapper.c') diff --git a/git_test.go b/git_test.go index 52aea1d..fff3c6c 100644 --- a/git_test.go +++ b/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 } - diff --git a/push.go b/push.go new file mode 100644 index 0000000..0694fe3 --- /dev/null +++ b/push.go @@ -0,0 +1,181 @@ +package git + +/* +#include +#include + +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)) +} diff --git a/push_test.go b/push_test.go new file mode 100644 index 0000000..dfd4af7 --- /dev/null +++ b/push_test.go @@ -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() +} diff --git a/remote.go b/remote.go index 38c1d47..ab2e174 100644 --- a/remote.go +++ b/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 +} diff --git a/wrapper.c b/wrapper.c index 7519a96..9e193ca 100644 --- a/wrapper.c +++ b/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 */ -- cgit v1.2.3 From 5e163fa2e8281642dbb9dbf6229a9a20387130d2 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 7 Mar 2014 16:43:20 -0800 Subject: add blob chunk creation, creation of tree builders for specific trees, minor API cleanup --- blob.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- repository.go | 24 +++++++++++++++++----- tree.go | 38 ++++++++++++++++++++++++---------- walk.go | 21 +++++++++++++------ wrapper.c | 13 ++++++++++++ 5 files changed, 137 insertions(+), 24 deletions(-) (limited to 'wrapper.c') diff --git a/blob.go b/blob.go index b638c4f..ced2cb1 100644 --- a/blob.go +++ b/blob.go @@ -3,9 +3,18 @@ package git /* #include #include +#include + +extern int _go_git_blob_create_fromchunks(git_oid *id, + git_repository *repo, + const char *hintpath, + void *payload); + */ import "C" import ( + "io" + "runtime" "unsafe" ) @@ -13,13 +22,65 @@ type Blob struct { gitObject } -func (v Blob) Size() int64 { +func (v *Blob) Size() int64 { return int64(C.git_blob_rawsize(v.ptr)) } -func (v Blob) Contents() []byte { +func (v *Blob) Contents() []byte { size := C.int(C.git_blob_rawsize(v.ptr)) buffer := unsafe.Pointer(C.git_blob_rawcontent(v.ptr)) return C.GoBytes(buffer, size) } +func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + oid := C.git_oid{} + ecode := C.git_blob_create_frombuffer(&oid, repo.ptr, unsafe.Pointer(&data[0]), C.size_t(len(data))) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + return newOidFromC(&oid), nil +} + +type BlobChunkCallback func(maxLen int) ([]byte, error) + +type BlobCallbackData struct { + Callback BlobChunkCallback + Error error +} + +//export blobChunkCb +func blobChunkCb(buffer *C.char, maxLen C.size_t, payload unsafe.Pointer) int { + data := (*BlobCallbackData)(payload) + goBuf, err := data.Callback(int(maxLen)) + if err == io.EOF { + return 1 + } else if err != nil { + data.Error = err + return -1 + } + C.memcpy(unsafe.Pointer(buffer), unsafe.Pointer(&goBuf), C.size_t(len(goBuf))) + return 0 +} + +func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunkCallback) (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var chintPath *C.char = nil + if len(hintPath) > 0 { + C.CString(hintPath) + defer C.free(unsafe.Pointer(chintPath)) + } + oid := C.git_oid{} + payload := &BlobCallbackData{Callback: callback} + ecode := C._go_git_blob_create_fromchunks(&oid, repo.ptr, chintPath, unsafe.Pointer(payload)) + if payload.Error != nil { + return nil, payload.Error + } + if ecode < 0 { + return nil, MakeGitError(ecode) + } + return newOidFromC(&oid), nil +} diff --git a/repository.go b/repository.go index 6b7345d..d6eadc8 100644 --- a/repository.go +++ b/repository.go @@ -206,19 +206,18 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si } func (v *Repository) Walk() (*RevWalk, error) { - walk := new(RevWalk) + + var walkPtr *C.git_revwalk runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_revwalk_new(&walk.ptr, v.ptr) + ecode := C.git_revwalk_new(&walkPtr, v.ptr) if ecode < 0 { return nil, MakeGitError(ecode) } - walk.repo = v - runtime.SetFinalizer(walk, freeRevWalk) - return walk, nil + return revWalkFromC(v, walkPtr), nil } func (v *Repository) CreateCommit( @@ -326,6 +325,21 @@ func (v *Repository) TreeBuilder() (*TreeBuilder, error) { return bld, nil } +func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) { + bld := new(TreeBuilder) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if ret := C.git_treebuilder_create(&bld.ptr, tree.ptr); ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(bld, (*TreeBuilder).Free) + + bld.repo = v + return bld, nil +} + func (v *Repository) RevparseSingle(spec string) (Object, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) diff --git a/tree.go b/tree.go index b3340d6..7070ac7 100644 --- a/tree.go +++ b/tree.go @@ -14,13 +14,14 @@ import ( ) type Filemode int + const ( - FilemodeNew Filemode = C.GIT_FILEMODE_NEW - FilemodeTree = C.GIT_FILEMODE_TREE - FilemodeBlob = C.GIT_FILEMODE_BLOB - FilemodeBlobExecutable = C.GIT_FILEMODE_BLOB_EXECUTABLE - FilemodeLink = C.GIT_FILEMODE_LINK - FilemodeCommit = C.GIT_FILEMODE_COMMIT + FilemodeNew Filemode = C.GIT_FILEMODE_NEW + FilemodeTree = C.GIT_FILEMODE_TREE + FilemodeBlob = C.GIT_FILEMODE_BLOB + FilemodeBlobExecutable = C.GIT_FILEMODE_BLOB_EXECUTABLE + FilemodeLink = C.GIT_FILEMODE_LINK + FilemodeCommit = C.GIT_FILEMODE_COMMIT ) type Tree struct { @@ -28,9 +29,9 @@ type Tree struct { } type TreeEntry struct { - Name string - Id *Oid - Type ObjectType + Name string + Id *Oid + Type ObjectType Filemode int } @@ -116,7 +117,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error { } type TreeBuilder struct { - ptr *C.git_treebuilder + ptr *C.git_treebuilder repo *Repository } @@ -125,7 +126,7 @@ func (v *TreeBuilder) Free() { C.git_treebuilder_free(v.ptr) } -func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) { +func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) error { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) @@ -140,6 +141,21 @@ func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) (error) { return nil } +func (v *TreeBuilder) Remove(filename string) error { + cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(cfilename)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := C.git_treebuilder_remove(v.ptr, cfilename) + if err < 0 { + return MakeGitError(err) + } + + return nil +} + func (v *TreeBuilder) Write() (*Oid, error) { oid := new(Oid) diff --git a/walk.go b/walk.go index cdc1a20..71df7bb 100644 --- a/walk.go +++ b/walk.go @@ -14,11 +14,12 @@ import ( // RevWalk type SortType uint + const ( - SortNone SortType = C.GIT_SORT_NONE - SortTopological = C.GIT_SORT_TOPOLOGICAL - SortTime = C.GIT_SORT_TIME - SortReverse = C.GIT_SORT_REVERSE + SortNone SortType = C.GIT_SORT_NONE + SortTopological = C.GIT_SORT_TOPOLOGICAL + SortTime = C.GIT_SORT_TIME + SortReverse = C.GIT_SORT_REVERSE ) type RevWalk struct { @@ -26,6 +27,12 @@ type RevWalk struct { repo *Repository } +func revWalkFromC(repo *Repository, c *C.git_revwalk) *RevWalk { + v := &RevWalk{ptr: c, repo: repo} + runtime.SetFinalizer(v, (*RevWalk).Free) + return v +} + func (v *RevWalk) Reset() { C.git_revwalk_reset(v.ptr) } @@ -92,6 +99,8 @@ func (v *RevWalk) Sorting(sm SortType) { C.git_revwalk_sorting(v.ptr, C.uint(sm)) } -func freeRevWalk(walk *RevWalk) { - C.git_revwalk_free(walk.ptr) +func (v *RevWalk) Free() { + + runtime.SetFinalizer(v, nil) + C.git_revwalk_free(v.ptr) } diff --git a/wrapper.c b/wrapper.c index 2af3974..4ce4c5c 100644 --- a/wrapper.c +++ b/wrapper.c @@ -24,4 +24,17 @@ int _go_git_odb_foreach(git_odb *db, void *payload) { return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } + +int _go_blob_chunk_cb(char *buffer, size_t maxLen, void *payload) +{ + return blobChunkCb(buffer, maxLen, payload); +} + +int _go_git_blob_create_fromchunks(git_oid *id, + git_repository *repo, + const char *hintpath, + void *payload) +{ + return git_blob_create_fromchunks(id, repo, hintpath, _go_blob_chunk_cb, payload); +} /* EOF */ -- cgit v1.2.3 From d560b9e9bd7162334f7122dadd02cd0a075e22ab Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 13:19:12 -0700 Subject: cleanup clone code --- clone.go | 9 +++---- credentials.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ push.go | 3 --- remote.go | 52 +++++++++++++++----------------------- transport.go | 79 ---------------------------------------------------------- wrapper.c | 5 ---- 6 files changed, 97 insertions(+), 125 deletions(-) create mode 100644 credentials.go delete mode 100644 transport.go (limited to 'wrapper.c') diff --git a/clone.go b/clone.go index 630c343..51dbd65 100644 --- a/clone.go +++ b/clone.go @@ -4,11 +4,6 @@ package git #include #include -static git_clone_options git_clone_options_init() { - git_clone_options ret = GIT_CLONE_OPTIONS_INIT; - return ret; -} - */ import "C" import ( @@ -60,7 +55,9 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) } func populateCloneOptions(ptr *C.git_clone_options, opts *CloneOptions) { - *ptr = C.git_clone_options_init() + ptr = &C.git_clone_options{} + C.git_clone_init_options(ptr, 1) + if opts == nil { return } diff --git a/credentials.go b/credentials.go new file mode 100644 index 0000000..c5ed055 --- /dev/null +++ b/credentials.go @@ -0,0 +1,74 @@ +package git + +/* +#include +#include +*/ +import "C" +import "unsafe" + +type CredType uint + +const ( + CredTypeUserpassPlaintext CredType = C.GIT_CREDTYPE_USERPASS_PLAINTEXT + CredTypeSshKey = C.GIT_CREDTYPE_SSH_KEY + CredTypeSshCustom = C.GIT_CREDTYPE_SSH_CUSTOM + CredTypeDefault = C.GIT_CREDTYPE_DEFAULT +) + +type Cred struct { + ptr *C.git_cred +} + +func (o *Cred) HasUsername() bool { + if C.git_cred_has_username(o.ptr) == 1 { + return true + } + return false +} + +func (o *Cred) Type() CredType { + return (CredType)(o.ptr.credtype) +} + +func credFromC(ptr *C.git_cred) *Cred { + return &Cred{ptr} +} + +func NewCredUserpassPlaintext(username string, password string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpassword := C.CString(password) + defer C.free(unsafe.Pointer(cpassword)) + ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) + return int(ret), cred +} + +func NewCredSshKey(username string, publickey string, privatekey string, passphrase string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + cpublickey := C.CString(publickey) + defer C.free(unsafe.Pointer(cpublickey)) + cprivatekey := C.CString(privatekey) + defer C.free(unsafe.Pointer(cprivatekey)) + cpassphrase := C.CString(passphrase) + defer C.free(unsafe.Pointer(cpassphrase)) + ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) + return int(ret), cred +} + +func NewCredSshKeyFromAgent(username string) (int, Cred) { + cred := Cred{} + cusername := C.CString(username) + defer C.free(unsafe.Pointer(cusername)) + ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) + return int(ret), cred +} + +func NewCredDefault() (int, Cred) { + cred := Cred{} + ret := C.git_cred_default_new(&cred.ptr) + return int(ret), cred +} diff --git a/push.go b/push.go index d1742e3..8b205c7 100644 --- a/push.go +++ b/push.go @@ -59,9 +59,6 @@ func (p *Push) Finish() error { func (p *Push) UnpackOk() bool { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - ret := C.git_push_unpack_ok(p.ptr) if ret == 0 { return false diff --git a/remote.go b/remote.go index 900a314..3621b5f 100644 --- a/remote.go +++ b/remote.go @@ -5,7 +5,6 @@ package git #include extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); -extern git_remote_callbacks _go_git_remote_callbacks_init(); extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); @@ -15,7 +14,22 @@ import "unsafe" import "runtime" type TransferProgress struct { - ptr *C.git_transfer_progress + 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 @@ -28,7 +42,7 @@ const ( 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 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 @@ -45,7 +59,7 @@ type Remote struct { } func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallbacks) { - *ptr = C._go_git_remote_callbacks_init() + C.git_remote_init_callbacks(ptr, C.GIT_REMOTE_CALLBACKS_VERSION) if callbacks == nil { return } @@ -81,9 +95,7 @@ func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C url := C.GoString(_url) username_from_url := C.GoString(_username_from_url) ret, cred := callbacks.CredentialsCallback(url, username_from_url, (CredType)(allowed_types)) - if gcred, ok := cred.(gitCred); ok { - *_cred = gcred.ptr - } + *_cred = cred.ptr return ret } @@ -93,7 +105,7 @@ func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointe if callbacks.TransferProgressCallback == nil { return 0 } - return callbacks.TransferProgressCallback(TransferProgress{stats}) + return callbacks.TransferProgressCallback(newTransferProgressFromC(stats)) } //export updateTipsCallback @@ -108,30 +120,6 @@ func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data uns return callbacks.UpdateTipsCallback(refname, a, b) } -func (o TransferProgress) TotalObjects() uint { - return uint(o.ptr.total_objects) -} - -func (o TransferProgress) IndexedObjects() uint { - return uint(o.ptr.indexed_objects) -} - -func (o TransferProgress) ReceivedObjects() uint { - return uint(o.ptr.received_objects) -} - -func (o TransferProgress) LocalObjects() uint { - return uint(o.ptr.local_objects) -} - -func (o TransferProgress) TotalDeltas() uint { - return uint(o.ptr.total_deltas) -} - -func (o TransferProgress) ReceivedBytes() uint { - return uint(o.ptr.received_bytes) -} - func RemoteIsValidName(name string) bool { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) diff --git a/transport.go b/transport.go deleted file mode 100644 index e97a70c..0000000 --- a/transport.go +++ /dev/null @@ -1,79 +0,0 @@ -package git - -/* -#include -#include -*/ -import "C" -import "unsafe" - -type CredType uint -const ( - CredTypeUserpassPlaintext CredType = C.GIT_CREDTYPE_USERPASS_PLAINTEXT - CredTypeSshKey = C.GIT_CREDTYPE_SSH_KEY - CredTypeSshCustom = C.GIT_CREDTYPE_SSH_CUSTOM - CredTypeDefault = C.GIT_CREDTYPE_DEFAULT -) - -type Cred interface { - HasUsername() bool - Type() CredType -} - -type gitCred struct { - ptr *C.git_cred -} - -func (o gitCred) HasUsername() bool { - if C.git_cred_has_username(o.ptr) == 1 { - return true - } - return false -} - -func (o gitCred) Type() CredType { - return (CredType)(o.ptr.credtype); -} - -func credFromC(ptr *C.git_cred) Cred { - return gitCred{ptr} -} - -func NewCredUserpassPlaintext(username string, password string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - cpassword := C.CString(password) - defer C.free(unsafe.Pointer(cpassword)) - ret := C.git_cred_userpass_plaintext_new(&cred.ptr, cusername, cpassword) - return int(ret), cred -} - -func NewCredSshKey(username string, publickey string, privatekey string, passphrase string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - cpublickey := C.CString(publickey) - defer C.free(unsafe.Pointer(cpublickey)) - cprivatekey := C.CString(privatekey) - defer C.free(unsafe.Pointer(cprivatekey)) - cpassphrase := C.CString(passphrase) - defer C.free(unsafe.Pointer(cpassphrase)) - ret := C.git_cred_ssh_key_new(&cred.ptr, cusername, cpublickey, cprivatekey, cpassphrase) - return int(ret), cred -} - -func NewCredSshKeyFromAgent(username string) (int, Cred) { - cred := gitCred{} - cusername := C.CString(username) - defer C.free(unsafe.Pointer(cusername)) - ret := C.git_cred_ssh_key_from_agent(&cred.ptr, cusername) - return int(ret), cred -} - -func NewCredDefault() (int, Cred) { - cred := gitCred{} - ret := C.git_cred_default_new(&cred.ptr) - return int(ret), cred -} - diff --git a/wrapper.c b/wrapper.c index 8e337df..bc69cd5 100644 --- a/wrapper.c +++ b/wrapper.c @@ -38,11 +38,6 @@ void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } -git_remote_callbacks _go_git_remote_callbacks_init() { - git_remote_callbacks ret = GIT_REMOTE_CALLBACKS_INIT; - return ret; -} - void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { array->strings[n] = str; } -- cgit v1.2.3 From 51aa76d6f7170bba60ab2252b74a3cab0276996f Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Tue, 11 Mar 2014 16:25:22 -0700 Subject: remove strarray wrappers --- remote.go | 48 +++++++++++++++++++++++++++++------------------- wrapper.c | 8 -------- 2 files changed, 29 insertions(+), 27 deletions(-) (limited to 'wrapper.c') diff --git a/remote.go b/remote.go index 3621b5f..da688e7 100644 --- a/remote.go +++ b/remote.go @@ -5,8 +5,6 @@ package git #include extern void _go_git_setup_callbacks(git_remote_callbacks *callbacks); -extern void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n); -extern char *_go_git_get_strarray_n(git_strarray *array, size_t n); */ import "C" @@ -280,6 +278,31 @@ func (o *Remote) AddFetch(refspec string) error { 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 (o *Remote) GetFetchRefspecs() ([]string, error) { crefspecs := C.git_strarray{} @@ -291,21 +314,15 @@ func (o *Remote) GetFetchRefspecs() ([]string, error) { return nil, MakeGitError(ret) } defer C.git_strarray_free(&crefspecs) - refspecs := make([]string, crefspecs.count) - for i := 0; i < int(crefspecs.count); i++ { - refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) - } + 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 = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) - for i, refspec := range refspecs { - C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) - } + crefspecs.strings = makeCStringsFromStrings(refspecs) defer C.git_strarray_free(&crefspecs) runtime.LockOSThread() @@ -343,21 +360,14 @@ func (o *Remote) GetPushRefspecs() ([]string, error) { return nil, MakeGitError(ret) } defer C.git_strarray_free(&crefspecs) - refspecs := make([]string, crefspecs.count) - - for i := 0; i < int(crefspecs.count); i++ { - refspecs[i] = C.GoString(C._go_git_get_strarray_n(&crefspecs, C.size_t(i))) - } + 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 = (**C.char)(C.malloc(C.size_t(unsafe.Sizeof(unsafe.Pointer(nil)) * uintptr(crefspecs.count)))) - for i, refspec := range refspecs { - C._go_git_set_strarray_n(&crefspecs, C.CString(refspec), C.size_t(i)) - } + crefspecs.strings = makeCStringsFromStrings(refspecs) defer C.git_strarray_free(&crefspecs) runtime.LockOSThread() diff --git a/wrapper.c b/wrapper.c index bc69cd5..0fa6c48 100644 --- a/wrapper.c +++ b/wrapper.c @@ -38,14 +38,6 @@ void _go_git_setup_callbacks(git_remote_callbacks *callbacks) { callbacks->update_tips = (update_tips_cb)updateTipsCallback; } -void _go_git_set_strarray_n(git_strarray *array, char *str, size_t n) { - array->strings[n] = str; -} - -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) -- cgit v1.2.3