summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <[email protected]>2015-06-05 02:02:37 +0200
committerCarlos Martín Nieto <[email protected]>2015-06-08 04:07:49 +0200
commit85fde1fcfbc3fd6000b8fa1a4041b4c314a92b2f (patch)
tree80b29ec86120ba092fcd05c05e28e6a65d1f2b13
parent1011b03e4139580679bb93183a781edd11c22a97 (diff)
parent53c158fbd7e5f4dac787f5c3a7107fcb4116f676 (diff)
Merge remote-tracking branch 'origin/master' into next
-rw-r--r--.travis.yml10
-rw-r--r--blame_test.go4
-rw-r--r--blob.go15
-rw-r--r--blob_test.go3
-rw-r--r--branch_test.go8
-rw-r--r--checkout.go11
-rw-r--r--cherrypick_test.go2
-rw-r--r--clone_test.go7
-rw-r--r--commit.go38
-rw-r--r--diff.go97
-rw-r--r--diff_test.go7
-rw-r--r--git.go4
-rw-r--r--git_test.go13
-rw-r--r--handles.go84
-rw-r--r--index.go67
-rw-r--r--index_test.go74
-rw-r--r--merge_test.go11
-rw-r--r--note_test.go10
-rw-r--r--object_test.go7
-rw-r--r--odb.go13
-rw-r--r--odb_test.go12
-rw-r--r--packbuilder.go13
-rw-r--r--patch_test.go3
-rw-r--r--push_test.go6
-rw-r--r--reference_test.go13
-rw-r--r--remote_test.go28
-rw-r--r--revparse_test.go7
-rw-r--r--status_test.go8
-rw-r--r--submodule.go15
-rw-r--r--submodule_test.go4
-rw-r--r--tag_test.go4
-rw-r--r--tree.go16
32 files changed, 488 insertions, 126 deletions
diff --git a/.travis.yml b/.travis.yml
index f84d07e..f8b7e93 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,19 @@
language: go
+install:
+ - cd "${HOME}"
+ - wget -O libgit2-0.22.1.tar.gz https://github.com/libgit2/libgit2/archive/v0.22.1.tar.gz
+ - tar -xzvf libgit2-0.22.1.tar.gz
+ - cd libgit2-0.22.1 && mkdir build && cd build
+ - cmake -DTHREADSAFE=ON -DBUILD_CLAR=OFF -DCMAKE_C_FLAGS=-fPIC -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DCMAKE_INSTALL_PREFIX=/usr/local .. && make && sudo make install
+ - sudo ldconfig
+ - cd "${TRAVIS_BUILD_DIR}"
+
go:
- 1.1
- 1.2
- 1.3
+ - 1.4
- tip
matrix:
diff --git a/blame_test.go b/blame_test.go
index 1785042..a2a4d38 100644
--- a/blame_test.go
+++ b/blame_test.go
@@ -1,15 +1,13 @@
package git
import (
- "os"
"reflect"
"testing"
)
func TestBlame(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId1, _ := seedTestRepo(t, repo)
commitId2, _ := updateReadme(t, repo, "foo\nbar\nbaz\n")
diff --git a/blob.go b/blob.go
index 5a33bd8..b1fc78a 100644
--- a/blob.go
+++ b/blob.go
@@ -60,8 +60,13 @@ type BlobCallbackData struct {
}
//export blobChunkCb
-func blobChunkCb(buffer *C.char, maxLen C.size_t, payload unsafe.Pointer) int {
- data := (*BlobCallbackData)(payload)
+func blobChunkCb(buffer *C.char, maxLen C.size_t, handle unsafe.Pointer) int {
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*BlobCallbackData)
+ if !ok {
+ panic("could not retrieve blob callback data")
+ }
+
goBuf, err := data.Callback(int(maxLen))
if err == io.EOF {
return 0
@@ -83,8 +88,12 @@ func (repo *Repository) CreateBlobFromChunks(hintPath string, callback BlobChunk
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))
+ handle := pointerHandles.Track(payload)
+ defer pointerHandles.Untrack(handle)
+
+ ecode := C._go_git_blob_create_fromchunks(&oid, repo.ptr, chintPath, handle)
if payload.Error != nil {
return nil, payload.Error
}
diff --git a/blob_test.go b/blob_test.go
index e075192..2b5ec4f 100644
--- a/blob_test.go
+++ b/blob_test.go
@@ -1,13 +1,12 @@
package git
import (
- "os"
"testing"
)
func TestCreateBlobFromBuffer(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
id, err := repo.CreateBlobFromBuffer(make([]byte, 0))
checkFatal(t, err)
diff --git a/branch_test.go b/branch_test.go
index 09ebeba..a0834a8 100644
--- a/branch_test.go
+++ b/branch_test.go
@@ -1,9 +1,13 @@
package git
-import "testing"
+import (
+ "testing"
+)
func TestBranchIterator(t *testing.T) {
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
i, err := repo.NewBranchIterator(BranchLocal)
@@ -24,6 +28,8 @@ func TestBranchIterator(t *testing.T) {
func TestBranchIteratorEach(t *testing.T) {
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
i, err := repo.NewBranchIterator(BranchLocal)
diff --git a/checkout.go b/checkout.go
index 98c1ee6..d747344 100644
--- a/checkout.go
+++ b/checkout.go
@@ -43,6 +43,7 @@ type CheckoutOpts struct {
FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob
FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY
TargetDirectory string // Alternative checkout path to workdir
+ Paths []string
}
func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts {
@@ -83,6 +84,11 @@ func populateCheckoutOpts(ptr *C.git_checkout_options, opts *CheckoutOpts) *C.gi
if opts.TargetDirectory != "" {
ptr.target_directory = C.CString(opts.TargetDirectory)
}
+ if len(opts.Paths) > 0 {
+ ptr.paths.strings = makeCStringsFromStrings(opts.Paths)
+ ptr.paths.count = C.size_t(len(opts.Paths))
+ }
+
return ptr
}
@@ -91,6 +97,9 @@ func freeCheckoutOpts(ptr *C.git_checkout_options) {
return
}
C.free(unsafe.Pointer(ptr.target_directory))
+ if ptr.paths.count > 0 {
+ freeStrarray(&ptr.paths)
+ }
}
// Updates files in the index and the working tree to match the content of
@@ -146,4 +155,4 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error {
}
return nil
-}
+} \ No newline at end of file
diff --git a/cherrypick_test.go b/cherrypick_test.go
index 141a55d..a3246bd 100644
--- a/cherrypick_test.go
+++ b/cherrypick_test.go
@@ -34,6 +34,8 @@ func readReadme(t *testing.T, repo *Repository) string {
func TestCherrypick(t *testing.T) {
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
c1, _ := seedTestRepo(t, repo)
c2, _ := updateReadme(t, repo, content)
diff --git a/clone_test.go b/clone_test.go
index 97366bf..fd83fec 100644
--- a/clone_test.go
+++ b/clone_test.go
@@ -2,22 +2,21 @@ package git
import (
"io/ioutil"
- "os"
"testing"
)
func TestClone(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
seedTestRepo(t, repo)
path, err := ioutil.TempDir("", "git2go")
checkFatal(t, err)
- _, err = Clone(repo.Path(), path, &CloneOptions{Bare: true})
- defer os.RemoveAll(path)
+ repo2, err := Clone(repo.Path(), path, &CloneOptions{Bare: true})
+ defer cleanupTestRepo(t, repo2)
checkFatal(t, err)
}
diff --git a/commit.go b/commit.go
index 57e1a77..52f7c01 100644
--- a/commit.go
+++ b/commit.go
@@ -9,6 +9,7 @@ import "C"
import (
"runtime"
+ "unsafe"
)
// Commit
@@ -70,3 +71,40 @@ func (c *Commit) ParentId(n uint) *Oid {
func (c *Commit) ParentCount() uint {
return uint(C.git_commit_parentcount(c.cast_ptr))
}
+
+func (c *Commit) Amend(refname string, author, committer *Signature, message string, tree *Tree) (*Oid, error) {
+ var cref *C.char
+ if refname == "" {
+ cref = nil
+ } else {
+ cref = C.CString(refname)
+ defer C.free(unsafe.Pointer(cref))
+ }
+
+ cmsg := C.CString(message)
+ defer C.free(unsafe.Pointer(cmsg))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ authorSig, err := author.toC()
+ if err != nil {
+ return nil, err
+ }
+ defer C.git_signature_free(authorSig)
+
+ committerSig, err := committer.toC()
+ if err != nil {
+ return nil, err
+ }
+ defer C.git_signature_free(committerSig)
+
+ oid := new(Oid)
+
+ cerr := C.git_commit_amend(oid.toC(), c.cast_ptr, cref, authorSig, committerSig, nil, cmsg, tree.cast_ptr)
+ if cerr < 0 {
+ return nil, MakeGitError(cerr)
+ }
+
+ return oid, nil
+}
diff --git a/diff.go b/diff.go
index 63fa867..5e03175 100644
--- a/diff.go
+++ b/diff.go
@@ -265,7 +265,11 @@ func (diff *Diff) ForEach(cbFile DiffForEachFileCallback, detail DiffDetail) err
data := &diffForEachData{
FileCallback: cbFile,
}
- ecode := C._go_git_diff_foreach(diff.ptr, 1, intHunks, intLines, unsafe.Pointer(data))
+
+ handle := pointerHandles.Track(data)
+ defer pointerHandles.Untrack(handle)
+
+ ecode := C._go_git_diff_foreach(diff.ptr, 1, intHunks, intLines, handle)
if ecode < 0 {
return data.Error
}
@@ -273,8 +277,12 @@ func (diff *Diff) ForEach(cbFile DiffForEachFileCallback, detail DiffDetail) err
}
//export diffForEachFileCb
-func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, payload unsafe.Pointer) int {
- data := (*diffForEachData)(payload)
+func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, handle unsafe.Pointer) int {
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*diffForEachData)
+ if !ok {
+ panic("could not retrieve data for handle")
+ }
data.HunkCallback = nil
if data.FileCallback != nil {
@@ -292,8 +300,12 @@ func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, payload unsafe
type DiffForEachHunkCallback func(DiffHunk) (DiffForEachLineCallback, error)
//export diffForEachHunkCb
-func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload unsafe.Pointer) int {
- data := (*diffForEachData)(payload)
+func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, handle unsafe.Pointer) int {
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*diffForEachData)
+ if !ok {
+ panic("could not retrieve data for handle")
+ }
data.LineCallback = nil
if data.HunkCallback != nil {
@@ -311,9 +323,12 @@ func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload u
type DiffForEachLineCallback func(DiffLine) error
//export diffForEachLineCb
-func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, payload unsafe.Pointer) int {
-
- data := (*diffForEachData)(payload)
+func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, handle unsafe.Pointer) int {
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*diffForEachData)
+ if !ok {
+ panic("could not retrieve data for handle")
+ }
err := data.LineCallback(diffLineFromC(delta, hunk, line))
if err != nil {
@@ -479,9 +494,15 @@ type diffNotifyData struct {
}
//export diffNotifyCb
-func diffNotifyCb(_diff_so_far unsafe.Pointer, delta_to_add *C.git_diff_delta, matched_pathspec *C.char, payload unsafe.Pointer) int {
+func diffNotifyCb(_diff_so_far unsafe.Pointer, delta_to_add *C.git_diff_delta, matched_pathspec *C.char, handle unsafe.Pointer) int {
diff_so_far := (*C.git_diff)(_diff_so_far)
- data := (*diffNotifyData)(payload)
+
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*diffNotifyData)
+ if !ok {
+ panic("could not retrieve data for handle")
+ }
+
if data != nil {
if data.Diff == nil {
data.Diff = newDiffFromC(diff_so_far)
@@ -507,6 +528,7 @@ func diffOptionsToC(opts *DiffOptions) (copts *C.git_diff_options, notifyData *d
notifyData = &diffNotifyData{
Callback: opts.NotifyCallback,
}
+
if opts.Pathspec != nil {
cpathspec.count = C.size_t(len(opts.Pathspec))
cpathspec.strings = makeCStringsFromStrings(opts.Pathspec)
@@ -527,7 +549,7 @@ func diffOptionsToC(opts *DiffOptions) (copts *C.git_diff_options, notifyData *d
if opts.NotifyCallback != nil {
C._go_git_setup_diff_notify_callbacks(copts)
- copts.notify_payload = unsafe.Pointer(notifyData)
+ copts.notify_payload = pointerHandles.Track(notifyData)
}
}
return
@@ -539,6 +561,9 @@ func freeDiffOptions(copts *C.git_diff_options) {
freeStrarray(&cpathspec)
C.free(unsafe.Pointer(copts.old_prefix))
C.free(unsafe.Pointer(copts.new_prefix))
+ if copts.notify_payload != nil {
+ pointerHandles.Untrack(copts.notify_payload)
+ }
}
}
@@ -595,3 +620,53 @@ func (v *Repository) DiffTreeToWorkdir(oldTree *Tree, opts *DiffOptions) (*Diff,
}
return newDiffFromC(diffPtr), nil
}
+
+func (v *Repository) DiffTreeToWorkdirWithIndex(oldTree *Tree, opts *DiffOptions) (*Diff, error) {
+ var diffPtr *C.git_diff
+ var oldPtr *C.git_tree
+
+ if oldTree != nil {
+ oldPtr = oldTree.cast_ptr
+ }
+
+ copts, notifyData := diffOptionsToC(opts)
+ defer freeDiffOptions(copts)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_diff_tree_to_workdir_with_index(&diffPtr, v.ptr, oldPtr, copts)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ if notifyData != nil && notifyData.Diff != nil {
+ return notifyData.Diff, nil
+ }
+ return newDiffFromC(diffPtr), nil
+}
+
+func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, error) {
+ var diffPtr *C.git_diff
+ var indexPtr *C.git_index
+
+ if index != nil {
+ indexPtr = index.ptr
+ }
+
+ copts, notifyData := diffOptionsToC(opts)
+ defer freeDiffOptions(copts)
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_diff_index_to_workdir(&diffPtr, v.ptr, indexPtr, copts)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ if notifyData != nil && notifyData.Diff != nil {
+ return notifyData.Diff, nil
+ }
+ return newDiffFromC(diffPtr), nil
+}
diff --git a/diff_test.go b/diff_test.go
index fc6fed9..464fae6 100644
--- a/diff_test.go
+++ b/diff_test.go
@@ -2,15 +2,13 @@ package git
import (
"errors"
- "os"
"strings"
"testing"
)
func TestFindSimilar(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
originalTree, newTree := createTestTrees(t, repo)
@@ -65,8 +63,7 @@ func TestFindSimilar(t *testing.T) {
func TestDiffTreeToTree(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
originalTree, newTree := createTestTrees(t, repo)
diff --git a/git.go b/git.go
index 8e78710..5f69837 100644
--- a/git.go
+++ b/git.go
@@ -92,7 +92,11 @@ var (
ErrInvalid = errors.New("Invalid state for operation")
)
+var pointerHandles *HandleList
+
func init() {
+ pointerHandles = NewHandleList()
+
C.git_libgit2_init()
// This is not something we should be doing, as we may be
diff --git a/git_test.go b/git_test.go
index b9cf0a9..58caf71 100644
--- a/git_test.go
+++ b/git_test.go
@@ -2,11 +2,24 @@ package git
import (
"io/ioutil"
+ "os"
"path"
"testing"
"time"
)
+func cleanupTestRepo(t *testing.T, r *Repository) {
+ var err error
+ if r.IsBare() {
+ err = os.RemoveAll(r.Path())
+ } else {
+ err = os.RemoveAll(r.Workdir())
+ }
+ checkFatal(t, err)
+
+ r.Free()
+}
+
func createTestRepo(t *testing.T) *Repository {
// figure out where we can create the test repo
path, err := ioutil.TempDir("", "git2go")
diff --git a/handles.go b/handles.go
new file mode 100644
index 0000000..ec62a48
--- /dev/null
+++ b/handles.go
@@ -0,0 +1,84 @@
+package git
+
+import (
+ "fmt"
+ "sync"
+ "unsafe"
+)
+
+type HandleList struct {
+ sync.RWMutex
+ // stores the Go pointers
+ handles []interface{}
+ // indicates which indices are in use
+ set map[int]bool
+}
+
+func NewHandleList() *HandleList {
+ return &HandleList{
+ handles: make([]interface{}, 5),
+ set: make(map[int]bool),
+ }
+}
+
+// findUnusedSlot finds the smallest-index empty space in our
+// list. You must only run this function while holding a write lock.
+func (v *HandleList) findUnusedSlot() int {
+ for i := 1; i < len(v.handles); i++ {
+ isUsed := v.set[i]
+ if !isUsed {
+ return i
+ }
+ }
+
+ // reaching here means we've run out of entries so append and
+ // return the new index, which is equal to the old length.
+ slot := len(v.handles)
+ v.handles = append(v.handles, nil)
+
+ return slot
+}
+
+// Track adds the given pointer to the list of pointers to track and
+// returns a pointer value which can be passed to C as an opaque
+// pointer.
+func (v *HandleList) Track(pointer interface{}) unsafe.Pointer {
+ v.Lock()
+
+ slot := v.findUnusedSlot()
+ v.handles[slot] = pointer
+ v.set[slot] = true
+
+ v.Unlock()
+
+ return unsafe.Pointer(&slot)
+}
+
+// Untrack stops tracking the pointer given by the handle
+func (v *HandleList) Untrack(handle unsafe.Pointer) {
+ slot := *(*int)(handle)
+
+ v.Lock()
+
+ v.handles[slot] = nil
+ delete(v.set, slot)
+
+ v.Unlock()
+}
+
+// Get retrieves the pointer from the given handle
+func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
+ slot := *(*int)(handle)
+
+ v.RLock()
+
+ if _, ok := v.set[slot]; !ok {
+ panic(fmt.Sprintf("invalid pointer handle: %p", handle))
+ }
+
+ ptr := v.handles[slot]
+
+ v.RUnlock()
+
+ return ptr
+}
diff --git a/index.go b/index.go
index 6b90758..c1bfb74 100644
--- a/index.go
+++ b/index.go
@@ -96,6 +96,30 @@ func NewIndex() (*Index, error) {
return &Index{ptr: ptr}, nil
}
+// OpenIndex creates a new index at the given path. If the file does
+// not exist it will be created when Write() is called.
+func OpenIndex(path string) (*Index, error) {
+ var ptr *C.git_index
+
+ var cpath = C.CString(path)
+ defer C.free(unsafe.Pointer(cpath))
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ if err := C.git_index_open(&ptr, cpath); err < 0 {
+ return nil, MakeGitError(err)
+ }
+
+ return &Index{ptr: ptr}, nil
+}
+
+// Path returns the index' path on disk or an empty string if it
+// exists only in memory.
+func (v *Index) Path() string {
+ return C.GoString(C.git_index_path(v.ptr))
+}
+
// Add adds or replaces the given entry to the index, making a copy of
// the data
func (v *Index) Add(entry *IndexEntry) error {
@@ -138,16 +162,17 @@ func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMat
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- var cb *IndexMatchedPathCallback
+ var handle unsafe.Pointer
if callback != nil {
- cb = &callback
+ handle = pointerHandles.Track(callback)
+ defer pointerHandles.Untrack(handle)
}
ret := C._go_git_index_add_all(
v.ptr,
&cpathspecs,
C.uint(flags),
- unsafe.Pointer(cb),
+ handle,
)
if ret < 0 {
return MakeGitError(ret)
@@ -164,15 +189,16 @@ func (v *Index) UpdateAll(pathspecs []string, callback IndexMatchedPathCallback)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- var cb *IndexMatchedPathCallback
+ var handle unsafe.Pointer
if callback != nil {
- cb = &callback
+ handle = pointerHandles.Track(callback)
+ defer pointerHandles.Untrack(handle)
}
ret := C._go_git_index_update_all(
v.ptr,
&cpathspecs,
- unsafe.Pointer(cb),
+ handle,
)
if ret < 0 {
return MakeGitError(ret)
@@ -189,15 +215,16 @@ func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- var cb *IndexMatchedPathCallback
+ var handle unsafe.Pointer
if callback != nil {
- cb = &callback
+ handle = pointerHandles.Track(callback)
+ defer pointerHandles.Untrack(handle)
}
ret := C._go_git_index_remove_all(
v.ptr,
&cpathspecs,
- unsafe.Pointer(cb),
+ handle,
)
if ret < 0 {
return MakeGitError(ret)
@@ -207,8 +234,11 @@ func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback)
//export indexMatchedPathCallback
func indexMatchedPathCallback(cPath, cMatchedPathspec *C.char, payload unsafe.Pointer) int {
- callback := (*IndexMatchedPathCallback)(payload)
- return (*callback)(C.GoString(cPath), C.GoString(cMatchedPathspec))
+ if callback, ok := pointerHandles.Get(payload).(IndexMatchedPathCallback); ok {
+ return callback(C.GoString(cPath), C.GoString(cMatchedPathspec))
+ } else {
+ panic("invalid matched path callback")
+ }
}
func (v *Index) RemoveByPath(path string) error {
@@ -240,6 +270,20 @@ func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) {
return oid, nil
}
+// ReadTree replaces the contents of the index with those of the given
+// tree
+func (v *Index) ReadTree(tree *Tree) error {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ret := C.git_index_read_tree(v.ptr, tree.cast_ptr);
+ if ret < 0 {
+ return MakeGitError(ret)
+ }
+
+ return nil
+}
+
func (v *Index) WriteTree() (*Oid, error) {
oid := new(Oid)
@@ -287,6 +331,7 @@ func (v *Index) HasConflicts() bool {
return C.git_index_has_conflicts(v.ptr) != 0
}
+// FIXME: this might return an error
func (v *Index) CleanupConflicts() {
C.git_index_conflict_cleanup(v.ptr)
}
diff --git a/index_test.go b/index_test.go
index 98d9a31..7c65f4f 100644
--- a/index_test.go
+++ b/index_test.go
@@ -9,7 +9,7 @@ import (
func TestCreateRepoAndStage(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
idx, err := repo.Index()
checkFatal(t, err)
@@ -23,12 +23,40 @@ func TestCreateRepoAndStage(t *testing.T) {
}
}
+func TestIndexReadTree(t *testing.T) {
+ repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
+ _, _ = seedTestRepo(t, repo)
+
+ ref, err := repo.Head()
+ checkFatal(t, err)
+
+ obj, err := ref.Peel(ObjectTree);
+ checkFatal(t, err)
+
+ tree := obj.(*Tree)
+
+ idx, err := NewIndex()
+ checkFatal(t, err)
+
+ err = idx.ReadTree(tree)
+ checkFatal(t, err)
+
+ id, err := idx.WriteTreeTo(repo)
+ checkFatal(t, err)
+
+ if tree.Id().Cmp(id) != 0 {
+ t.Fatalf("Read and written trees are not the same")
+ }
+}
+
func TestIndexWriteTreeTo(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
repo2 := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo2)
idx, err := repo.Index()
checkFatal(t, err)
@@ -44,7 +72,7 @@ func TestIndexWriteTreeTo(t *testing.T) {
func TestIndexAddAndWriteTreeTo(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
odb, err := repo.Odb()
checkFatal(t, err)
@@ -55,6 +83,10 @@ func TestIndexAddAndWriteTreeTo(t *testing.T) {
idx, err := NewIndex()
checkFatal(t, err)
+ if idx.Path() != "" {
+ t.Fatal("in-memory repo has a path")
+ }
+
entry := IndexEntry{
Path: "README",
Id: blobID,
@@ -74,7 +106,7 @@ func TestIndexAddAndWriteTreeTo(t *testing.T) {
func TestIndexAddAllNoCallback(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
err := ioutil.WriteFile(repo.Workdir()+"/README", []byte("foo\n"), 0644)
checkFatal(t, err)
@@ -95,7 +127,7 @@ func TestIndexAddAllNoCallback(t *testing.T) {
func TestIndexAddAllCallback(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
err := ioutil.WriteFile(repo.Workdir()+"/README", []byte("foo\n"), 0644)
checkFatal(t, err)
@@ -121,6 +153,33 @@ func TestIndexAddAllCallback(t *testing.T) {
}
}
+func TestIndexOpen(t *testing.T) {
+ repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
+ path := repo.Workdir() + "/heyindex"
+
+ _, err := os.Stat(path)
+ if !os.IsNotExist(err) {
+ t.Fatal("new index file already exists")
+ }
+
+ idx, err := OpenIndex(path)
+ checkFatal(t, err)
+
+ if path != idx.Path() {
+ t.Fatalf("mismatched index paths, expected %v, got %v", path, idx.Path())
+ }
+
+ err = idx.Write()
+ checkFatal(t, err)
+
+ _, err = os.Stat(path)
+ if os.IsNotExist(err) {
+ t.Fatal("new index file did not get written")
+ }
+}
+
func checkFatal(t *testing.T, err error) {
if err == nil {
return
@@ -129,8 +188,7 @@ func checkFatal(t *testing.T, err error) {
// The failure happens at wherever we were called, not here
_, file, line, ok := runtime.Caller(1)
if !ok {
- t.Fatal()
+ t.Fatalf("Unable to get caller")
}
-
t.Fatalf("Fail at %v:%v; %v", file, line, err)
}
diff --git a/merge_test.go b/merge_test.go
index 1eba806..0b1faca 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -1,13 +1,13 @@
package git
import (
- "os"
"testing"
)
func TestMergeWithSelf(t *testing.T) {
-
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
master, err := repo.LookupReference("refs/heads/master")
@@ -23,8 +23,9 @@ func TestMergeWithSelf(t *testing.T) {
}
func TestMergeAnalysisWithSelf(t *testing.T) {
-
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
master, err := repo.LookupReference("refs/heads/master")
@@ -44,7 +45,6 @@ func TestMergeAnalysisWithSelf(t *testing.T) {
}
func TestMergeSameFile(t *testing.T) {
-
file := MergeFileInput{
Path: "test",
Mode: 33188,
@@ -68,8 +68,7 @@ func TestMergeSameFile(t *testing.T) {
}
func TestMergeTreesWithoutAncestor(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
_, originalTreeId := seedTestRepo(t, repo)
originalTree, err := repo.LookupTree(originalTreeId)
diff --git a/note_test.go b/note_test.go
index f5e9c01..e6c378d 100644
--- a/note_test.go
+++ b/note_test.go
@@ -2,7 +2,6 @@ package git
import (
"fmt"
- "os"
"reflect"
"testing"
"time"
@@ -10,7 +9,7 @@ import (
func TestCreateNote(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, _ := seedTestRepo(t, repo)
@@ -29,7 +28,8 @@ func TestCreateNote(t *testing.T) {
func TestNoteIterator(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
notes := make([]*Note, 5)
@@ -64,7 +64,7 @@ func TestNoteIterator(t *testing.T) {
func TestRemoveNote(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, _ := seedTestRepo(t, repo)
@@ -87,7 +87,7 @@ func TestRemoveNote(t *testing.T) {
func TestDefaultNoteRef(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
ref, err := repo.DefaultNoteRef()
checkFatal(t, err)
diff --git a/object_test.go b/object_test.go
index f525351..aa295e5 100644
--- a/object_test.go
+++ b/object_test.go
@@ -1,13 +1,13 @@
package git
import (
- "os"
"testing"
)
func TestObjectPoymorphism(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
commitId, treeId := seedTestRepo(t, repo)
var obj Object
@@ -89,7 +89,8 @@ func checkOwner(t *testing.T, repo *Repository, obj Object) {
func TestObjectOwner(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
commitId, treeId := seedTestRepo(t, repo)
commit, err := repo.LookupCommit(commitId)
diff --git a/odb.go b/odb.go
index ba03860..6b21329 100644
--- a/odb.go
+++ b/odb.go
@@ -98,8 +98,12 @@ type foreachData struct {
}
//export odbForEachCb
-func odbForEachCb(id *C.git_oid, payload unsafe.Pointer) int {
- data := (*foreachData)(payload)
+func odbForEachCb(id *C.git_oid, handle unsafe.Pointer) int {
+ data, ok := pointerHandles.Get(handle).(*foreachData)
+
+ if !ok {
+ panic("could not retrieve handle")
+ }
err := data.callback(newOidFromC(id))
if err != nil {
@@ -119,7 +123,10 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C._go_git_odb_foreach(v.ptr, unsafe.Pointer(&data))
+ handle := pointerHandles.Track(&data)
+ defer pointerHandles.Untrack(handle)
+
+ ret := C._go_git_odb_foreach(v.ptr, handle)
if ret == C.GIT_EUSER {
return data.err
} else if ret < 0 {
diff --git a/odb_test.go b/odb_test.go
index 5e6b7ff..2fb6840 100644
--- a/odb_test.go
+++ b/odb_test.go
@@ -3,13 +3,13 @@ package git
import (
"errors"
"io"
- "os"
"testing"
)
func TestOdbStream(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
_, _ = seedTestRepo(t, repo)
odb, error := repo.Odb()
@@ -38,7 +38,8 @@ func TestOdbStream(t *testing.T) {
func TestOdbHash(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
_, _ = seedTestRepo(t, repo)
odb, error := repo.Odb()
@@ -64,7 +65,8 @@ Initial commit.`
func TestOdbForeach(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
_, _ = seedTestRepo(t, repo)
odb, err := repo.Odb()
@@ -79,7 +81,7 @@ func TestOdbForeach(t *testing.T) {
checkFatal(t, err)
if count != expect {
- t.Fatalf("Expected %v objects, got %v")
+ t.Fatalf("Expected %v objects, got %v", expect, count)
}
expect = 1
diff --git a/packbuilder.go b/packbuilder.go
index 54a8390..4dc352c 100644
--- a/packbuilder.go
+++ b/packbuilder.go
@@ -110,8 +110,13 @@ type packbuilderCbData struct {
}
//export packbuilderForEachCb
-func packbuilderForEachCb(buf unsafe.Pointer, size C.size_t, payload unsafe.Pointer) int {
- data := (*packbuilderCbData)(payload)
+func packbuilderForEachCb(buf unsafe.Pointer, size C.size_t, handle unsafe.Pointer) int {
+ payload := pointerHandles.Get(handle)
+ data, ok := payload.(*packbuilderCbData)
+ if !ok {
+ panic("could not get packbuilder CB data")
+ }
+
slice := C.GoBytes(buf, C.int(size))
err := data.callback(slice)
@@ -130,11 +135,13 @@ func (pb *Packbuilder) ForEach(callback PackbuilderForeachCallback) error {
callback: callback,
err: nil,
}
+ handle := pointerHandles.Track(&data)
+ defer pointerHandles.Untrack(handle)
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- err := C._go_git_packbuilder_foreach(pb.ptr, unsafe.Pointer(&data))
+ err := C._go_git_packbuilder_foreach(pb.ptr, handle)
if err == C.GIT_EUSER {
return data.err
}
diff --git a/patch_test.go b/patch_test.go
index a061142..2d52fb4 100644
--- a/patch_test.go
+++ b/patch_test.go
@@ -7,8 +7,7 @@ import (
func TestPatch(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- //defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
_, originalTreeId := seedTestRepo(t, repo)
originalTree, err := repo.LookupTree(originalTreeId)
diff --git a/push_test.go b/push_test.go
index ad72e4d..4686c65 100644
--- a/push_test.go
+++ b/push_test.go
@@ -1,15 +1,15 @@
package git
import (
- "os"
"testing"
)
func TestRemotePush(t *testing.T) {
repo := createBareTestRepo(t)
- defer os.RemoveAll(repo.Path())
+ defer cleanupTestRepo(t, repo)
+
localRepo := createTestRepo(t)
- defer os.RemoveAll(localRepo.Workdir())
+ defer cleanupTestRepo(t, localRepo)
remote, err := localRepo.CreateRemote("test_push", repo.Path())
checkFatal(t, err)
diff --git a/reference_test.go b/reference_test.go
index 562e276..e891e7a 100644
--- a/reference_test.go
+++ b/reference_test.go
@@ -1,7 +1,6 @@
package git
import (
- "os"
"runtime"
"sort"
"testing"
@@ -10,7 +9,7 @@ import (
func TestRefModification(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, treeId := seedTestRepo(t, repo)
@@ -55,7 +54,7 @@ func TestRefModification(t *testing.T) {
func TestReferenceIterator(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
loc, err := time.LoadLocation("Europe/Berlin")
checkFatal(t, err)
@@ -133,7 +132,8 @@ func TestReferenceIterator(t *testing.T) {
func TestReferenceOwner(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
commitId, _ := seedTestRepo(t, repo)
ref, err := repo.CreateReference("refs/heads/foo", commitId, true, "")
@@ -151,7 +151,7 @@ func TestReferenceOwner(t *testing.T) {
func TestUtil(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, _ := seedTestRepo(t, repo)
@@ -192,8 +192,7 @@ func checkRefType(t *testing.T, ref *Reference, kind ReferenceType) {
// The failure happens at wherever we were called, not here
_, file, line, ok := runtime.Caller(1)
if !ok {
- t.Fatal()
+ t.Fatalf("Unable to get caller")
}
-
t.Fatalf("Wrong ref type at %v:%v; have %v, expected %v", file, line, ref.Type(), kind)
}
diff --git a/remote_test.go b/remote_test.go
index bbbdeb9..23c80f5 100644
--- a/remote_test.go
+++ b/remote_test.go
@@ -2,14 +2,12 @@ package git
import (
"fmt"
- "os"
"testing"
)
func TestRefspecs(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
remote, err := repo.CreateAnonymousRemote("git://foo/bar", "refs/heads/*:refs/heads/*")
checkFatal(t, err)
@@ -30,8 +28,7 @@ func TestRefspecs(t *testing.T) {
func TestListRemotes(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
_, err := repo.CreateRemote("test", "git://foo/bar")
@@ -58,8 +55,7 @@ func assertHostname(cert *Certificate, valid bool, hostname string, t *testing.T
func TestCertificateCheck(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
@@ -78,8 +74,7 @@ func TestCertificateCheck(t *testing.T) {
func TestRemoteConnect(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
@@ -90,8 +85,7 @@ func TestRemoteConnect(t *testing.T) {
func TestRemoteLs(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
@@ -109,8 +103,7 @@ func TestRemoteLs(t *testing.T) {
func TestRemoteLsFiltering(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
remote, err := repo.CreateRemote("origin", "https://github.com/libgit2/TestGitRepository")
checkFatal(t, err)
@@ -136,8 +129,7 @@ func TestRemoteLsFiltering(t *testing.T) {
func TestRemotePruneRefs(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
config, err := repo.Config()
checkFatal(t, err)
@@ -159,8 +151,7 @@ func TestRemotePruneRefs(t *testing.T) {
func TestRemotePrune(t *testing.T) {
remoteRepo := createTestRepo(t)
- defer os.RemoveAll(remoteRepo.Workdir())
- defer remoteRepo.Free()
+ defer cleanupTestRepo(t, remoteRepo)
head, _ := seedTestRepo(t, remoteRepo)
commit, err := remoteRepo.LookupCommit(head)
@@ -171,8 +162,7 @@ func TestRemotePrune(t *testing.T) {
checkFatal(t, err)
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
- defer repo.Free()
+ defer cleanupTestRepo(t, repo)
config, err := repo.Config()
checkFatal(t, err)
diff --git a/revparse_test.go b/revparse_test.go
index 8c3a352..4bc327c 100644
--- a/revparse_test.go
+++ b/revparse_test.go
@@ -1,13 +1,12 @@
package git
import (
- "os"
"testing"
)
func TestRevparse(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, _ := seedTestRepo(t, repo)
@@ -19,7 +18,7 @@ func TestRevparse(t *testing.T) {
func TestRevparseSingle(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
commitId, _ := seedTestRepo(t, repo)
@@ -31,7 +30,7 @@ func TestRevparseSingle(t *testing.T) {
func TestRevparseExt(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
_, treeId := seedTestRepo(t, repo)
diff --git a/status_test.go b/status_test.go
index d18fca1..5b97b00 100644
--- a/status_test.go
+++ b/status_test.go
@@ -2,15 +2,13 @@ package git
import (
"io/ioutil"
- "os"
"path"
"testing"
)
func TestStatusFile(t *testing.T) {
repo := createTestRepo(t)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
state := repo.State()
if state != RepositoryStateNone {
@@ -30,10 +28,10 @@ func TestStatusFile(t *testing.T) {
func TestStatusList(t *testing.T) {
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
// This commits the test repo README, so it doesn't show up in the status list and there's a head to compare to
seedTestRepo(t, repo)
- defer repo.Free()
- defer os.RemoveAll(repo.Workdir())
err := ioutil.WriteFile(path.Join(path.Dir(repo.Workdir()), "hello.txt"), []byte("Hello, World"), 0644)
checkFatal(t, err)
diff --git a/submodule.go b/submodule.go
index fdd38cc..6edc1d7 100644
--- a/submodule.go
+++ b/submodule.go
@@ -96,17 +96,24 @@ func (repo *Repository) LookupSubmodule(name string) (*Submodule, error) {
type SubmoduleCbk func(sub *Submodule, name string) int
//export SubmoduleVisitor
-func SubmoduleVisitor(csub unsafe.Pointer, name *C.char, cfct unsafe.Pointer) C.int {
+func SubmoduleVisitor(csub unsafe.Pointer, name *C.char, handle unsafe.Pointer) C.int {
sub := &Submodule{(*C.git_submodule)(csub)}
- fct := *(*SubmoduleCbk)(cfct)
- return (C.int)(fct(sub, C.GoString(name)))
+
+ if callback, ok := pointerHandles.Get(handle).(SubmoduleCbk); ok {
+ return (C.int)(callback(sub, C.GoString(name)))
+ } else {
+ panic("invalid submodule visitor callback")
+ }
}
func (repo *Repository) ForeachSubmodule(cbk SubmoduleCbk) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- ret := C._go_git_visit_submodule(repo.ptr, unsafe.Pointer(&cbk))
+ handle := pointerHandles.Track(cbk)
+ defer pointerHandles.Untrack(handle)
+
+ ret := C._go_git_visit_submodule(repo.ptr, handle)
if ret < 0 {
return MakeGitError(ret)
}
diff --git a/submodule_test.go b/submodule_test.go
index 1c8f471..27bc193 100644
--- a/submodule_test.go
+++ b/submodule_test.go
@@ -6,6 +6,8 @@ import (
func TestSubmoduleForeach(t *testing.T) {
repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
seedTestRepo(t, repo)
_, err := repo.AddSubmodule("http://example.org/submodule", "submodule", true)
@@ -19,6 +21,6 @@ func TestSubmoduleForeach(t *testing.T) {
checkFatal(t, err)
if i != 1 {
- t.Fatalf("expected one submodule found but got %i", i)
+ t.Fatalf("expected one submodule found but got %d", i)
}
}
diff --git a/tag_test.go b/tag_test.go
index 126cf6e..74f9fec 100644
--- a/tag_test.go
+++ b/tag_test.go
@@ -1,14 +1,14 @@
package git
import (
- "os"
"testing"
"time"
)
func TestCreateTag(t *testing.T) {
repo := createTestRepo(t)
- defer os.RemoveAll(repo.Workdir())
+ defer cleanupTestRepo(t, repo)
+
commitId, _ := seedTestRepo(t, repo)
commit, err := repo.LookupCommit(commitId)
diff --git a/tree.go b/tree.go
index c18d02a..aad2c8d 100644
--- a/tree.go
+++ b/tree.go
@@ -90,22 +90,28 @@ func (t Tree) EntryCount() uint64 {
type TreeWalkCallback func(string, *TreeEntry) int
//export CallbackGitTreeWalk
-func CallbackGitTreeWalk(_root unsafe.Pointer, _entry unsafe.Pointer, ptr unsafe.Pointer) C.int {
- root := C.GoString((*C.char)(_root))
+func CallbackGitTreeWalk(_root *C.char, _entry unsafe.Pointer, ptr unsafe.Pointer) C.int {
+ root := C.GoString(_root)
entry := (*C.git_tree_entry)(_entry)
- callback := *(*TreeWalkCallback)(ptr)
- return C.int(callback(root, newTreeEntry(entry)))
+ if callback, ok := pointerHandles.Get(ptr).(TreeWalkCallback); ok {
+ return C.int(callback(root, newTreeEntry(entry)))
+ } else {
+ panic("invalid treewalk callback")
+ }
}
func (t Tree) Walk(callback TreeWalkCallback) error {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
+ ptr := pointerHandles.Track(callback)
+ defer pointerHandles.Untrack(ptr)
+
err := C._go_git_treewalk(
t.cast_ptr,
C.GIT_TREEWALK_PRE,
- unsafe.Pointer(&callback),
+ ptr,
)
if err < 0 {