diff --git a/merge.go b/merge.go index b3fd818..bfbf9a3 100644 --- a/merge.go +++ b/merge.go @@ -18,10 +18,11 @@ import ( type AnnotatedCommit struct { ptr *C.git_annotated_commit + r *Repository } -func newAnnotatedCommitFromC(c *C.git_annotated_commit) *AnnotatedCommit { - mh := &AnnotatedCommit{ptr: c} +func newAnnotatedCommitFromC(ptr *C.git_annotated_commit, r *Repository) *AnnotatedCommit { + mh := &AnnotatedCommit{ptr: ptr, r: r} runtime.SetFinalizer(mh, (*AnnotatedCommit).Free) return mh } @@ -32,8 +33,6 @@ func (mh *AnnotatedCommit) Free() { } func (r *Repository) AnnotatedCommitFromFetchHead(branchName string, remoteURL string, oid *Oid) (*AnnotatedCommit, error) { - mh := &AnnotatedCommit{} - cbranchName := C.CString(branchName) defer C.free(unsafe.Pointer(cbranchName)) @@ -43,40 +42,41 @@ func (r *Repository) AnnotatedCommitFromFetchHead(branchName string, remoteURL s runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_annotated_commit_from_fetchhead(&mh.ptr, r.ptr, cbranchName, cremoteURL, oid.toC()) + var ptr *C.git_annotated_commit + ret := C.git_annotated_commit_from_fetchhead(&ptr, r.ptr, cbranchName, cremoteURL, oid.toC()) + runtime.KeepAlive(oid) if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(mh, (*AnnotatedCommit).Free) - return mh, nil + + return newAnnotatedCommitFromC(ptr, r), nil } func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) { - mh := &AnnotatedCommit{} - runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_annotated_commit_lookup(&mh.ptr, r.ptr, oid.toC()) + var ptr *C.git_annotated_commit + ret := C.git_annotated_commit_lookup(&ptr, r.ptr, oid.toC()) + runtime.KeepAlive(oid) if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(mh, (*AnnotatedCommit).Free) - return mh, nil + return newAnnotatedCommitFromC(ptr, r), nil } func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, error) { - mh := &AnnotatedCommit{} - runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_annotated_commit_from_ref(&mh.ptr, r.ptr, ref.ptr) + var ptr *C.git_annotated_commit + ret := C.git_annotated_commit_from_ref(&ptr, r.ptr, ref.ptr) + runtime.KeepAlive(r) + runtime.KeepAlive(ref) if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(mh, (*AnnotatedCommit).Free) - return mh, nil + return newAnnotatedCommitFromC(ptr, r), nil } type MergeTreeFlag int @@ -162,6 +162,7 @@ func (r *Repository) Merge(theirHeads []*AnnotatedCommit, mergeOptions *MergeOpt } ptr := unsafe.Pointer(&gmerge_head_array[0]) err := C.git_merge(r.ptr, (**C.git_annotated_commit)(ptr), C.size_t(len(theirHeads)), cMergeOpts, cCheckoutOpts) + runtime.KeepAlive(theirHeads) if err < 0 { return MakeGitError(err) } @@ -201,6 +202,7 @@ func (r *Repository) MergeAnalysis(theirHeads []*AnnotatedCommit) (MergeAnalysis var analysis C.git_merge_analysis_t var preference C.git_merge_preference_t err := C.git_merge_analysis(&analysis, &preference, r.ptr, (**C.git_annotated_commit)(ptr), C.size_t(len(theirHeads))) + runtime.KeepAlive(theirHeads) if err < 0 { return MergeAnalysisNone, MergePreferenceNone, MakeGitError(err) } @@ -214,14 +216,15 @@ func (r *Repository) MergeCommits(ours *Commit, theirs *Commit, options *MergeOp copts := options.toC() - idx := &Index{} - - ret := C.git_merge_commits(&idx.ptr, r.ptr, ours.cast_ptr, theirs.cast_ptr, copts) + var ptr *C.git_index + ret := C.git_merge_commits(&ptr, r.ptr, ours.cast_ptr, theirs.cast_ptr, copts) + runtime.KeepAlive(ours) + runtime.KeepAlive(theirs) if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(idx, (*Index).Free) - return idx, nil + + return newIndexFromC(ptr, r), nil } func (r *Repository) MergeTrees(ancestor *Tree, ours *Tree, theirs *Tree, options *MergeOptions) (*Index, error) { @@ -230,17 +233,20 @@ func (r *Repository) MergeTrees(ancestor *Tree, ours *Tree, theirs *Tree, option copts := options.toC() - idx := &Index{} var ancestor_ptr *C.git_tree if ancestor != nil { ancestor_ptr = ancestor.cast_ptr } - ret := C.git_merge_trees(&idx.ptr, r.ptr, ancestor_ptr, ours.cast_ptr, theirs.cast_ptr, copts) + var ptr *C.git_index + ret := C.git_merge_trees(&ptr, r.ptr, ancestor_ptr, ours.cast_ptr, theirs.cast_ptr, copts) + runtime.KeepAlive(ancestor) + runtime.KeepAlive(ours) + runtime.KeepAlive(theirs) if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(idx, (*Index).Free) - return idx, nil + + return newIndexFromC(ptr, r), nil } func (r *Repository) MergeBase(one *Oid, two *Oid) (*Oid, error) { @@ -249,6 +255,9 @@ func (r *Repository) MergeBase(one *Oid, two *Oid) (*Oid, error) { var oid C.git_oid ret := C.git_merge_base(&oid, r.ptr, one.toC(), two.toC()) + runtime.KeepAlive(one) + runtime.KeepAlive(two) + runtime.KeepAlive(r) if ret < 0 { return nil, MakeGitError(ret) } @@ -265,6 +274,8 @@ func (r *Repository) MergeBases(one, two *Oid) ([]*Oid, error) { var coids C.git_oidarray ret := C.git_merge_bases(&coids, r.ptr, one.toC(), two.toC()) + runtime.KeepAlive(one) + runtime.KeepAlive(two) if ret < 0 { return make([]*Oid, 0), MakeGitError(ret) } @@ -413,6 +424,9 @@ func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInp (*C.char)(unsafe.Pointer(oursContents)), C.size_t(len(ours.Contents)), oursPath, C.uint(ours.Mode), (*C.char)(unsafe.Pointer(theirsContents)), C.size_t(len(theirs.Contents)), theirsPath, C.uint(theirs.Mode), copts) + runtime.KeepAlive(ancestor) + runtime.KeepAlive(ours) + runtime.KeepAlive(theirs) if ecode < 0 { return nil, MakeGitError(ecode) } diff --git a/note.go b/note.go index a1b15d8..21bed57 100644 --- a/note.go +++ b/note.go @@ -52,7 +52,8 @@ func (c *NoteCollection) Create( ret := C.git_note_create( oid.toC(), c.repo.ptr, cref, authorSig, committerSig, id.toC(), cnote, cbool(force)) - + runtime.KeepAlive(c) + runtime.KeepAlive(id) if ret < 0 { return nil, MakeGitError(ret) } @@ -69,17 +70,18 @@ func (c *NoteCollection) Read(ref string, id *Oid) (*Note, error) { defer C.free(unsafe.Pointer(cref)) } - note := new(Note) - runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_note_read(¬e.ptr, c.repo.ptr, cref, id.toC()); ret < 0 { + var ptr *C.git_note + ret := C.git_note_read(&ptr, c.repo.ptr, cref, id.toC()) + runtime.KeepAlive(c) + runtime.KeepAlive(id) + if ret < 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(note, (*Note).Free) - return note, nil + return newNoteFromC(ptr, c.repo), nil } // Remove removes the note for an object @@ -108,6 +110,8 @@ func (c *NoteCollection) Remove(ref string, author, committer *Signature, id *Oi defer runtime.UnlockOSThread() ret := C.git_note_remove(c.repo.ptr, cref, authorSig, committerSig, id.toC()) + runtime.KeepAlive(c) + runtime.KeepAlive(id) if ret < 0 { return MakeGitError(ret) } @@ -121,8 +125,10 @@ func (c *NoteCollection) DefaultRef() (string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_note_default_ref(&buf, c.repo.ptr); ret < 0 { - return "", MakeGitError(ret) + ecode := C.git_note_default_ref(&buf, c.repo.ptr) + runtime.KeepAlive(c) + if ecode < 0 { + return "", MakeGitError(ecode) } ret := C.GoString(buf.ptr) @@ -134,6 +140,13 @@ func (c *NoteCollection) DefaultRef() (string, error) { // Note type Note struct { ptr *C.git_note + r *Repository +} + +func newNoteFromC(ptr *C.git_note, r *Repository) *Note { + note := &Note{ptr: ptr, r: r} + runtime.SetFinalizer(note, (*Note).Free) + return note } // Free frees a git_note object @@ -156,23 +169,28 @@ func (n *Note) Author() *Signature { // Id returns the note object's id func (n *Note) Id() *Oid { ptr := C.git_note_id(n.ptr) + runtime.KeepAlive(n) return newOidFromC(ptr) } // Committer returns the signature of the note committer func (n *Note) Committer() *Signature { ptr := C.git_note_committer(n.ptr) + runtime.KeepAlive(n) return newSignatureFromC(ptr) } // Message returns the note message func (n *Note) Message() string { - return C.GoString(C.git_note_message(n.ptr)) + ret := C.GoString(C.git_note_message(n.ptr)) + runtime.KeepAlive(n) + return ret } // NoteIterator type NoteIterator struct { ptr *C.git_note_iterator + r *Repository } // NewNoteIterator creates a new iterator for notes @@ -190,11 +208,13 @@ func (repo *Repository) NewNoteIterator(ref string) (*NoteIterator, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_note_iterator_new(&ptr, repo.ptr, cref); ret < 0 { + ret := C.git_note_iterator_new(&ptr, repo.ptr, cref) + runtime.KeepAlive(repo) + if ret < 0 { return nil, MakeGitError(ret) } - iter := &NoteIterator{ptr: ptr} + iter := &NoteIterator{ptr: ptr, r: repo} runtime.SetFinalizer(iter, (*NoteIterator).Free) return iter, nil } @@ -213,7 +233,11 @@ func (it *NoteIterator) Next() (noteId, annotatedId *Oid, err error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_note_next(noteId.toC(), annotatedId.toC(), it.ptr); ret < 0 { + ret := C.git_note_next(noteId.toC(), annotatedId.toC(), it.ptr) + runtime.KeepAlive(noteId) + runtime.KeepAlive(annotatedId) + runtime.KeepAlive(it) + if ret < 0 { err = MakeGitError(ret) } return diff --git a/object.go b/object.go index b365a3f..f4f1b3e 100644 --- a/object.go +++ b/object.go @@ -46,7 +46,9 @@ func (t ObjectType) String() string { } func (o *Object) Id() *Oid { - return newOidFromC(C.git_object_id(o.ptr)) + ret := newOidFromC(C.git_object_id(o.ptr)) + runtime.KeepAlive(o) + return ret } func (o *Object) ShortId() (string, error) { @@ -56,6 +58,7 @@ func (o *Object) ShortId() (string, error) { defer runtime.UnlockOSThread() ecode := C.git_object_short_id(&resultBuf, o.ptr) + runtime.KeepAlive(o) if ecode < 0 { return "", MakeGitError(ecode) } @@ -64,15 +67,19 @@ func (o *Object) ShortId() (string, error) { } func (o *Object) Type() ObjectType { - return ObjectType(C.git_object_type(o.ptr)) + ret := ObjectType(C.git_object_type(o.ptr)) + runtime.KeepAlive(o) + return ret } // Owner returns a weak reference to the repository which owns this // object. This won't keep the underlying repository alive. func (o *Object) Owner() *Repository { - return &Repository{ + ret := &Repository{ ptr: C.git_object_owner(o.ptr), } + runtime.KeepAlive(o) + return ret } func dupObject(obj *Object, kind ObjectType) (*C.git_object, error) { @@ -85,7 +92,9 @@ func dupObject(obj *Object, kind ObjectType) (*C.git_object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if err := C.git_object_dup(&cobj, obj.ptr); err < 0 { + err := C.git_object_dup(&cobj, obj.ptr) + runtime.KeepAlive(obj) + if err < 0 { return nil, MakeGitError(err) } @@ -203,7 +212,9 @@ func (o *Object) Peel(t ObjectType) (*Object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t)); err < 0 { + err := C.git_object_peel(&cobj, o.ptr, C.git_otype(t)) + runtime.KeepAlive(o) + if err < 0 { return nil, MakeGitError(err) } diff --git a/odb.go b/odb.go index a728cd3..64c5415 100644 --- a/odb.go +++ b/odb.go @@ -47,6 +47,7 @@ func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) { defer runtime.UnlockOSThread() ret := C.git_odb_add_backend(v.ptr, backend.ptr, C.int(priority)) + runtime.KeepAlive(v) if ret < 0 { backend.Free() return MakeGitError(ret) @@ -57,20 +58,23 @@ func (v *Odb) AddBackend(backend *OdbBackend, priority int) (err error) { func (v *Odb) ReadHeader(oid *Oid) (uint64, ObjectType, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - + var sz C.size_t - var cotype C.git_otype + var cotype C.git_otype ret := C.git_odb_read_header(&sz, &cotype, v.ptr, oid.toC()) + runtime.KeepAlive(v) if ret < 0 { return 0, C.GIT_OBJ_BAD, MakeGitError(ret) } return uint64(sz), ObjectType(cotype), nil } - + func (v *Odb) Exists(oid *Oid) bool { ret := C.git_odb_exists(v.ptr, oid.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(oid) return ret != 0 } @@ -85,7 +89,7 @@ func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) { defer runtime.UnlockOSThread() ret := C.git_odb_write(oid.toC(), v.ptr, cptr, C.size_t(len(data)), C.git_otype(otype)) - + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -100,6 +104,8 @@ func (v *Odb) Read(oid *Oid) (obj *OdbObject, err error) { defer runtime.UnlockOSThread() ret := C.git_odb_read(&obj.ptr, v.ptr, oid.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(oid) if ret < 0 { return nil, MakeGitError(ret) } @@ -145,6 +151,7 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error { defer pointerHandles.Untrack(handle) ret := C._go_git_odb_foreach(v.ptr, handle) + runtime.KeepAlive(v) if ret == C.GIT_EUSER { return data.err } else if ret < 0 { @@ -164,6 +171,7 @@ func (v *Odb) Hash(data []byte, otype ObjectType) (oid *Oid, err error) { defer runtime.UnlockOSThread() ret := C.git_odb_hash(oid.toC(), ptr, C.size_t(header.Len), C.git_otype(otype)) + runtime.KeepAlive(data) if ret < 0 { return nil, MakeGitError(ret) } @@ -179,6 +187,8 @@ func (v *Odb) NewReadStream(id *Oid) (*OdbReadStream, error) { defer runtime.UnlockOSThread() ret := C.git_odb_open_rstream(&stream.ptr, v.ptr, id.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(id) if ret < 0 { return nil, MakeGitError(ret) } @@ -197,6 +207,7 @@ func (v *Odb) NewWriteStream(size int64, otype ObjectType) (*OdbWriteStream, err defer runtime.UnlockOSThread() ret := C.git_odb_open_wstream(&stream.ptr, v.ptr, C.git_off_t(size), C.git_otype(otype)) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -219,17 +230,25 @@ func (v *OdbObject) Free() { } func (object *OdbObject) Id() (oid *Oid) { - return newOidFromC(C.git_odb_object_id(object.ptr)) + ret := newOidFromC(C.git_odb_object_id(object.ptr)) + runtime.KeepAlive(object) + return ret } func (object *OdbObject) Len() (len uint64) { - return uint64(C.git_odb_object_size(object.ptr)) + ret := uint64(C.git_odb_object_size(object.ptr)) + runtime.KeepAlive(object) + return ret } func (object *OdbObject) Type() ObjectType { - return ObjectType(C.git_odb_object_type(object.ptr)) + ret := ObjectType(C.git_odb_object_type(object.ptr)) + runtime.KeepAlive(object) + return ret } +// Data returns a slice pointing to the unmanaged object memory. You must make +// sure the object is referenced for at least as long as the slice is used. func (object *OdbObject) Data() (data []byte) { var c_blob unsafe.Pointer = C.git_odb_object_data(object.ptr) var blob []byte @@ -258,6 +277,7 @@ func (stream *OdbReadStream) Read(data []byte) (int, error) { defer runtime.UnlockOSThread() ret := C.git_odb_stream_read(stream.ptr, ptr, size) + runtime.KeepAlive(stream) if ret < 0 { return 0, MakeGitError(ret) } @@ -293,6 +313,7 @@ func (stream *OdbWriteStream) Write(data []byte) (int, error) { defer runtime.UnlockOSThread() ret := C.git_odb_stream_write(stream.ptr, ptr, size) + runtime.KeepAlive(stream) if ret < 0 { return 0, MakeGitError(ret) } @@ -307,6 +328,7 @@ func (stream *OdbWriteStream) Close() error { defer runtime.UnlockOSThread() ret := C.git_odb_stream_finalize_write(stream.Id.toC(), stream.ptr) + runtime.KeepAlive(stream) if ret < 0 { return MakeGitError(ret) } diff --git a/packbuilder.go b/packbuilder.go index 4dc352c..0e04bbf 100644 --- a/packbuilder.go +++ b/packbuilder.go @@ -17,20 +17,25 @@ import ( type Packbuilder struct { ptr *C.git_packbuilder + r *Repository } func (repo *Repository) NewPackbuilder() (*Packbuilder, error) { - builder := &Packbuilder{} - runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_packbuilder_new(&builder.ptr, repo.ptr) + var ptr *C.git_packbuilder + ret := C.git_packbuilder_new(&ptr, repo.ptr) if ret != 0 { return nil, MakeGitError(ret) } - runtime.SetFinalizer(builder, (*Packbuilder).Free) - return builder, nil + return newPackbuilderFromC(ptr, repo), nil +} + +func newPackbuilderFromC(ptr *C.git_packbuilder, r *Repository) *Packbuilder { + pb := &Packbuilder{ptr: ptr, r: r} + runtime.SetFinalizer(pb, (*Packbuilder).Free) + return pb } func (pb *Packbuilder) Free() { @@ -46,6 +51,8 @@ func (pb *Packbuilder) Insert(id *Oid, name string) error { defer runtime.UnlockOSThread() ret := C.git_packbuilder_insert(pb.ptr, id.toC(), cname) + runtime.KeepAlive(pb) + runtime.KeepAlive(id) if ret != 0 { return MakeGitError(ret) } @@ -57,6 +64,8 @@ func (pb *Packbuilder) InsertCommit(id *Oid) error { defer runtime.UnlockOSThread() ret := C.git_packbuilder_insert_commit(pb.ptr, id.toC()) + runtime.KeepAlive(pb) + runtime.KeepAlive(id) if ret != 0 { return MakeGitError(ret) } @@ -68,6 +77,8 @@ func (pb *Packbuilder) InsertTree(id *Oid) error { defer runtime.UnlockOSThread() ret := C.git_packbuilder_insert_tree(pb.ptr, id.toC()) + runtime.KeepAlive(pb) + runtime.KeepAlive(id) if ret != 0 { return MakeGitError(ret) } @@ -75,7 +86,9 @@ func (pb *Packbuilder) InsertTree(id *Oid) error { } func (pb *Packbuilder) ObjectCount() uint32 { - return uint32(C.git_packbuilder_object_count(pb.ptr)) + ret := uint32(C.git_packbuilder_object_count(pb.ptr)) + runtime.KeepAlive(pb) + return ret } func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error { @@ -86,6 +99,7 @@ func (pb *Packbuilder) WriteToFile(name string, mode os.FileMode) error { defer runtime.UnlockOSThread() ret := C.git_packbuilder_write(pb.ptr, cname, C.uint(mode.Perm()), nil, nil) + runtime.KeepAlive(pb) if ret != 0 { return MakeGitError(ret) } @@ -100,7 +114,9 @@ func (pb *Packbuilder) Write(w io.Writer) error { } func (pb *Packbuilder) Written() uint32 { - return uint32(C.git_packbuilder_written(pb.ptr)) + ret := uint32(C.git_packbuilder_written(pb.ptr)) + runtime.KeepAlive(pb) + return ret } type PackbuilderForeachCallback func([]byte) error @@ -142,6 +158,7 @@ func (pb *Packbuilder) ForEach(callback PackbuilderForeachCallback) error { defer runtime.UnlockOSThread() err := C._go_git_packbuilder_foreach(pb.ptr, handle) + runtime.KeepAlive(pb) if err == C.GIT_EUSER { return data.err } diff --git a/patch.go b/patch.go index 0d0df7f..75e843c 100644 --- a/patch.go +++ b/patch.go @@ -47,6 +47,7 @@ func (patch *Patch) String() (string, error) { var buf C.git_buf ecode := C.git_patch_to_buf(&buf, patch.ptr) + runtime.KeepAlive(patch) if ecode < 0 { return "", MakeGitError(ecode) } @@ -83,6 +84,8 @@ func (v *Repository) PatchFromBuffers(oldPath, newPath string, oldBuf, newBuf [] defer runtime.UnlockOSThread() ecode := C.git_patch_from_buffers(&patchPtr, oldPtr, C.size_t(len(oldBuf)), cOldPath, newPtr, C.size_t(len(newBuf)), cNewPath, copts) + runtime.KeepAlive(oldBuf) + runtime.KeepAlive(newBuf) if ecode < 0 { return nil, MakeGitError(ecode) } diff --git a/rebase.go b/rebase.go index 8553e25..390b924 100644 --- a/rebase.go +++ b/rebase.go @@ -100,6 +100,7 @@ func mapEmptyStringToNull(ref string) *C.char { // Rebase is the struct representing a Rebase object. type Rebase struct { ptr *C.git_rebase + r *Repository } // InitRebase initializes a rebase operation to rebase the changes in branch relative to upstream onto another branch. @@ -121,6 +122,9 @@ func (r *Repository) InitRebase(branch *AnnotatedCommit, upstream *AnnotatedComm var ptr *C.git_rebase err := C.git_rebase_init(&ptr, r.ptr, branch.ptr, upstream.ptr, onto.ptr, opts.toC()) + runtime.KeepAlive(branch) + runtime.KeepAlive(upstream) + runtime.KeepAlive(onto) if err < 0 { return nil, MakeGitError(err) } @@ -135,6 +139,7 @@ func (r *Repository) OpenRebase(opts *RebaseOptions) (*Rebase, error) { var ptr *C.git_rebase err := C.git_rebase_open(&ptr, r.ptr, opts.toC()) + runtime.KeepAlive(r) if err < 0 { return nil, MakeGitError(err) } @@ -145,7 +150,7 @@ func (r *Repository) OpenRebase(opts *RebaseOptions) (*Rebase, error) { // OperationAt gets the rebase operation specified by the given index. func (rebase *Rebase) OperationAt(index uint) *RebaseOperation { operation := C.git_rebase_operation_byindex(rebase.ptr, C.size_t(index)) - + return newRebaseOperationFromC(operation) } @@ -165,7 +170,9 @@ func (rebase *Rebase) CurrentOperationIndex() (uint, error) { // OperationCount gets the count of rebase operations that are to be applied. func (rebase *Rebase) OperationCount() uint { - return uint(C.git_rebase_operation_entrycount(rebase.ptr)) + ret := uint(C.git_rebase_operation_entrycount(rebase.ptr)) + runtime.KeepAlive(rebase) + return ret } // Next performs the next rebase operation and returns the information about it. @@ -178,6 +185,7 @@ func (rebase *Rebase) Next() (*RebaseOperation, error) { var ptr *C.git_rebase_operation err := C.git_rebase_next(&ptr, rebase.ptr) + runtime.KeepAlive(rebase) if err < 0 { return nil, MakeGitError(err) } @@ -207,6 +215,8 @@ func (rebase *Rebase) Commit(ID *Oid, author, committer *Signature, message stri defer C.free(unsafe.Pointer(cmsg)) cerr := C.git_rebase_commit(ID.toC(), rebase.ptr, authorSig, committerSig, nil, cmsg) + runtime.KeepAlive(ID) + runtime.KeepAlive(rebase) if cerr < 0 { return MakeGitError(cerr) } @@ -220,6 +230,7 @@ func (rebase *Rebase) Finish() error { defer runtime.UnlockOSThread() err := C.git_rebase_finish(rebase.ptr, nil) + runtime.KeepAlive(rebase) if err < 0 { return MakeGitError(err) } @@ -233,6 +244,7 @@ func (rebase *Rebase) Abort() error { defer runtime.UnlockOSThread() err := C.git_rebase_abort(rebase.ptr) + runtime.KeepAlive(rebase) if err < 0 { return MakeGitError(err) } diff --git a/refdb.go b/refdb.go index 4e3ebf9..578f43c 100644 --- a/refdb.go +++ b/refdb.go @@ -14,6 +14,7 @@ import ( type Refdb struct { ptr *C.git_refdb + r *Repository } type RefdbBackend struct { @@ -21,16 +22,17 @@ type RefdbBackend struct { } func (v *Repository) NewRefdb() (refdb *Refdb, err error) { - refdb = new(Refdb) + var ptr *C.git_refdb runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_refdb_new(&refdb.ptr, v.ptr) + ret := C.git_refdb_new(&ptr, v.ptr) if ret < 0 { return nil, MakeGitError(ret) } + refdb = &Refdb{ptr: ptr, r: v} runtime.SetFinalizer(refdb, (*Refdb).Free) return refdb, nil } @@ -45,6 +47,8 @@ func (v *Refdb) SetBackend(backend *RefdbBackend) (err error) { defer runtime.UnlockOSThread() ret := C.git_refdb_set_backend(v.ptr, backend.ptr) + runtime.KeepAlive(v) + runtime.KeepAlive(backend) if ret < 0 { backend.Free() return MakeGitError(ret) @@ -53,5 +57,6 @@ func (v *Refdb) SetBackend(backend *RefdbBackend) (err error) { } func (v *RefdbBackend) Free() { + runtime.SetFinalizer(v, nil) C._go_git_refdb_backend_free(v.ptr) } diff --git a/reference.go b/reference.go index 463f2fc..e10c9b2 100644 --- a/reference.go +++ b/reference.go @@ -34,6 +34,7 @@ func (c *ReferenceCollection) Lookup(name string) (*Reference, error) { defer runtime.UnlockOSThread() ecode := C.git_reference_lookup(&ptr, c.repo.ptr, cname) + runtime.KeepAlive(c) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -59,6 +60,8 @@ func (c *ReferenceCollection) Create(name string, id *Oid, force bool, msg strin defer runtime.UnlockOSThread() ecode := C.git_reference_create(&ptr, c.repo.ptr, cname, id.toC(), cbool(force), cmsg) + runtime.KeepAlive(c) + runtime.KeepAlive(id) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -87,6 +90,7 @@ func (c *ReferenceCollection) CreateSymbolic(name, target string, force bool, ms defer runtime.UnlockOSThread() ecode := C.git_reference_symbolic_create(&ptr, c.repo.ptr, cname, ctarget, cbool(force), cmsg) + runtime.KeepAlive(c) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -104,6 +108,7 @@ func (c *ReferenceCollection) EnsureLog(name string) error { defer runtime.UnlockOSThread() ret := C.git_reference_ensure_log(c.repo.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -121,6 +126,7 @@ func (c *ReferenceCollection) HasLog(name string) (bool, error) { defer runtime.UnlockOSThread() ret := C.git_reference_has_log(c.repo.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return false, MakeGitError(ret) } @@ -138,6 +144,7 @@ func (c *ReferenceCollection) Dwim(name string) (*Reference, error) { var ptr *C.git_reference ret := C.git_reference_dwim(&ptr, c.repo.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return nil, MakeGitError(ret) } @@ -169,6 +176,7 @@ func (v *Reference) SetSymbolicTarget(target string, msg string) (*Reference, er } ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, cmsg) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -191,6 +199,7 @@ func (v *Reference) SetTarget(target *Oid, msg string) (*Reference, error) { } ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), cmsg) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -205,6 +214,7 @@ func (v *Reference) Resolve() (*Reference, error) { defer runtime.UnlockOSThread() ret := C.git_reference_resolve(&ptr, v.ptr) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -229,7 +239,7 @@ func (v *Reference) Rename(name string, force bool, msg string) (*Reference, err defer runtime.UnlockOSThread() ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), cmsg) - + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -238,16 +248,21 @@ func (v *Reference) Rename(name string, force bool, msg string) (*Reference, err } func (v *Reference) Target() *Oid { - return newOidFromC(C.git_reference_target(v.ptr)) + ret := newOidFromC(C.git_reference_target(v.ptr)) + runtime.KeepAlive(v) + return ret } func (v *Reference) SymbolicTarget() string { + var ret string cstr := C.git_reference_symbolic_target(v.ptr) - if cstr == nil { - return "" + + if cstr != nil { + return C.GoString(cstr) } - return C.GoString(cstr) + runtime.KeepAlive(v) + return ret } func (v *Reference) Delete() error { @@ -255,7 +270,7 @@ func (v *Reference) Delete() error { defer runtime.UnlockOSThread() ret := C.git_reference_delete(v.ptr) - + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -269,7 +284,9 @@ func (v *Reference) Peel(t ObjectType) (*Object, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if err := C.git_reference_peel(&cobj, v.ptr, C.git_otype(t)); err < 0 { + err := C.git_reference_peel(&cobj, v.ptr, C.git_otype(t)) + runtime.KeepAlive(v) + if err < 0 { return nil, MakeGitError(err) } @@ -287,37 +304,54 @@ func (v *Reference) Owner() *Repository { // Cmp compares both references, retursn 0 on equality, otherwise a // stable sorting. func (v *Reference) Cmp(ref2 *Reference) int { - return int(C.git_reference_cmp(v.ptr, ref2.ptr)) + ret := int(C.git_reference_cmp(v.ptr, ref2.ptr)) + runtime.KeepAlive(v) + runtime.KeepAlive(ref2) + return ret } -// Shorthand returns a "human-readable" short reference name +// Shorthand ret :=s a "human-readable" short reference name func (v *Reference) Shorthand() string { - return C.GoString(C.git_reference_shorthand(v.ptr)) + ret := C.GoString(C.git_reference_shorthand(v.ptr)) + runtime.KeepAlive(v) + return ret } func (v *Reference) Name() string { - return C.GoString(C.git_reference_name(v.ptr)) + ret := C.GoString(C.git_reference_name(v.ptr)) + runtime.KeepAlive(v) + return ret } func (v *Reference) Type() ReferenceType { - return ReferenceType(C.git_reference_type(v.ptr)) + ret := ReferenceType(C.git_reference_type(v.ptr)) + runtime.KeepAlive(v) + return ret } func (v *Reference) IsBranch() bool { - return C.git_reference_is_branch(v.ptr) == 1 + ret := C.git_reference_is_branch(v.ptr) == 1 + runtime.KeepAlive(v) + return ret } func (v *Reference) IsRemote() bool { - return C.git_reference_is_remote(v.ptr) == 1 + ret := C.git_reference_is_remote(v.ptr) == 1 + runtime.KeepAlive(v) + return ret } func (v *Reference) IsTag() bool { - return C.git_reference_is_tag(v.ptr) == 1 + ret := C.git_reference_is_tag(v.ptr) == 1 + runtime.KeepAlive(v) + return ret } // IsNote checks if the reference is a note. func (v *Reference) IsNote() bool { - return C.git_reference_is_note(v.ptr) == 1 + ret := C.git_reference_is_note(v.ptr) == 1 + runtime.KeepAlive(v) + return ret } func (v *Reference) Free() { @@ -346,9 +380,7 @@ func (repo *Repository) NewReferenceIterator() (*ReferenceIterator, error) { return nil, MakeGitError(ret) } - iter := &ReferenceIterator{ptr: ptr, repo: repo} - runtime.SetFinalizer(iter, (*ReferenceIterator).Free) - return iter, nil + return newReferenceIteratorFromC(ptr, repo), nil } // NewReferenceIterator creates a new branch iterator over reference names @@ -363,8 +395,7 @@ func (repo *Repository) NewReferenceNameIterator() (*ReferenceNameIterator, erro return nil, MakeGitError(ret) } - iter := &ReferenceIterator{ptr: ptr, repo: repo} - runtime.SetFinalizer(iter, (*ReferenceIterator).Free) + iter := newReferenceIteratorFromC(ptr, repo) return iter.Names(), nil } @@ -384,9 +415,7 @@ func (repo *Repository) NewReferenceIteratorGlob(glob string) (*ReferenceIterato return nil, MakeGitError(ret) } - iter := &ReferenceIterator{ptr: ptr} - runtime.SetFinalizer(iter, (*ReferenceIterator).Free) - return iter, nil + return newReferenceIteratorFromC(ptr, repo), nil } func (i *ReferenceIterator) Names() *ReferenceNameIterator { @@ -425,6 +454,13 @@ func (v *ReferenceIterator) Next() (*Reference, error) { return newReferenceFromC(ptr, v.repo), nil } +func newReferenceIteratorFromC(ptr *C.git_reference_iterator, r *Repository) *ReferenceIterator { + return &ReferenceIterator{ + ptr: ptr, + repo: r, + } +} + // Free the reference iterator func (v *ReferenceIterator) Free() { runtime.SetFinalizer(v, nil) diff --git a/repository.go b/repository.go index 6b07e87..abf8b71 100644 --- a/repository.go +++ b/repository.go @@ -120,6 +120,7 @@ func NewRepositoryWrapOdb(odb *Odb) (repo *Repository, err error) { var ptr *C.git_repository ret := C.git_repository_wrap_odb(&ptr, odb.ptr) + runtime.KeepAlive(odb) if ret < 0 { return nil, MakeGitError(ret) } diff --git a/signature.go b/signature.go index 0518387..16964d2 100644 --- a/signature.go +++ b/signature.go @@ -63,6 +63,7 @@ func (repo *Repository) DefaultSignature() (*Signature, error) { defer runtime.UnlockOSThread() cErr := C.git_signature_default(&out, repo.ptr) + runtime.KeepAlive(repo) if cErr < 0 { return nil, MakeGitError(cErr) } diff --git a/stash.go b/stash.go index 809732e..8743da8 100644 --- a/stash.go +++ b/stash.go @@ -63,7 +63,7 @@ func (c *StashCollection) Save( ret := C.git_stash_save( oid.toC(), c.repo.ptr, stasherC, messageC, C.uint32_t(flags)) - + runtime.KeepAlive(c) if ret < 0 { return nil, MakeGitError(ret) } @@ -228,6 +228,7 @@ func (c *StashCollection) Apply(index int, opts StashApplyOptions) error { defer runtime.UnlockOSThread() ret := C.git_stash_apply(c.repo.ptr, C.size_t(index), optsC) + runtime.KeepAlive(c) if ret == C.GIT_EUSER { return progressData.Error } @@ -282,6 +283,7 @@ func (c *StashCollection) Foreach(callback StashCallback) error { defer runtime.UnlockOSThread() ret := C._go_git_stash_foreach(c.repo.ptr, handle) + runtime.KeepAlive(c) if ret == C.GIT_EUSER { return data.Error } @@ -303,6 +305,7 @@ func (c *StashCollection) Drop(index int) error { defer runtime.UnlockOSThread() ret := C.git_stash_drop(c.repo.ptr, C.size_t(index)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -328,6 +331,7 @@ func (c *StashCollection) Pop(index int, opts StashApplyOptions) error { defer runtime.UnlockOSThread() ret := C.git_stash_pop(c.repo.ptr, C.size_t(index), optsC) + runtime.KeepAlive(c) if ret == C.GIT_EUSER { return progressData.Error } diff --git a/status.go b/status.go index e68e6e9..e37a96d 100644 --- a/status.go +++ b/status.go @@ -55,15 +55,17 @@ func statusEntryFromC(statusEntry *C.git_status_entry) StatusEntry { type StatusList struct { ptr *C.git_status_list + r *Repository } -func newStatusListFromC(ptr *C.git_status_list) *StatusList { +func newStatusListFromC(ptr *C.git_status_list, r *Repository) *StatusList { if ptr == nil { return nil } statusList := &StatusList{ ptr: ptr, + r: r, } runtime.SetFinalizer(statusList, (*StatusList).Free) @@ -84,14 +86,20 @@ func (statusList *StatusList) ByIndex(index int) (StatusEntry, error) { return StatusEntry{}, ErrInvalid } ptr := C.git_status_byindex(statusList.ptr, C.size_t(index)) - return statusEntryFromC(ptr), nil + entry := statusEntryFromC(ptr) + runtime.KeepAlive(statusList) + + return entry, nil } func (statusList *StatusList) EntryCount() (int, error) { if statusList.ptr == nil { return -1, ErrInvalid } - return int(C.git_status_list_entrycount(statusList.ptr)), nil + ret := int(C.git_status_list_entrycount(statusList.ptr)) + runtime.KeepAlive(statusList) + + return ret, nil } type StatusOpt int @@ -161,7 +169,7 @@ func (v *Repository) StatusList(opts *StatusOptions) (*StatusList, error) { return nil, MakeGitError(ret) } - return newStatusListFromC(ptr), nil + return newStatusListFromC(ptr, v), nil } func (v *Repository) StatusFile(path string) (Status, error) { @@ -173,6 +181,7 @@ func (v *Repository) StatusFile(path string) (Status, error) { defer runtime.UnlockOSThread() ret := C.git_status_file(&statusFlags, v.ptr, cPath) + runtime.KeepAlive(v) if ret < 0 { return 0, MakeGitError(ret) } diff --git a/submodule.go b/submodule.go index 4a32ce4..406ed08 100644 --- a/submodule.go +++ b/submodule.go @@ -21,6 +21,18 @@ type SubmoduleUpdateOptions struct { // Submodule type Submodule struct { ptr *C.git_submodule + r *Repository +} + +func newSubmoduleFromC(ptr *C.git_submodule, r *Repository) *Submodule { + s := &Submodule{ptr: ptr, r: r} + runtime.SetFinalizer(s, (*Submodule).Free) + return s +} + +func (sub *Submodule) Free() { + runtime.SetFinalizer(sub, nil) + C.git_submodule_free(sub.ptr) } type SubmoduleUpdate int @@ -82,24 +94,24 @@ func (c *SubmoduleCollection) Lookup(name string) (*Submodule, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - sub := new(Submodule) + var ptr *C.git_submodule runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_submodule_lookup(&sub.ptr, c.repo.ptr, cname) + ret := C.git_submodule_lookup(&ptr, c.repo.ptr, cname) if ret < 0 { return nil, MakeGitError(ret) } - return sub, nil + return newSubmoduleFromC(ptr, c.repo), nil } type SubmoduleCbk func(sub *Submodule, name string) int //export SubmoduleVisitor func SubmoduleVisitor(csub unsafe.Pointer, name *C.char, handle unsafe.Pointer) C.int { - sub := &Submodule{(*C.git_submodule)(csub)} + sub := &Submodule{(*C.git_submodule)(csub), nil} if callback, ok := pointerHandles.Get(handle).(SubmoduleCbk); ok { return (C.int)(callback(sub, C.GoString(name))) @@ -116,6 +128,7 @@ func (c *SubmoduleCollection) Foreach(cbk SubmoduleCbk) error { defer pointerHandles.Untrack(handle) ret := C._go_git_visit_submodule(c.repo.ptr, handle) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -128,16 +141,15 @@ func (c *SubmoduleCollection) Add(url, path string, use_git_link bool) (*Submodu cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) - sub := new(Submodule) - runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_submodule_add_setup(&sub.ptr, c.repo.ptr, curl, cpath, cbool(use_git_link)) + var ptr *C.git_submodule + ret := C.git_submodule_add_setup(&ptr, c.repo.ptr, curl, cpath, cbool(use_git_link)) if ret < 0 { return nil, MakeGitError(ret) } - return sub, nil + return newSubmoduleFromC(ptr, c.repo), nil } func (sub *Submodule) FinalizeAdd() error { @@ -145,6 +157,7 @@ func (sub *Submodule) FinalizeAdd() error { defer runtime.UnlockOSThread() ret := C.git_submodule_add_finalize(sub.ptr) + runtime.KeepAlive(sub) if ret < 0 { return MakeGitError(ret) } @@ -156,6 +169,7 @@ func (sub *Submodule) AddToIndex(write_index bool) error { defer runtime.UnlockOSThread() ret := C.git_submodule_add_to_index(sub.ptr, cbool(write_index)) + runtime.KeepAlive(sub) if ret < 0 { return MakeGitError(ret) } @@ -163,18 +177,21 @@ func (sub *Submodule) AddToIndex(write_index bool) error { } func (sub *Submodule) Name() string { - n := C.git_submodule_name(sub.ptr) - return C.GoString(n) + n := C.GoString(C.git_submodule_name(sub.ptr)) + runtime.KeepAlive(sub) + return n } func (sub *Submodule) Path() string { - n := C.git_submodule_path(sub.ptr) - return C.GoString(n) + n := C.GoString(C.git_submodule_path(sub.ptr)) + runtime.KeepAlive(sub) + return n } func (sub *Submodule) Url() string { - n := C.git_submodule_url(sub.ptr) - return C.GoString(n) + n := C.GoString(C.git_submodule_url(sub.ptr)) + runtime.KeepAlive(sub) + return n } func (c *SubmoduleCollection) SetUrl(submodule, url string) error { @@ -187,6 +204,7 @@ func (c *SubmoduleCollection) SetUrl(submodule, url string) error { defer runtime.UnlockOSThread() ret := C.git_submodule_set_url(c.repo.ptr, csubmodule, curl) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -194,31 +212,38 @@ func (c *SubmoduleCollection) SetUrl(submodule, url string) error { } func (sub *Submodule) IndexId() *Oid { + var id *Oid idx := C.git_submodule_index_id(sub.ptr) - if idx == nil { - return nil + if idx != nil { + id = newOidFromC(idx) } - return newOidFromC(idx) + runtime.KeepAlive(sub) + return id } func (sub *Submodule) HeadId() *Oid { + var id *Oid idx := C.git_submodule_head_id(sub.ptr) - if idx == nil { - return nil + if idx != nil { + id = newOidFromC(idx) } - return newOidFromC(idx) + runtime.KeepAlive(sub) + return id } func (sub *Submodule) WdId() *Oid { + var id *Oid idx := C.git_submodule_wd_id(sub.ptr) - if idx == nil { - return nil + if idx != nil { + id = newOidFromC(idx) } - return newOidFromC(idx) + runtime.KeepAlive(sub) + return id } func (sub *Submodule) Ignore() SubmoduleIgnore { o := C.git_submodule_ignore(sub.ptr) + runtime.KeepAlive(sub) return SubmoduleIgnore(o) } @@ -230,6 +255,7 @@ func (c *SubmoduleCollection) SetIgnore(submodule string, ignore SubmoduleIgnore defer runtime.UnlockOSThread() ret := C.git_submodule_set_ignore(c.repo.ptr, csubmodule, C.git_submodule_ignore_t(ignore)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -239,6 +265,7 @@ func (c *SubmoduleCollection) SetIgnore(submodule string, ignore SubmoduleIgnore func (sub *Submodule) UpdateStrategy() SubmoduleUpdate { o := C.git_submodule_update_strategy(sub.ptr) + runtime.KeepAlive(sub) return SubmoduleUpdate(o) } @@ -250,6 +277,7 @@ func (c *SubmoduleCollection) SetUpdate(submodule string, update SubmoduleUpdate defer runtime.UnlockOSThread() ret := C.git_submodule_set_update(c.repo.ptr, csubmodule, C.git_submodule_update_t(update)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -269,6 +297,7 @@ func (c *SubmoduleCollection) SetFetchRecurseSubmodules(submodule string, recurs defer runtime.UnlockOSThread() ret := C.git_submodule_set_fetch_recurse_submodules(c.repo.ptr, csubmodule, C.git_submodule_recurse_t(recurse)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(C.int(ret)) } @@ -280,6 +309,7 @@ func (sub *Submodule) Init(overwrite bool) error { defer runtime.UnlockOSThread() ret := C.git_submodule_init(sub.ptr, cbool(overwrite)) + runtime.KeepAlive(sub) if ret < 0 { return MakeGitError(ret) } @@ -291,6 +321,7 @@ func (sub *Submodule) Sync() error { defer runtime.UnlockOSThread() ret := C.git_submodule_sync(sub.ptr) + runtime.KeepAlive(sub) if ret < 0 { return MakeGitError(ret) } @@ -303,6 +334,7 @@ func (sub *Submodule) Open() (*Repository, error) { var ptr *C.git_repository ret := C.git_submodule_open(&ptr, sub.ptr) + runtime.KeepAlive(sub) if ret < 0 { return nil, MakeGitError(ret) } @@ -320,6 +352,7 @@ func (sub *Submodule) Update(init bool, opts *SubmoduleUpdateOptions) error { defer runtime.UnlockOSThread() ret := C.git_submodule_update(sub.ptr, cbool(init), &copts) + runtime.KeepAlive(sub) if ret < 0 { return MakeGitError(ret) } diff --git a/tag.go b/tag.go index 81d7258..a58b090 100644 --- a/tag.go +++ b/tag.go @@ -18,22 +18,28 @@ type Tag struct { } func (t Tag) Message() string { - return C.GoString(C.git_tag_message(t.cast_ptr)) + ret := C.GoString(C.git_tag_message(t.cast_ptr)) + runtime.KeepAlive(t) + return ret } func (t Tag) Name() string { - return C.GoString(C.git_tag_name(t.cast_ptr)) + ret := C.GoString(C.git_tag_name(t.cast_ptr)) + runtime.KeepAlive(t) + return ret } func (t Tag) Tagger() *Signature { cast_ptr := C.git_tag_tagger(t.cast_ptr) - return newSignatureFromC(cast_ptr) + ret := newSignatureFromC(cast_ptr) + runtime.KeepAlive(t) + return ret } func (t Tag) Target() *Object { var ptr *C.git_object ret := C.git_tag_target(&ptr, t.cast_ptr) - + runtime.KeepAlive(t) if ret != 0 { return nil } @@ -42,11 +48,15 @@ func (t Tag) Target() *Object { } func (t Tag) TargetId() *Oid { - return newOidFromC(C.git_tag_target_id(t.cast_ptr)) + ret := newOidFromC(C.git_tag_target_id(t.cast_ptr)) + runtime.KeepAlive(t) + return ret } func (t Tag) TargetType() ObjectType { - return ObjectType(C.git_tag_target_type(t.cast_ptr)) + ret := ObjectType(C.git_tag_target_type(t.cast_ptr)) + runtime.KeepAlive(t) + return ret } type TagsCollection struct { @@ -76,6 +86,7 @@ func (c *TagsCollection) Create( defer runtime.UnlockOSThread() ret := C.git_tag_create(oid.toC(), c.repo.ptr, cname, ctarget, taggerSig, cmessage, 0) + runtime.KeepAlive(c) if ret < 0 { return nil, MakeGitError(ret) } @@ -91,6 +102,7 @@ func (c *TagsCollection) Remove(name string) error { defer C.free(unsafe.Pointer(cname)) ret := C.git_tag_delete(c.repo.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -123,6 +135,7 @@ func (c *TagsCollection) CreateLightweight(name string, commit *Commit, force bo defer runtime.UnlockOSThread() err := C.git_tag_create_lightweight(oid.toC(), c.repo.ptr, cname, ctarget, cbool(force)) + runtime.KeepAlive(c) if err < 0 { return nil, MakeGitError(err) } @@ -139,6 +152,7 @@ func (c *TagsCollection) List() ([]string, error) { defer runtime.UnlockOSThread() ecode := C.git_tag_list(&strC, c.repo.ptr) + runtime.KeepAlive(c) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -162,6 +176,7 @@ func (c *TagsCollection) ListWithMatch(pattern string) ([]string, error) { defer runtime.UnlockOSThread() ecode := C.git_tag_list_match(&strC, patternC, c.repo.ptr) + runtime.KeepAlive(c) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -215,6 +230,7 @@ func (c *TagsCollection) Foreach(callback TagForeachCallback) error { defer runtime.UnlockOSThread() err := C._go_git_tag_foreach(c.repo.ptr, handle) + runtime.KeepAlive(c) if err == C.GIT_EUSER { return data.err } diff --git a/tree.go b/tree.go index 27dd63d..f5cbd78 100644 --- a/tree.go +++ b/tree.go @@ -48,6 +48,7 @@ func (t Tree) EntryByName(filename string) *TreeEntry { defer C.free(unsafe.Pointer(cname)) entry := C.git_tree_entry_byname(t.cast_ptr, cname) + runtime.KeepAlive(t) if entry == nil { return nil } @@ -66,6 +67,8 @@ func (t Tree) EntryById(id *Oid) *TreeEntry { defer runtime.UnlockOSThread() entry := C.git_tree_entry_byid(t.cast_ptr, id.toC()) + runtime.KeepAlive(t) + runtime.KeepAlive(id) if entry == nil { return nil } @@ -84,6 +87,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { defer runtime.UnlockOSThread() ret := C.git_tree_entry_bypath(&entry, t.cast_ptr, cpath) + runtime.KeepAlive(t) if ret < 0 { return nil, MakeGitError(ret) } @@ -94,6 +98,7 @@ func (t Tree) EntryByPath(path string) (*TreeEntry, error) { func (t Tree) EntryByIndex(index uint64) *TreeEntry { entry := C.git_tree_entry_byindex(t.cast_ptr, C.size_t(index)) + runtime.KeepAlive(t) if entry == nil { return nil } @@ -103,6 +108,7 @@ func (t Tree) EntryByIndex(index uint64) *TreeEntry { func (t Tree) EntryCount() uint64 { num := C.git_tree_entrycount(t.cast_ptr) + runtime.KeepAlive(t) return uint64(num) } @@ -132,7 +138,7 @@ func (t Tree) Walk(callback TreeWalkCallback) error { C.GIT_TREEWALK_PRE, ptr, ) - + runtime.KeepAlive(t) if err < 0 { return MakeGitError(err) } @@ -158,6 +164,8 @@ func (v *TreeBuilder) Insert(filename string, id *Oid, filemode Filemode) error defer runtime.UnlockOSThread() err := C.git_treebuilder_insert(nil, v.ptr, cfilename, id.toC(), C.git_filemode_t(filemode)) + runtime.KeepAlive(v) + runtime.KeepAlive(id) if err < 0 { return MakeGitError(err) } @@ -173,6 +181,7 @@ func (v *TreeBuilder) Remove(filename string) error { defer runtime.UnlockOSThread() err := C.git_treebuilder_remove(v.ptr, cfilename) + runtime.KeepAlive(v) if err < 0 { return MakeGitError(err) } @@ -187,7 +196,7 @@ func (v *TreeBuilder) Write() (*Oid, error) { defer runtime.UnlockOSThread() err := C.git_treebuilder_write(oid.toC(), v.ptr) - + runtime.KeepAlive(v) if err < 0 { return nil, MakeGitError(err) } diff --git a/walk.go b/walk.go index ab1de61..287edb6 100644 --- a/walk.go +++ b/walk.go @@ -34,6 +34,7 @@ func revWalkFromC(repo *Repository, c *C.git_revwalk) *RevWalk { func (v *RevWalk) Reset() { C.git_revwalk_reset(v.ptr) + runtime.KeepAlive(v) } func (v *RevWalk) Push(id *Oid) error { @@ -41,6 +42,8 @@ func (v *RevWalk) Push(id *Oid) error { defer runtime.UnlockOSThread() ecode := C.git_revwalk_push(v.ptr, id.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(id) if ecode < 0 { return MakeGitError(ecode) } @@ -55,6 +58,7 @@ func (v *RevWalk) PushGlob(glob string) error { defer C.free(unsafe.Pointer(cstr)) ecode := C.git_revwalk_push_glob(v.ptr, cstr) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -69,6 +73,7 @@ func (v *RevWalk) PushRange(r string) error { defer C.free(unsafe.Pointer(cstr)) ecode := C.git_revwalk_push_range(v.ptr, cstr) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -83,6 +88,7 @@ func (v *RevWalk) PushRef(r string) error { defer C.free(unsafe.Pointer(cstr)) ecode := C.git_revwalk_push_ref(v.ptr, cstr) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -94,6 +100,7 @@ func (v *RevWalk) PushHead() (err error) { defer runtime.UnlockOSThread() ecode := C.git_revwalk_push_head(v.ptr) + runtime.KeepAlive(v) if ecode < 0 { err = MakeGitError(ecode) } @@ -105,6 +112,8 @@ func (v *RevWalk) Hide(id *Oid) error { defer runtime.UnlockOSThread() ecode := C.git_revwalk_hide(v.ptr, id.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(id) if ecode < 0 { return MakeGitError(ecode) } @@ -119,6 +128,7 @@ func (v *RevWalk) HideGlob(glob string) error { defer C.free(unsafe.Pointer(cstr)) ecode := C.git_revwalk_hide_glob(v.ptr, cstr) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -133,6 +143,7 @@ func (v *RevWalk) HideRef(r string) error { defer C.free(unsafe.Pointer(cstr)) ecode := C.git_revwalk_hide_ref(v.ptr, cstr) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -144,6 +155,7 @@ func (v *RevWalk) HideHead() (err error) { defer runtime.UnlockOSThread() ecode := C.git_revwalk_hide_head(v.ptr) + runtime.KeepAlive(v) if ecode < 0 { err = MakeGitError(ecode) } @@ -155,6 +167,7 @@ func (v *RevWalk) Next(id *Oid) (err error) { defer runtime.UnlockOSThread() ret := C.git_revwalk_next(id.toC(), v.ptr) + runtime.KeepAlive(v) switch { case ret < 0: err = MakeGitError(ret) @@ -192,14 +205,15 @@ func (v *RevWalk) Iterate(fun RevWalkIterator) (err error) { func (v *RevWalk) SimplifyFirstParent() { C.git_revwalk_simplify_first_parent(v.ptr) + runtime.KeepAlive(v) } func (v *RevWalk) Sorting(sm SortType) { C.git_revwalk_sorting(v.ptr, C.uint(sm)) + runtime.KeepAlive(v) } func (v *RevWalk) Free() { - runtime.SetFinalizer(v, nil) C.git_revwalk_free(v.ptr) }