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