From 5d466ffbc00bc2fbde0f0589c70e23b8fc7cc7d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 7 Jul 2017 23:24:54 +0200 Subject: [PATCH 1/5] commit: add thread locking to signature extraction --- commit.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/commit.go b/commit.go index fc2815a..fc04e1e 100644 --- a/commit.go +++ b/commit.go @@ -35,16 +35,18 @@ func (c Commit) ExtractSignature() (string, string, error) { defer C.git_buf_free(&c_signature) oid := c.Id() - repo := C.git_commit_owner(c.cast_ptr) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() ret := C.git_commit_extract_signature(&c_signature, &c_signed, repo, oid.toC(), nil) - + if ret < 0 { - return "", "", MakeGitError(ret) + return "", "", MakeGitError(ret) } else { return C.GoString(c_signature.ptr), C.GoString(c_signed.ptr), nil } - + } func (c Commit) Summary() string { From 0e9336be3f590b900a28a48b265dd2eab7836e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 7 Jul 2017 23:36:04 +0200 Subject: [PATCH 2/5] commit: add keep-alives for those that need conversion to pointer receivers We can't work on the copies here, we need to have pointer receivers so we know we're keeping alive the object whose finalizer would free the unmanaged memory we're working with. --- commit.go | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/commit.go b/commit.go index fc04e1e..3ccb5da 100644 --- a/commit.go +++ b/commit.go @@ -18,15 +18,19 @@ type Commit struct { cast_ptr *C.git_commit } -func (c Commit) Message() string { - return C.GoString(C.git_commit_message(c.cast_ptr)) +func (c *Commit) Message() string { + ret := C.GoString(C.git_commit_message(c.cast_ptr)) + runtime.KeepAlive(c) + return ret } -func (c Commit) RawMessage() string { - return C.GoString(C.git_commit_message_raw(c.cast_ptr)) +func (c *Commit) RawMessage() string { + ret := C.GoString(C.git_commit_message_raw(c.cast_ptr)) + runtime.KeepAlive(c) + return ret } -func (c Commit) ExtractSignature() (string, string, error) { +func (c *Commit) ExtractSignature() (string, string, error) { var c_signed C.git_buf defer C.git_buf_free(&c_signed) @@ -40,7 +44,7 @@ func (c Commit) ExtractSignature() (string, string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_commit_extract_signature(&c_signature, &c_signed, repo, oid.toC(), nil) - + runtime.KeepAlive(oid) if ret < 0 { return "", "", MakeGitError(ret) } else { @@ -49,17 +53,20 @@ func (c Commit) ExtractSignature() (string, string, error) { } -func (c Commit) Summary() string { - return C.GoString(C.git_commit_summary(c.cast_ptr)) +func (c *Commit) Summary() string { + ret := C.GoString(C.git_commit_summary(c.cast_ptr)) + runtime.KeepAlive(c) + return ret } -func (c Commit) Tree() (*Tree, error) { +func (c *Commit) Tree() (*Tree, error) { var ptr *C.git_tree runtime.LockOSThread() defer runtime.UnlockOSThread() err := C.git_commit_tree(&ptr, c.cast_ptr) + runtime.KeepAlive(c) if err < 0 { return nil, MakeGitError(err) } @@ -67,18 +74,24 @@ func (c Commit) Tree() (*Tree, error) { return allocTree(ptr, c.repo), nil } -func (c Commit) TreeId() *Oid { - return newOidFromC(C.git_commit_tree_id(c.cast_ptr)) +func (c *Commit) TreeId() *Oid { + ret := newOidFromC(C.git_commit_tree_id(c.cast_ptr)) + runtime.KeepAlive(c) + return c } -func (c Commit) Author() *Signature { +func (c *Commit) Author() *Signature { cast_ptr := C.git_commit_author(c.cast_ptr) - return newSignatureFromC(cast_ptr) + ret := newSignatureFromC(cast_ptr) + runtime.KeepAlive(c) + return ret } -func (c Commit) Committer() *Signature { +func (c *Commit) Committer() *Signature { cast_ptr := C.git_commit_committer(c.cast_ptr) - return newSignatureFromC(cast_ptr) + ret := newSignatureFromC(cast_ptr) + runtime.KeepAlive(c) + return ret } func (c *Commit) Parent(n uint) *Commit { From 58334cf60441bd713b8fd990e30e0580b97bf3ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 7 Jul 2017 23:45:09 +0200 Subject: [PATCH 3/5] First round of mass keep-alive additions --- blame.go | 8 +++++++- blob.go | 23 +++++++++++++++++------ branch.go | 12 ++++++++++++ checkout.go | 3 +++ cherrypick.go | 2 ++ commit.go | 17 +++++++++++++---- config.go | 29 +++++++++++++++++++++++------ describe.go | 3 +++ repository.go | 47 ++++++++++++++++++++++++++++++++++++++++------- 9 files changed, 120 insertions(+), 24 deletions(-) diff --git a/blame.go b/blame.go index b07d6bc..de32bb3 100644 --- a/blame.go +++ b/blame.go @@ -76,6 +76,7 @@ func (v *Repository) BlameFile(path string, opts *BlameOptions) (*Blame, error) defer runtime.UnlockOSThread() ecode := C.git_blame_file(&blamePtr, v.ptr, cpath, copts) + runtime.KeepAlive(v) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -88,11 +89,15 @@ type Blame struct { } func (blame *Blame) HunkCount() int { - return int(C.git_blame_get_hunk_count(blame.ptr)) + ret := int(C.git_blame_get_hunk_count(blame.ptr)) + runtime.KeepAlive(blame) + + return ret } func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) { ptr := C.git_blame_get_hunk_byindex(blame.ptr, C.uint32_t(index)) + runtime.KeepAlive(blame) if ptr == nil { return BlameHunk{}, ErrInvalid } @@ -101,6 +106,7 @@ func (blame *Blame) HunkByIndex(index int) (BlameHunk, error) { func (blame *Blame) HunkByLine(lineno int) (BlameHunk, error) { ptr := C.git_blame_get_hunk_byline(blame.ptr, C.size_t(lineno)) + runtime.KeepAlive(blame) if ptr == nil { return BlameHunk{}, ErrInvalid } diff --git a/blob.go b/blob.go index 73a4a19..5235597 100644 --- a/blob.go +++ b/blob.go @@ -21,13 +21,19 @@ type Blob struct { } func (v *Blob) Size() int64 { - return int64(C.git_blob_rawsize(v.cast_ptr)) + ret := int64(C.git_blob_rawsize(v.cast_ptr)) + runtime.KeepAlive(v) + return ret } func (v *Blob) Contents() []byte { size := C.int(C.git_blob_rawsize(v.cast_ptr)) buffer := unsafe.Pointer(C.git_blob_rawcontent(v.cast_ptr)) - return C.GoBytes(buffer, size) + + goBytes := C.GoBytes(buffer, size) + runtime.KeepAlive(v) + + return goBytes } func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) { @@ -53,6 +59,7 @@ func (repo *Repository) CreateBlobFromBuffer(data []byte) (*Oid, error) { } ecode := C.git_blob_create_frombuffer(&id, repo.ptr, unsafe.Pointer(&data[0]), size) + runtime.KeepAlive(repo) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -102,16 +109,18 @@ func (repo *Repository) CreateFromStream(hintPath string) (*BlobWriteStream, err return nil, MakeGitError(ecode) } - return newBlobWriteStreamFromC(stream), nil + return newBlobWriteStreamFromC(stream, repo), nil } type BlobWriteStream struct { - ptr *C.git_writestream + ptr *C.git_writestream + repo *Repository } -func newBlobWriteStreamFromC(ptr *C.git_writestream) *BlobWriteStream { +func newBlobWriteStreamFromC(ptr *C.git_writestream, repo *Repository) *BlobWriteStream { stream := &BlobWriteStream{ - ptr: ptr, + ptr: ptr, + repo: repo, } runtime.SetFinalizer(stream, (*BlobWriteStream).Free) @@ -128,6 +137,7 @@ func (stream *BlobWriteStream) Write(p []byte) (int, error) { defer runtime.UnlockOSThread() ecode := C._go_git_writestream_write(stream.ptr, ptr, size) + runtime.KeepAlive(stream) if ecode < 0 { return 0, MakeGitError(ecode) } @@ -147,6 +157,7 @@ func (stream *BlobWriteStream) Commit() (*Oid, error) { defer runtime.UnlockOSThread() ecode := C.git_blob_create_fromstream_commit(&oid, stream.ptr) + runtime.KeepAlive(stream) if ecode < 0 { return nil, MakeGitError(ecode) } diff --git a/branch.go b/branch.go index d381c23..d6e7a53 100644 --- a/branch.go +++ b/branch.go @@ -88,6 +88,7 @@ func (repo *Repository) NewBranchIterator(flags BranchType) (*BranchIterator, er defer runtime.UnlockOSThread() ecode := C.git_branch_iterator_new(&ptr, repo.ptr, refType) + runtime.KeepAlive(repo) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -106,6 +107,8 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo defer runtime.UnlockOSThread() ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce) + runtime.KeepAlive(repo) + runtime.KeepAlive(target) if ret < 0 { return nil, MakeGitError(ret) } @@ -117,6 +120,7 @@ func (b *Branch) Delete() error { runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_delete(b.Reference.ptr) + runtime.KeepAlive(b.Reference) if ret < 0 { return MakeGitError(ret) } @@ -133,6 +137,7 @@ func (b *Branch) Move(newBranchName string, force bool) (*Branch, error) { defer runtime.UnlockOSThread() ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce) + runtime.KeepAlive(b.Reference) if ret < 0 { return nil, MakeGitError(ret) } @@ -145,6 +150,7 @@ func (b *Branch) IsHead() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_branch_is_head(b.Reference.ptr) + runtime.KeepAlive(b.Reference) switch ret { case 1: return true, nil @@ -165,6 +171,7 @@ func (repo *Repository) LookupBranch(branchName string, bt BranchType) (*Branch, defer runtime.UnlockOSThread() ret := C.git_branch_lookup(&ptr, repo.ptr, cName, C.git_branch_t(bt)) + runtime.KeepAlive(repo) if ret < 0 { return nil, MakeGitError(ret) } @@ -179,6 +186,7 @@ func (b *Branch) Name() (string, error) { defer runtime.UnlockOSThread() ret := C.git_branch_name(&cName, b.Reference.ptr) + runtime.KeepAlive(b.Reference) if ret < 0 { return "", MakeGitError(ret) } @@ -196,6 +204,7 @@ func (repo *Repository) RemoteName(canonicalBranchName string) (string, error) { defer runtime.UnlockOSThread() ret := C.git_branch_remote_name(&nameBuf, repo.ptr, cName) + runtime.KeepAlive(repo) if ret < 0 { return "", MakeGitError(ret) } @@ -212,6 +221,7 @@ func (b *Branch) SetUpstream(upstreamName string) error { defer runtime.UnlockOSThread() ret := C.git_branch_set_upstream(b.Reference.ptr, cName) + runtime.KeepAlive(b.Reference) if ret < 0 { return MakeGitError(ret) } @@ -225,6 +235,7 @@ func (b *Branch) Upstream() (*Reference, error) { defer runtime.UnlockOSThread() ret := C.git_branch_upstream(&ptr, b.Reference.ptr) + runtime.KeepAlive(b.Reference) if ret < 0 { return nil, MakeGitError(ret) } @@ -241,6 +252,7 @@ func (repo *Repository) UpstreamName(canonicalBranchName string) (string, error) defer runtime.UnlockOSThread() ret := C.git_branch_upstream_name(&nameBuf, repo.ptr, cName) + runtime.KeepAlive(repo) if ret < 0 { return "", MakeGitError(ret) } diff --git a/checkout.go b/checkout.go index f5822c9..db3118f 100644 --- a/checkout.go +++ b/checkout.go @@ -188,6 +188,7 @@ func (v *Repository) CheckoutHead(opts *CheckoutOpts) error { defer freeCheckoutOpts(cOpts) ret := C.git_checkout_head(v.ptr, cOpts) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -211,6 +212,7 @@ func (v *Repository) CheckoutIndex(index *Index, opts *CheckoutOpts) error { defer freeCheckoutOpts(cOpts) ret := C.git_checkout_index(v.ptr, iptr, cOpts) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -226,6 +228,7 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error { defer freeCheckoutOpts(cOpts) ret := C.git_checkout_tree(v.ptr, tree.ptr, cOpts) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } diff --git a/cherrypick.go b/cherrypick.go index afc1b7e..8983a7a 100644 --- a/cherrypick.go +++ b/cherrypick.go @@ -66,6 +66,8 @@ func (v *Repository) Cherrypick(commit *Commit, opts CherrypickOptions) error { defer freeCherrypickOpts(cOpts) ecode := C.git_cherrypick(v.ptr, commit.cast_ptr, cOpts) + runtime.KeepAlive(v) + runtime.KeepAlive(commit) if ecode < 0 { return MakeGitError(ecode) } diff --git a/commit.go b/commit.go index 3ccb5da..5aa5f25 100644 --- a/commit.go +++ b/commit.go @@ -77,7 +77,7 @@ func (c *Commit) Tree() (*Tree, error) { func (c *Commit) TreeId() *Oid { ret := newOidFromC(C.git_commit_tree_id(c.cast_ptr)) runtime.KeepAlive(c) - return c + return ret } func (c *Commit) Author() *Signature { @@ -101,15 +101,21 @@ func (c *Commit) Parent(n uint) *Commit { return nil } - return allocCommit(cobj, c.repo) + parent := allocCommit(cobj, c.repo) + runtime.KeepAlive(c) + return parent } func (c *Commit) ParentId(n uint) *Oid { - return newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n))) + ret := newOidFromC(C.git_commit_parent_id(c.cast_ptr, C.uint(n))) + runtime.KeepAlive(c) + return ret } func (c *Commit) ParentCount() uint { - return uint(C.git_commit_parentcount(c.cast_ptr)) + ret := uint(C.git_commit_parentcount(c.cast_ptr)) + runtime.KeepAlive(c) + return ret } func (c *Commit) Amend(refname string, author, committer *Signature, message string, tree *Tree) (*Oid, error) { @@ -142,6 +148,9 @@ func (c *Commit) Amend(refname string, author, committer *Signature, message str oid := new(Oid) cerr := C.git_commit_amend(oid.toC(), c.cast_ptr, cref, authorSig, committerSig, nil, cmsg, tree.cast_ptr) + runtime.KeepAlive(oid) + runtime.KeepAlive(c) + runtime.KeepAlive(tree) if cerr < 0 { return nil, MakeGitError(cerr) } diff --git a/config.go b/config.go index 7408fbc..c19ad32 100644 --- a/config.go +++ b/config.go @@ -78,6 +78,7 @@ func (c *Config) AddFile(path string, level ConfigLevel, force bool) error { defer runtime.UnlockOSThread() ret := C.git_config_add_file_ondisk(c.ptr, cpath, C.git_config_level_t(level), cbool(force)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -94,6 +95,7 @@ func (c *Config) LookupInt32(name string) (int32, error) { defer runtime.UnlockOSThread() ret := C.git_config_get_int32(&out, c.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return 0, MakeGitError(ret) } @@ -110,6 +112,7 @@ func (c *Config) LookupInt64(name string) (int64, error) { defer runtime.UnlockOSThread() ret := C.git_config_get_int64(&out, c.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return 0, MakeGitError(ret) } @@ -126,7 +129,9 @@ func (c *Config) LookupString(name string) (string, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname); ret < 0 { + ret := C.git_config_get_string_buf(&valBuf, c.ptr, cname) + runtime.KeepAlive(c) + if ret < 0 { return "", MakeGitError(ret) } defer C.git_buf_free(&valBuf) @@ -143,6 +148,7 @@ func (c *Config) LookupBool(name string) (bool, error) { defer runtime.UnlockOSThread() ret := C.git_config_get_bool(&out, c.ptr, cname) + runtime.KeepAlive(c) if ret < 0 { return false, MakeGitError(ret) } @@ -162,7 +168,7 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro defer C.free(unsafe.Pointer(cregexp)) } - iter := new(ConfigIterator) + iter := &ConfigIterator{cfg: c} runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -179,7 +185,7 @@ func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, erro // NewIterator creates an iterator over each entry in the // configuration func (c *Config) NewIterator() (*ConfigIterator, error) { - iter := new(ConfigIterator) + iter := &ConfigIterator{cfg: c} runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -195,7 +201,7 @@ func (c *Config) NewIterator() (*ConfigIterator, error) { // NewIteratorGlob creates an iterator over each entry in the // configuration whose name matches the given regular expression func (c *Config) NewIteratorGlob(regexp string) (*ConfigIterator, error) { - iter := new(ConfigIterator) + iter := &ConfigIterator{cfg: c} cregexp := C.CString(regexp) defer C.free(unsafe.Pointer(cregexp)) @@ -221,6 +227,7 @@ func (c *Config) SetString(name, value string) (err error) { defer runtime.UnlockOSThread() ret := C.git_config_set_string(c.ptr, cname, cvalue) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -241,6 +248,7 @@ func (c *Config) SetInt32(name string, value int32) (err error) { defer runtime.UnlockOSThread() ret := C.git_config_set_int32(c.ptr, cname, C.int32_t(value)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -256,6 +264,7 @@ func (c *Config) SetInt64(name string, value int64) (err error) { defer runtime.UnlockOSThread() ret := C.git_config_set_int64(c.ptr, cname, C.int64_t(value)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -271,6 +280,7 @@ func (c *Config) SetBool(name string, value bool) (err error) { defer runtime.UnlockOSThread() ret := C.git_config_set_bool(c.ptr, cname, cbool(value)) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -292,6 +302,7 @@ func (c *Config) SetMultivar(name, regexp, value string) (err error) { defer runtime.UnlockOSThread() ret := C.git_config_set_multivar(c.ptr, cname, cregexp, cvalue) + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -307,7 +318,7 @@ func (c *Config) Delete(name string) error { defer runtime.UnlockOSThread() ret := C.git_config_delete_entry(c.ptr, cname) - + runtime.KeepAlive(c) if ret < 0 { return MakeGitError(ret) } @@ -323,6 +334,8 @@ func (c *Config) OpenLevel(parent *Config, level ConfigLevel) (*Config, error) { defer runtime.UnlockOSThread() ret := C.git_config_open_level(&config.ptr, parent.ptr, C.git_config_level_t(level)) + runtime.KeepAlive(c) + runtime.KeepAlive(parent) if ret < 0 { return nil, MakeGitError(ret) } @@ -349,6 +362,7 @@ func OpenOndisk(parent *Config, path string) (*Config, error) { type ConfigIterator struct { ptr *C.git_config_iterator + cfg *Config } // Next returns the next entry for this iterator @@ -363,7 +377,10 @@ func (iter *ConfigIterator) Next() (*ConfigEntry, error) { return nil, MakeGitError(ret) } - return newConfigEntryFromC(centry), nil + entry := newConfigEntryFromC(centry) + runtime.KeepAlive(iter) + + return entry, nil } func (iter *ConfigIterator) Free() { diff --git a/describe.go b/describe.go index d75dbcb..0b75076 100644 --- a/describe.go +++ b/describe.go @@ -128,6 +128,7 @@ func (c *Commit) Describe(opts *DescribeOptions) (*DescribeResult, error) { defer runtime.UnlockOSThread() ecode := C.git_describe_commit(&resultPtr, c.ptr, cDescribeOpts) + runtime.KeepAlive(c) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -162,6 +163,7 @@ func (repo *Repository) DescribeWorkdir(opts *DescribeOptions) (*DescribeResult, defer runtime.UnlockOSThread() ecode := C.git_describe_workdir(&resultPtr, repo.ptr, cDescribeOpts) + runtime.KeepAlive(repo) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -206,6 +208,7 @@ func (result *DescribeResult) Format(opts *DescribeFormatOptions) (string, error defer runtime.UnlockOSThread() ecode := C.git_describe_format(&resultBuf, result.ptr, cFormatOpts) + runtime.KeepAlive(result) if ecode < 0 { return "", MakeGitError(ecode) } diff --git a/repository.go b/repository.go index a44b9b8..44d18a9 100644 --- a/repository.go +++ b/repository.go @@ -129,6 +129,7 @@ func NewRepositoryWrapOdb(odb *Odb) (repo *Repository, err error) { func (v *Repository) SetRefdb(refdb *Refdb) { C.git_repository_set_refdb(v.ptr, refdb.ptr) + runtime.KeepAlive(v) } func (v *Repository) Free() { @@ -143,6 +144,7 @@ func (v *Repository) Config() (*Config, error) { defer runtime.UnlockOSThread() ret := C.git_repository_config(&config.ptr, v.ptr) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -158,6 +160,7 @@ func (v *Repository) Index() (*Index, error) { defer runtime.UnlockOSThread() ret := C.git_repository_index(&ptr, v.ptr) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -172,6 +175,7 @@ func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) { defer runtime.UnlockOSThread() ret := C.git_object_lookup(&ptr, v.ptr, id.toC(), C.git_otype(t)) + runtime.KeepAlive(id) if ret < 0 { return nil, MakeGitError(ret) } @@ -241,6 +245,7 @@ func (v *Repository) SetHead(refname string) error { defer runtime.UnlockOSThread() ecode := C.git_repository_set_head(v.ptr, cname) + runtime.KeepAlive(v) if ecode != 0 { return MakeGitError(ecode) } @@ -252,6 +257,8 @@ func (v *Repository) SetHeadDetached(id *Oid) error { defer runtime.UnlockOSThread() ecode := C.git_repository_set_head_detached(v.ptr, id.toC()) + runtime.KeepAlive(v) + runtime.KeepAlive(id) if ecode != 0 { return MakeGitError(ecode) } @@ -263,6 +270,7 @@ func (v *Repository) IsHeadDetached() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_repository_head_detached(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return false, MakeGitError(ret) } @@ -275,6 +283,7 @@ func (v *Repository) IsHeadUnborn() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_repository_head_unborn(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return false, MakeGitError(ret) } @@ -286,6 +295,7 @@ func (v *Repository) IsEmpty() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_repository_is_empty(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return false, MakeGitError(ret) } @@ -298,6 +308,7 @@ func (v *Repository) IsShallow() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_repository_is_shallow(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return false, MakeGitError(ret) } @@ -368,6 +379,9 @@ func (v *Repository) CreateCommit( authorSig, committerSig, nil, cmsg, tree.cast_ptr, C.size_t(nparents), parentsarg) + runtime.KeepAlive(v) + runtime.KeepAlive(oid) + runtime.KeepAlive(parents) if ret < 0 { return nil, MakeGitError(ret) } @@ -391,7 +405,9 @@ func (v *Repository) Odb() (odb *Odb, err error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 { + ret := C.git_repository_odb(&odb.ptr, v.ptr) + runtime.KeepAlive(v) + if ret < 0 { return nil, MakeGitError(ret) } @@ -400,15 +416,21 @@ func (v *Repository) Odb() (odb *Odb, err error) { } func (repo *Repository) Path() string { - return C.GoString(C.git_repository_path(repo.ptr)) + s := C.GoString(C.git_repository_path(repo.ptr)) + runtime.KeepAlive(repo) + return s } func (repo *Repository) IsBare() bool { - return C.git_repository_is_bare(repo.ptr) != 0 + ret := C.git_repository_is_bare(repo.ptr) != 0 + runtime.KeepAlive(repo) + return ret } func (repo *Repository) Workdir() string { - return C.GoString(C.git_repository_workdir(repo.ptr)) + s := C.GoString(C.git_repository_workdir(repo.ptr)) + runtime.KeepAlive(repo) + return s } func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error { @@ -421,6 +443,7 @@ func (repo *Repository) SetWorkdir(workdir string, updateGitlink bool) error { if ret := C.git_repository_set_workdir(repo.ptr, cstr, cbool(updateGitlink)); ret < 0 { return MakeGitError(ret) } + runtime.KeepAlive(repo) return nil } @@ -434,6 +457,7 @@ func (v *Repository) TreeBuilder() (*TreeBuilder, error) { if ret := C.git_treebuilder_new(&bld.ptr, v.ptr, nil); ret < 0 { return nil, MakeGitError(ret) } + runtime.SetFinalizer(bld, (*TreeBuilder).Free) bld.repo = v @@ -474,7 +498,10 @@ func (r *Repository) State() RepositoryState { runtime.LockOSThread() defer runtime.UnlockOSThread() - return RepositoryState(C.git_repository_state(r.ptr)) + ret := RepositoryState(C.git_repository_state(r.ptr)) + runtime.KeepAlive(r) + + return ret } func (r *Repository) StateCleanup() error { @@ -482,18 +509,22 @@ func (r *Repository) StateCleanup() error { defer runtime.UnlockOSThread() cErr := C.git_repository_state_cleanup(r.ptr) + runtime.KeepAlive(r) if cErr < 0 { return MakeGitError(cErr) } return nil } + func (r *Repository) AddGitIgnoreRules(rules string) error { runtime.LockOSThread() defer runtime.UnlockOSThread() crules := C.CString(rules) defer C.free(unsafe.Pointer(crules)) - if ret := C.git_ignore_add_rule(r.ptr, crules); ret < 0 { + ret := C.git_ignore_add_rule(r.ptr, crules) + runtime.KeepAlive(r) + if ret < 0 { return MakeGitError(ret) } return nil @@ -503,7 +534,9 @@ func (r *Repository) ClearGitIgnoreRules() error { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_ignore_clear_internal_rules(r.ptr); ret < 0 { + ret := C.git_ignore_clear_internal_rules(r.ptr) + runtime.KeepAlive(r) + if ret < 0 { return MakeGitError(ret) } return nil From 7d29d6864474525c9853d86996d769a5459dc15d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 8 Jul 2017 11:38:19 +0200 Subject: [PATCH 4/5] Second round of keep-alives --- diff.go | 57 +++++++++++++++++++++++++++++++------------ git.go | 1 + graph.go | 6 +++++ ignore.go | 3 +++ index.go | 67 +++++++++++++++++++++++++++++++++++++++------------ repository.go | 3 +-- 6 files changed, 105 insertions(+), 32 deletions(-) diff --git a/diff.go b/diff.go index e8d5007..3cc1dc2 100644 --- a/diff.go +++ b/diff.go @@ -127,14 +127,17 @@ func diffLineFromC(line *C.git_diff_line) DiffLine { } type Diff struct { - ptr *C.git_diff + ptr *C.git_diff + repo *Repository } func (diff *Diff) NumDeltas() (int, error) { if diff.ptr == nil { return -1, ErrInvalid } - return int(C.git_diff_num_deltas(diff.ptr)), nil + ret := int(C.git_diff_num_deltas(diff.ptr)) + runtime.KeepAlive(diff) + return ret, nil } func (diff *Diff) GetDelta(index int) (DiffDelta, error) { @@ -142,16 +145,19 @@ func (diff *Diff) GetDelta(index int) (DiffDelta, error) { return DiffDelta{}, ErrInvalid } ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index)) - return diffDeltaFromC(ptr), nil + ret := diffDeltaFromC(ptr) + runtime.KeepAlive(diff) + return ret, nil } -func newDiffFromC(ptr *C.git_diff) *Diff { +func newDiffFromC(ptr *C.git_diff, repo *Repository) *Diff { if ptr == nil { return nil } diff := &Diff{ - ptr: ptr, + ptr: ptr, + repo: repo, } runtime.SetFinalizer(diff, (*Diff).Free) @@ -187,6 +193,7 @@ func (diff *Diff) FindSimilar(opts *DiffFindOptions) error { defer runtime.UnlockOSThread() ecode := C.git_diff_find_similar(diff.ptr, copts) + runtime.KeepAlive(diff) if ecode < 0 { return MakeGitError(ecode) } @@ -209,15 +216,21 @@ func (stats *DiffStats) Free() error { } func (stats *DiffStats) Insertions() int { - return int(C.git_diff_stats_insertions(stats.ptr)) + ret := int(C.git_diff_stats_insertions(stats.ptr)) + runtime.KeepAlive(stats) + return ret } func (stats *DiffStats) Deletions() int { - return int(C.git_diff_stats_deletions(stats.ptr)) + ret := int(C.git_diff_stats_deletions(stats.ptr)) + runtime.KeepAlive(stats) + return ret } func (stats *DiffStats) FilesChanged() int { - return int(C.git_diff_stats_files_changed(stats.ptr)) + ret := int(C.git_diff_stats_files_changed(stats.ptr)) + runtime.KeepAlive(stats) + return ret } type DiffStatsFormat int @@ -240,6 +253,7 @@ func (stats *DiffStats) String(format DiffStatsFormat, ret := C.git_diff_stats_to_buf(&buf, stats.ptr, C.git_diff_stats_format_t(format), C.size_t(width)) + runtime.KeepAlive(stats) if ret < 0 { return "", MakeGitError(ret) } @@ -253,7 +267,9 @@ func (diff *Diff) Stats() (*DiffStats, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - if ecode := C.git_diff_get_stats(&stats.ptr, diff.ptr); ecode < 0 { + ecode := C.git_diff_get_stats(&stats.ptr, diff.ptr) + runtime.KeepAlive(diff) + if ecode < 0 { return nil, MakeGitError(ecode) } runtime.SetFinalizer(stats, (*DiffStats).Free) @@ -301,6 +317,7 @@ func (diff *Diff) ForEach(cbFile DiffForEachFileCallback, detail DiffDetail) err defer pointerHandles.Untrack(handle) ecode := C._go_git_diff_foreach(diff.ptr, 1, intHunks, intLines, handle) + runtime.KeepAlive(diff) if ecode < 0 { return data.Error } @@ -380,6 +397,7 @@ func (diff *Diff) Patch(deltaIndex int) (*Patch, error) { defer runtime.UnlockOSThread() ecode := C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex)) + runtime.KeepAlive(diff) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -537,7 +555,7 @@ func diffNotifyCb(_diff_so_far unsafe.Pointer, delta_to_add *C.git_diff_delta, m if data != nil { if data.Diff == nil { - data.Diff = newDiffFromC(diff_so_far) + data.Diff = newDiffFromC(diff_so_far, nil) } err := data.Callback(data.Diff, diffDeltaFromC(delta_to_add), C.GoString(matched_pathspec)) @@ -618,6 +636,8 @@ func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree, opts *DiffOptions) ( defer runtime.UnlockOSThread() ecode := C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, copts) + runtime.KeepAlive(oldTree) + runtime.KeepAlive(newTree) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -625,7 +645,7 @@ func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree, opts *DiffOptions) ( if notifyData != nil && notifyData.Diff != nil { return notifyData.Diff, nil } - return newDiffFromC(diffPtr), nil + return newDiffFromC(diffPtr, v), nil } func (v *Repository) DiffTreeToWorkdir(oldTree *Tree, opts *DiffOptions) (*Diff, error) { @@ -643,6 +663,7 @@ func (v *Repository) DiffTreeToWorkdir(oldTree *Tree, opts *DiffOptions) (*Diff, defer runtime.UnlockOSThread() ecode := C.git_diff_tree_to_workdir(&diffPtr, v.ptr, oldPtr, copts) + runtime.KeepAlive(oldTree) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -650,7 +671,7 @@ func (v *Repository) DiffTreeToWorkdir(oldTree *Tree, opts *DiffOptions) (*Diff, if notifyData != nil && notifyData.Diff != nil { return notifyData.Diff, nil } - return newDiffFromC(diffPtr), nil + return newDiffFromC(diffPtr, v), nil } func (v *Repository) DiffTreeToIndex(oldTree *Tree, index *Index, opts *DiffOptions) (*Diff, error) { @@ -673,6 +694,8 @@ func (v *Repository) DiffTreeToIndex(oldTree *Tree, index *Index, opts *DiffOpti defer runtime.UnlockOSThread() ecode := C.git_diff_tree_to_index(&diffPtr, v.ptr, oldPtr, indexPtr, copts) + runtime.KeepAlive(oldTree) + runtime.KeepAlive(index) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -680,7 +703,7 @@ func (v *Repository) DiffTreeToIndex(oldTree *Tree, index *Index, opts *DiffOpti if notifyData != nil && notifyData.Diff != nil { return notifyData.Diff, nil } - return newDiffFromC(diffPtr), nil + return newDiffFromC(diffPtr, v), nil } func (v *Repository) DiffTreeToWorkdirWithIndex(oldTree *Tree, opts *DiffOptions) (*Diff, error) { @@ -698,6 +721,7 @@ func (v *Repository) DiffTreeToWorkdirWithIndex(oldTree *Tree, opts *DiffOptions defer runtime.UnlockOSThread() ecode := C.git_diff_tree_to_workdir_with_index(&diffPtr, v.ptr, oldPtr, copts) + runtime.KeepAlive(oldTree) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -705,7 +729,7 @@ func (v *Repository) DiffTreeToWorkdirWithIndex(oldTree *Tree, opts *DiffOptions if notifyData != nil && notifyData.Diff != nil { return notifyData.Diff, nil } - return newDiffFromC(diffPtr), nil + return newDiffFromC(diffPtr, v), nil } func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, error) { @@ -723,6 +747,7 @@ func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, defer runtime.UnlockOSThread() ecode := C.git_diff_index_to_workdir(&diffPtr, v.ptr, indexPtr, copts) + runtime.KeepAlive(index) if ecode < 0 { return nil, MakeGitError(ecode) } @@ -730,7 +755,7 @@ func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, if notifyData != nil && notifyData.Diff != nil { return notifyData.Diff, nil } - return newDiffFromC(diffPtr), nil + return newDiffFromC(diffPtr, v), nil } // DiffBlobs performs a diff between two arbitrary blobs. You can pass @@ -773,6 +798,8 @@ func DiffBlobs(oldBlob *Blob, oldAsPath string, newBlob *Blob, newAsPath string, defer runtime.UnlockOSThread() ecode := C._go_git_diff_blobs(oldBlobPtr, oldBlobPath, newBlobPtr, newBlobPath, copts, 1, intHunks, intLines, handle) + runtime.KeepAlive(oldBlob) + runtime.KeepAlive(newBlob) if ecode < 0 { return MakeGitError(ecode) } diff --git a/git.go b/git.go index 5181b8b..0925e45 100644 --- a/git.go +++ b/git.go @@ -232,6 +232,7 @@ func ShortenOids(ids []*Oid, minlen int) (int, error) { return int(ret), MakeGitError(ret) } } + runtime.KeepAlive(ids) return int(ret), nil } diff --git a/graph.go b/graph.go index e5d7732..688818c 100644 --- a/graph.go +++ b/graph.go @@ -13,6 +13,9 @@ func (repo *Repository) DescendantOf(commit, ancestor *Oid) (bool, error) { defer runtime.UnlockOSThread() ret := C.git_graph_descendant_of(repo.ptr, commit.toC(), ancestor.toC()) + runtime.KeepAlive(repo) + runtime.KeepAlive(commit) + runtime.KeepAlive(ancestor) if ret < 0 { return false, MakeGitError(ret) } @@ -28,6 +31,9 @@ func (repo *Repository) AheadBehind(local, upstream *Oid) (ahead, behind int, er var behindT C.size_t ret := C.git_graph_ahead_behind(&aheadT, &behindT, repo.ptr, local.toC(), upstream.toC()) + runtime.KeepAlive(repo) + runtime.KeepAlive(local) + runtime.KeepAlive(upstream) if ret < 0 { return 0, 0, MakeGitError(ret) } diff --git a/ignore.go b/ignore.go index 6b12348..c698de1 100644 --- a/ignore.go +++ b/ignore.go @@ -17,6 +17,7 @@ func (v *Repository) AddIgnoreRule(rules string) error { defer runtime.UnlockOSThread() ret := C.git_ignore_add_rule(v.ptr, crules) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -28,6 +29,7 @@ func (v *Repository) ClearInternalIgnoreRules() error { defer runtime.UnlockOSThread() ret := C.git_ignore_clear_internal_rules(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -44,6 +46,7 @@ func (v *Repository) IsPathIgnored(path string) (bool, error) { defer runtime.UnlockOSThread() ret := C.git_ignore_path_is_ignored(&ignored, v.ptr, cpath) + runtime.KeepAlive(v) if ret < 0 { return false, MakeGitError(ret) } diff --git a/index.go b/index.go index 2afdcdf..5106516 100644 --- a/index.go +++ b/index.go @@ -45,7 +45,8 @@ const ( ) type Index struct { - ptr *C.git_index + ptr *C.git_index + repo *Repository } type IndexTime struct { @@ -97,8 +98,8 @@ func freeCIndexEntry(entry *C.git_index_entry) { C.free(unsafe.Pointer(entry.path)) } -func newIndexFromC(ptr *C.git_index) *Index { - idx := &Index{ptr} +func newIndexFromC(ptr *C.git_index, repo *Repository) *Index { + idx := &Index{ptr, repo} runtime.SetFinalizer(idx, (*Index).Free) return idx } @@ -115,7 +116,7 @@ func NewIndex() (*Index, error) { return nil, MakeGitError(err) } - return newIndexFromC(ptr), nil + return newIndexFromC(ptr, nil), nil } // OpenIndex creates a new index at the given path. If the file does @@ -133,13 +134,15 @@ func OpenIndex(path string) (*Index, error) { return nil, MakeGitError(err) } - return newIndexFromC(ptr), nil + return newIndexFromC(ptr, nil), 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)) + ret := C.GoString(C.git_index_path(v.ptr)) + runtime.KeepAlive(v) + return ret } // Add adds or replaces the given entry to the index, making a copy of @@ -153,7 +156,9 @@ func (v *Index) Add(entry *IndexEntry) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - if err := C.git_index_add(v.ptr, ¢ry); err < 0 { + err := C.git_index_add(v.ptr, ¢ry) + runtime.KeepAlive(v) + if err < 0 { return MakeGitError(err) } @@ -168,6 +173,7 @@ func (v *Index) AddByPath(path string) error { defer runtime.UnlockOSThread() ret := C.git_index_add_bypath(v.ptr, cstr) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -196,6 +202,7 @@ func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMat C.uint(flags), handle, ) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -222,6 +229,7 @@ func (v *Index) UpdateAll(pathspecs []string, callback IndexMatchedPathCallback) &cpathspecs, handle, ) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -248,6 +256,7 @@ func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback) &cpathspecs, handle, ) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -271,6 +280,7 @@ func (v *Index) RemoveByPath(path string) error { defer runtime.UnlockOSThread() ret := C.git_index_remove_bypath(v.ptr, cstr) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -287,6 +297,7 @@ func (v *Index) RemoveDirectory(dir string, stage int) error { defer runtime.UnlockOSThread() ret := C.git_index_remove_directory(v.ptr, cstr, C.int(stage)) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -301,6 +312,8 @@ func (v *Index) WriteTreeTo(repo *Repository) (*Oid, error) { defer runtime.UnlockOSThread() ret := C.git_index_write_tree_to(oid.toC(), v.ptr, repo.ptr) + runtime.KeepAlive(v) + runtime.KeepAlive(repo) if ret < 0 { return nil, MakeGitError(ret) } @@ -315,6 +328,8 @@ func (v *Index) ReadTree(tree *Tree) error { defer runtime.UnlockOSThread() ret := C.git_index_read_tree(v.ptr, tree.cast_ptr) + runtime.KeepAlive(v) + runtime.KeepAlive(tree) if ret < 0 { return MakeGitError(ret) } @@ -329,6 +344,7 @@ func (v *Index) WriteTree() (*Oid, error) { defer runtime.UnlockOSThread() ret := C.git_index_write_tree(oid.toC(), v.ptr) + runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } @@ -341,6 +357,7 @@ func (v *Index) Write() error { defer runtime.UnlockOSThread() ret := C.git_index_write(v.ptr) + runtime.KeepAlive(v) if ret < 0 { return MakeGitError(ret) } @@ -354,7 +371,9 @@ func (v *Index) Free() { } func (v *Index) EntryCount() uint { - return uint(C.git_index_entrycount(v.ptr)) + ret := uint(C.git_index_entrycount(v.ptr)) + runtime.KeepAlive(v) + return ret } func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { @@ -362,7 +381,9 @@ func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { if centry == nil { return nil, fmt.Errorf("Index out of Bounds") } - return newIndexEntryFromC(centry), nil + ret := newIndexEntryFromC(centry) + runtime.KeepAlive(v) + return ret, nil } func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) { @@ -376,7 +397,9 @@ func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) { if centry == nil { return nil, MakeGitError(C.GIT_ENOTFOUND) } - return newIndexEntryFromC(centry), nil + ret := newIndexEntryFromC(centry) + runtime.KeepAlive(v) + return ret, nil } func (v *Index) Find(path string) (uint, error) { @@ -388,6 +411,7 @@ func (v *Index) Find(path string) (uint, error) { var pos C.size_t ret := C.git_index_find(&pos, v.ptr, cpath) + runtime.KeepAlive(v) if ret < 0 { return uint(0), MakeGitError(ret) } @@ -403,6 +427,7 @@ func (v *Index) FindPrefix(prefix string) (uint, error) { var pos C.size_t ret := C.git_index_find_prefix(&pos, v.ptr, cprefix) + runtime.KeepAlive(v) if ret < 0 { return uint(0), MakeGitError(ret) } @@ -410,12 +435,15 @@ func (v *Index) FindPrefix(prefix string) (uint, error) { } func (v *Index) HasConflicts() bool { - return C.git_index_has_conflicts(v.ptr) != 0 + ret := C.git_index_has_conflicts(v.ptr) != 0 + runtime.KeepAlive(v) + return ret } // FIXME: this might return an error func (v *Index) CleanupConflicts() { C.git_index_conflict_cleanup(v.ptr) + runtime.KeepAlive(v) } func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error { @@ -446,6 +474,10 @@ func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexE defer runtime.UnlockOSThread() ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir) + runtime.KeepAlive(v) + runtime.KeepAlive(ancestor) + runtime.KeepAlive(our) + runtime.KeepAlive(their) if ecode < 0 { return MakeGitError(ecode) } @@ -474,11 +506,13 @@ func (v *Index) GetConflict(path string) (IndexConflict, error) { if ecode < 0 { return IndexConflict{}, MakeGitError(ecode) } - return IndexConflict{ + ret := IndexConflict{ Ancestor: newIndexEntryFromC(cancestor), Our: newIndexEntryFromC(cour), Their: newIndexEntryFromC(ctheir), - }, nil + } + runtime.KeepAlive(v) + return ret, nil } func (v *Index) RemoveConflict(path string) error { @@ -490,6 +524,7 @@ func (v *Index) RemoveConflict(path string) error { defer runtime.UnlockOSThread() ecode := C.git_index_conflict_remove(v.ptr, cpath) + runtime.KeepAlive(v) if ecode < 0 { return MakeGitError(ecode) } @@ -541,9 +576,11 @@ func (v *IndexConflictIterator) Next() (IndexConflict, error) { if ecode < 0 { return IndexConflict{}, MakeGitError(ecode) } - return IndexConflict{ + ret := IndexConflict{ Ancestor: newIndexEntryFromC(cancestor), Our: newIndexEntryFromC(cour), Their: newIndexEntryFromC(ctheir), - }, nil + } + runtime.KeepAlive(v) + return ret, nil } diff --git a/repository.go b/repository.go index 44d18a9..6b07e87 100644 --- a/repository.go +++ b/repository.go @@ -160,12 +160,11 @@ func (v *Repository) Index() (*Index, error) { defer runtime.UnlockOSThread() ret := C.git_repository_index(&ptr, v.ptr) - runtime.KeepAlive(v) if ret < 0 { return nil, MakeGitError(ret) } - return newIndexFromC(ptr), nil + return newIndexFromC(ptr, v), nil } func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) { From 55a1096141519a1f380d0702671cfe9bf90ec435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 8 Jul 2017 16:07:51 +0200 Subject: [PATCH 5/5] Third round of keep-alive aditions --- merge.go | 66 +++++++++++++++++++++++---------------- note.go | 48 +++++++++++++++++++++-------- object.go | 21 ++++++++++--- odb.go | 36 +++++++++++++++++----- packbuilder.go | 31 ++++++++++++++----- patch.go | 3 ++ rebase.go | 16 ++++++++-- refdb.go | 9 ++++-- reference.go | 84 +++++++++++++++++++++++++++++++++++--------------- repository.go | 1 + signature.go | 1 + stash.go | 6 +++- status.go | 17 +++++++--- submodule.go | 79 +++++++++++++++++++++++++++++++++-------------- tag.go | 28 +++++++++++++---- tree.go | 13 ++++++-- walk.go | 16 +++++++++- 17 files changed, 353 insertions(+), 122 deletions(-) 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) }