From b7159b0cd4b25ee3b1a8eb9e0d4991d297487a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 4 Aug 2015 14:47:10 +0200 Subject: [PATCH 01/14] Move from an Object interface to a type An Object should be about representing a libgit2 object rather than showing which methods it should support. Change any return of Object to *Object and provide methods to convert between this and the particular type. --- blob.go | 2 +- commit.go | 6 +- describe.go | 2 +- index_test.go | 5 +- object.go | 173 +++++++++++++++++++++++++++++++++-------------- object_test.go | 24 +++---- reference.go | 2 +- repository.go | 12 ++-- reset.go | 2 +- revparse.go | 16 ++--- revparse_test.go | 2 +- tag.go | 8 +-- tree.go | 2 +- 13 files changed, 163 insertions(+), 93 deletions(-) diff --git a/blob.go b/blob.go index b1fc78a..16ec183 100644 --- a/blob.go +++ b/blob.go @@ -18,7 +18,7 @@ import ( ) type Blob struct { - gitObject + Object cast_ptr *C.git_blob } diff --git a/commit.go b/commit.go index 52f7c01..6830da3 100644 --- a/commit.go +++ b/commit.go @@ -14,7 +14,7 @@ import ( // Commit type Commit struct { - gitObject + Object cast_ptr *C.git_commit } @@ -37,7 +37,7 @@ func (c Commit) Tree() (*Tree, error) { return nil, MakeGitError(err) } - return allocObject((*C.git_object)(ptr), c.repo).(*Tree), nil + return allocTree(ptr, c.repo), nil } func (c Commit) TreeId() *Oid { @@ -61,7 +61,7 @@ func (c *Commit) Parent(n uint) *Commit { return nil } - return allocObject((*C.git_object)(cobj), c.repo).(*Commit) + return allocCommit(cobj, c.repo) } func (c *Commit) ParentId(n uint) *Oid { diff --git a/describe.go b/describe.go index c6f9a79..d75dbcb 100644 --- a/describe.go +++ b/describe.go @@ -127,7 +127,7 @@ func (c *Commit) Describe(opts *DescribeOptions) (*DescribeResult, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_describe_commit(&resultPtr, c.gitObject.ptr, cDescribeOpts) + ecode := C.git_describe_commit(&resultPtr, c.ptr, cDescribeOpts) if ecode < 0 { return nil, MakeGitError(ecode) } diff --git a/index_test.go b/index_test.go index 7c65f4f..5f6b375 100644 --- a/index_test.go +++ b/index_test.go @@ -32,10 +32,11 @@ func TestIndexReadTree(t *testing.T) { ref, err := repo.Head() checkFatal(t, err) - obj, err := ref.Peel(ObjectTree); + obj, err := ref.Peel(ObjectTree) checkFatal(t, err) - tree := obj.(*Tree) + tree, err := obj.AsTree() + checkFatal(t, err) idx, err := NewIndex() checkFatal(t, err) diff --git a/object.go b/object.go index 6ecebf8..1981980 100644 --- a/object.go +++ b/object.go @@ -4,7 +4,11 @@ package git #include */ import "C" -import "runtime" +import ( + "errors" + "fmt" + "runtime" +) type ObjectType int @@ -17,15 +21,7 @@ const ( ObjectTag ObjectType = C.GIT_OBJ_TAG ) -type Object interface { - Free() - Id() *Oid - Type() ObjectType - Owner() *Repository - Peel(t ObjectType) (Object, error) -} - -type gitObject struct { +type Object struct { ptr *C.git_object repo *Repository } @@ -49,23 +45,128 @@ func (t ObjectType) String() string { return "" } -func (o gitObject) Id() *Oid { +func (o *Object) Id() *Oid { return newOidFromC(C.git_object_id(o.ptr)) } -func (o gitObject) Type() ObjectType { +func (o *Object) Type() ObjectType { return ObjectType(C.git_object_type(o.ptr)) } // Owner returns a weak reference to the repository which owns this -// object -func (o gitObject) Owner() *Repository { +// object. This won't keep the underlying repository alive. +func (o *Object) Owner() *Repository { return &Repository{ ptr: C.git_object_owner(o.ptr), } } -func (o *gitObject) Free() { +func dupObject(obj *Object, kind ObjectType) (*C.git_object, error) { + if obj.Type() != kind { + return nil, errors.New(fmt.Sprintf("object is not a %v", kind)) + } + + var cobj *C.git_object + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if err := C.git_object_dup(&cobj, obj.ptr); err < 0 { + return nil, MakeGitError(err) + } + + return cobj, nil +} + +func allocTree(ptr *C.git_tree, repo *Repository) *Tree { + tree := &Tree{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(tree, (*Tree).Free) + + return tree +} + +func (o *Object) AsTree() (*Tree, error) { + cobj, err := dupObject(o, ObjectTree) + if err != nil { + return nil, err + } + + return allocTree((*C.git_tree)(cobj), o.repo), nil +} + +func allocCommit(ptr *C.git_commit, repo *Repository) *Commit { + commit := &Commit{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(commit, (*Commit).Free) + + return commit +} + +func (o *Object) AsCommit() (*Commit, error) { + cobj, err := dupObject(o, ObjectCommit) + if err != nil { + return nil, err + } + + return allocCommit((*C.git_commit)(cobj), o.repo), nil +} + +func allocBlob(ptr *C.git_blob, repo *Repository) *Blob { + blob := &Blob{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(blob, (*Blob).Free) + + return blob +} + +func (o *Object) AsBlob() (*Blob, error) { + cobj, err := dupObject(o, ObjectBlob) + if err != nil { + return nil, err + } + + return allocBlob((*C.git_blob)(cobj), o.repo), nil +} + +func allocTag(ptr *C.git_tag, repo *Repository) *Tag { + tag := &Tag{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(tag, (*Tag).Free) + + return tag +} + +func (o *Object) AsTag() (*Tag, error) { + cobj, err := dupObject(o, ObjectTag) + if err != nil { + return nil, err + } + + return allocTag((*C.git_tag)(cobj), o.repo), nil +} + +func (o *Object) Free() { runtime.SetFinalizer(o, nil) C.git_object_free(o.ptr) } @@ -82,7 +183,7 @@ func (o *gitObject) Free() { // // If peeling a tag we discover an object which cannot be peeled to the target // type due to the object model, an error will be returned. -func (o *gitObject) Peel(t ObjectType) (Object, error) { +func (o *Object) Peel(t ObjectType) (*Object, error) { var cobj *C.git_object runtime.LockOSThread() @@ -95,44 +196,12 @@ func (o *gitObject) Peel(t ObjectType) (Object, error) { return allocObject(cobj, o.repo), nil } -func allocObject(cobj *C.git_object, repo *Repository) Object { - obj := gitObject{ +func allocObject(cobj *C.git_object, repo *Repository) *Object { + obj := &Object{ ptr: cobj, repo: repo, } + runtime.SetFinalizer(obj, (*Object).Free) - switch ObjectType(C.git_object_type(cobj)) { - case ObjectCommit: - commit := &Commit{ - gitObject: obj, - cast_ptr: (*C.git_commit)(cobj), - } - runtime.SetFinalizer(commit, (*Commit).Free) - return commit - - case ObjectTree: - tree := &Tree{ - gitObject: obj, - cast_ptr: (*C.git_tree)(cobj), - } - runtime.SetFinalizer(tree, (*Tree).Free) - return tree - - case ObjectBlob: - blob := &Blob{ - gitObject: obj, - cast_ptr: (*C.git_blob)(cobj), - } - runtime.SetFinalizer(blob, (*Blob).Free) - return blob - case ObjectTag: - tag := &Tag{ - gitObject: obj, - cast_ptr: (*C.git_tag)(cobj), - } - runtime.SetFinalizer(tag, (*Tag).Free) - return tag - } - - return nil + return obj } diff --git a/object_test.go b/object_test.go index ef6c5a1..2ae2a6a 100644 --- a/object_test.go +++ b/object_test.go @@ -10,12 +10,12 @@ func TestObjectPoymorphism(t *testing.T) { commitId, treeId := seedTestRepo(t, repo) - var obj Object + var obj *Object commit, err := repo.LookupCommit(commitId) checkFatal(t, err) - obj = commit + obj = &commit.Object if obj.Type() != ObjectCommit { t.Fatalf("Wrong object type, expected commit, have %v", obj.Type()) } @@ -27,13 +27,13 @@ func TestObjectPoymorphism(t *testing.T) { tree, err := repo.LookupTree(treeId) checkFatal(t, err) - obj = tree + obj = &tree.Object if obj.Type() != ObjectTree { t.Fatalf("Wrong object type, expected tree, have %v", obj.Type()) } - tree2, ok := obj.(*Tree) - if !ok { + tree2, err := obj.AsTree() + if err != nil { t.Fatalf("Converting back to *Tree is not ok") } @@ -46,16 +46,16 @@ func TestObjectPoymorphism(t *testing.T) { t.Fatal("Wrong filemode for \"README\"") } - _, ok = obj.(*Commit) - if ok { + _, err = obj.AsCommit() + if err == nil { t.Fatalf("*Tree is somehow the same as *Commit") } obj, err = repo.Lookup(tree.Id()) checkFatal(t, err) - _, ok = obj.(*Tree) - if !ok { + _, err = obj.AsTree() + if err != nil { t.Fatalf("Lookup creates the wrong type") } @@ -99,8 +99,8 @@ func TestObjectOwner(t *testing.T) { tree, err := repo.LookupTree(treeId) checkFatal(t, err) - checkOwner(t, repo, commit) - checkOwner(t, repo, tree) + checkOwner(t, repo, commit.Object) + checkOwner(t, repo, tree.Object) } func TestObjectPeel(t *testing.T) { @@ -109,7 +109,7 @@ func TestObjectPeel(t *testing.T) { commitID, treeID := seedTestRepo(t, repo) - var obj Object + var obj *Object commit, err := repo.LookupCommit(commitID) checkFatal(t, err) diff --git a/reference.go b/reference.go index 140082f..463f2fc 100644 --- a/reference.go +++ b/reference.go @@ -263,7 +263,7 @@ func (v *Reference) Delete() error { return nil } -func (v *Reference) Peel(t ObjectType) (Object, error) { +func (v *Reference) Peel(t ObjectType) (*Object, error) { var cobj *C.git_object runtime.LockOSThread() diff --git a/repository.go b/repository.go index 62fde6d..2e05780 100644 --- a/repository.go +++ b/repository.go @@ -145,7 +145,7 @@ func (v *Repository) Index() (*Index, error) { return newIndexFromC(ptr), nil } -func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { +func (v *Repository) lookupType(id *Oid, t ObjectType) (*Object, error) { var ptr *C.git_object runtime.LockOSThread() @@ -159,7 +159,7 @@ func (v *Repository) lookupType(id *Oid, t ObjectType) (Object, error) { return allocObject(ptr, v), nil } -func (v *Repository) Lookup(id *Oid) (Object, error) { +func (v *Repository) Lookup(id *Oid) (*Object, error) { return v.lookupType(id, ObjectAny) } @@ -169,7 +169,7 @@ func (v *Repository) LookupTree(id *Oid) (*Tree, error) { return nil, err } - return obj.(*Tree), nil + return obj.AsTree() } func (v *Repository) LookupCommit(id *Oid) (*Commit, error) { @@ -178,7 +178,7 @@ func (v *Repository) LookupCommit(id *Oid) (*Commit, error) { return nil, err } - return obj.(*Commit), nil + return obj.AsCommit() } func (v *Repository) LookupBlob(id *Oid) (*Blob, error) { @@ -187,7 +187,7 @@ func (v *Repository) LookupBlob(id *Oid) (*Blob, error) { return nil, err } - return obj.(*Blob), nil + return obj.AsBlob() } func (v *Repository) LookupTag(id *Oid) (*Tag, error) { @@ -196,7 +196,7 @@ func (v *Repository) LookupTag(id *Oid) (*Tag, error) { return nil, err } - return obj.(*Tag), nil + return obj.AsTag() } func (v *Repository) Head() (*Reference, error) { diff --git a/reset.go b/reset.go index b5b7435..9da7625 100644 --- a/reset.go +++ b/reset.go @@ -17,7 +17,7 @@ const ( func (r *Repository) ResetToCommit(commit *Commit, resetType ResetType, opts *CheckoutOpts) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_reset(r.ptr, commit.gitObject.ptr, C.git_reset_t(resetType), opts.toC()) + ret := C.git_reset(r.ptr, commit.ptr, C.git_reset_t(resetType), opts.toC()) if ret < 0 { return MakeGitError(ret) diff --git a/revparse.go b/revparse.go index 7eb04f1..950932b 100644 --- a/revparse.go +++ b/revparse.go @@ -20,16 +20,16 @@ const ( ) type Revspec struct { - to Object - from Object + to *Object + from *Object flags RevparseFlag } -func (rs *Revspec) To() Object { +func (rs *Revspec) To() *Object { return rs.to } -func (rs *Revspec) From() Object { +func (rs *Revspec) From() *Object { return rs.from } @@ -38,8 +38,8 @@ func (rs *Revspec) Flags() RevparseFlag { } func newRevspecFromC(ptr *C.git_revspec, repo *Repository) *Revspec { - var to Object - var from Object + var to *Object + var from *Object if ptr.to != nil { to = allocObject(ptr.to, repo) @@ -73,7 +73,7 @@ func (r *Repository) Revparse(spec string) (*Revspec, error) { return newRevspecFromC(&crevspec, r), nil } -func (v *Repository) RevparseSingle(spec string) (Object, error) { +func (v *Repository) RevparseSingle(spec string) (*Object, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) @@ -90,7 +90,7 @@ func (v *Repository) RevparseSingle(spec string) (Object, error) { return allocObject(ptr, v), nil } -func (r *Repository) RevparseExt(spec string) (Object, *Reference, error) { +func (r *Repository) RevparseExt(spec string) (*Object, *Reference, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) diff --git a/revparse_test.go b/revparse_test.go index 091a76b..75e9ffd 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -46,7 +46,7 @@ func TestRevparseExt(t *testing.T) { } } -func checkObject(t *testing.T, obj Object, id *Oid) { +func checkObject(t *testing.T, obj *Object, id *Oid) { if obj == nil { t.Fatalf("bad object") } diff --git a/tag.go b/tag.go index ca85156..8957430 100644 --- a/tag.go +++ b/tag.go @@ -13,7 +13,7 @@ import ( // Tag type Tag struct { - gitObject + Object cast_ptr *C.git_tag } @@ -30,7 +30,7 @@ func (t Tag) Tagger() *Signature { return newSignatureFromC(cast_ptr) } -func (t Tag) Target() Object { +func (t Tag) Target() *Object { var ptr *C.git_object ret := C.git_tag_target(&ptr, t.cast_ptr) @@ -70,7 +70,7 @@ func (c *TagsCollection) Create( } defer C.git_signature_free(taggerSig) - ctarget := commit.gitObject.ptr + ctarget := commit.ptr runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -102,7 +102,7 @@ func (c *TagsCollection) CreateLightweight(name string, commit *Commit, force bo cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - ctarget := commit.gitObject.ptr + ctarget := commit.ptr runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/tree.go b/tree.go index f543c11..8288176 100644 --- a/tree.go +++ b/tree.go @@ -23,7 +23,7 @@ const ( ) type Tree struct { - gitObject + Object cast_ptr *C.git_tree } From 876ddd17eba886c8d1cc10d34a8130dd147d63da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 31 Aug 2015 20:21:28 +0200 Subject: [PATCH 02/14] Update missing bit to the new object model --- merge_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/merge_test.go b/merge_test.go index ad01319..8059727 100644 --- a/merge_test.go +++ b/merge_test.go @@ -115,7 +115,10 @@ func appendCommit(t *testing.T, repo *Repository) (*Oid, *Oid) { parent, err := ref.Peel(ObjectCommit) checkFatal(t, err) - commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree, parent.(*Commit)) + parentCommit, err := parent.AsCommit() + checkFatal(t, err) + + commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree, parentCommit) checkFatal(t, err) return commitId, treeId From d5890f58e884174f1cee13d5a616e818ba2f5049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 31 Aug 2015 20:22:17 +0200 Subject: [PATCH 03/14] Run go fmt As it seems to be something that many people can't get over, reformat all the files; as we're breaking things, whoever depended on 'next' will have to take many changes into account anyway, so let's include this to reduce the noise of incoming patches. --- checkout.go | 4 ++-- index.go | 6 +++--- merge.go | 12 ++++++------ odb.go | 4 ++-- remote.go | 26 +++++++++++++------------- remote_test.go | 2 +- repository.go | 10 +++++----- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/checkout.go b/checkout.go index e0c067e..ce2f469 100644 --- a/checkout.go +++ b/checkout.go @@ -44,7 +44,7 @@ type CheckoutOpts struct { FileMode os.FileMode // Default is 0644 or 0755 as dictated by blob FileOpenFlags int // Default is O_CREAT | O_TRUNC | O_WRONLY TargetDirectory string // Alternative checkout path to workdir - Paths []string + Paths []string } func checkoutOptionsFromC(c *C.git_checkout_options) CheckoutOpts { @@ -156,4 +156,4 @@ func (v *Repository) CheckoutTree(tree *Tree, opts *CheckoutOpts) error { } return nil -} \ No newline at end of file +} diff --git a/index.go b/index.go index 0174dc1..f4c0c1e 100644 --- a/index.go +++ b/index.go @@ -51,8 +51,8 @@ func newIndexEntryFromC(entry *C.git_index_entry) *IndexEntry { return nil } return &IndexEntry{ - IndexTime { int32(entry.ctime.seconds), uint32(entry.ctime.nanoseconds) }, - IndexTime { int32(entry.mtime.seconds), uint32(entry.mtime.nanoseconds) }, + IndexTime{int32(entry.ctime.seconds), uint32(entry.ctime.nanoseconds)}, + IndexTime{int32(entry.mtime.seconds), uint32(entry.mtime.nanoseconds)}, Filemode(entry.mode), uint32(entry.uid), uint32(entry.gid), @@ -280,7 +280,7 @@ func (v *Index) ReadTree(tree *Tree) error { runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_index_read_tree(v.ptr, tree.cast_ptr); + ret := C.git_index_read_tree(v.ptr, tree.cast_ptr) if ret < 0 { return MakeGitError(ret) } diff --git a/merge.go b/merge.go index 7307f10..f1a6f40 100644 --- a/merge.go +++ b/merge.go @@ -85,8 +85,8 @@ const ( ) type MergeOptions struct { - Version uint - TreeFlags MergeTreeFlag + Version uint + TreeFlags MergeTreeFlag RenameThreshold uint TargetLimit uint @@ -98,7 +98,7 @@ type MergeOptions struct { func mergeOptionsFromC(opts *C.git_merge_options) MergeOptions { return MergeOptions{ Version: uint(opts.version), - TreeFlags: MergeTreeFlag(opts.tree_flags), + TreeFlags: MergeTreeFlag(opts.tree_flags), RenameThreshold: uint(opts.rename_threshold), TargetLimit: uint(opts.target_limit), FileFavor: MergeFileFavor(opts.file_favor), @@ -259,10 +259,10 @@ func (r *Repository) MergeBases(one, two *Oid) ([]*Oid, error) { } oids := make([]*Oid, coids.count) - hdr := reflect.SliceHeader { + hdr := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(coids.ids)), - Len: int(coids.count), - Cap: int(coids.count), + Len: int(coids.count), + Cap: int(coids.count), } goSlice := *(*[]C.git_oid)(unsafe.Pointer(&hdr)) diff --git a/odb.go b/odb.go index be0870e..ff8b739 100644 --- a/odb.go +++ b/odb.go @@ -8,10 +8,10 @@ extern void _go_git_odb_backend_free(git_odb_backend *backend); */ import "C" import ( + "fmt" "reflect" "runtime" "unsafe" - "fmt" ) type Odb struct { @@ -130,7 +130,7 @@ func (v *Odb) ForEach(callback OdbForEachCallback) error { defer pointerHandles.Untrack(handle) ret := C._go_git_odb_foreach(v.ptr, handle) - fmt.Println("ret %v", ret); + fmt.Println("ret %v", ret) if ret == C.GIT_EUSER { return data.err } else if ret < 0 { diff --git a/remote.go b/remote.go index b2fb96f..b3aba54 100644 --- a/remote.go +++ b/remote.go @@ -72,12 +72,12 @@ type RemoteCallbacks struct { type FetchPrune uint const ( - // Use the setting from the configuration + // Use the setting from the configuration FetchPruneUnspecified FetchPrune = C.GIT_FETCH_PRUNE_UNSPECIFIED // Force pruning on - FetchPruneOn FetchPrune = C.GIT_FETCH_PRUNE + FetchPruneOn FetchPrune = C.GIT_FETCH_PRUNE // Force pruning off - FetchNoPrune FetchPrune = C.GIT_FETCH_NO_PRUNE + FetchNoPrune FetchPrune = C.GIT_FETCH_NO_PRUNE ) type DownloadTags uint @@ -88,20 +88,20 @@ const ( DownloadTagsUnspecified DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED // Ask the server for tags pointing to objects we're already // downloading. - DownloadTagsAuto DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_AUTO + DownloadTagsAuto DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_AUTO // Don't ask for any tags beyond the refspecs. - DownloadTagsNone DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_NONE + DownloadTagsNone DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_NONE // Ask for the all the tags. - DownloadTagsAll DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_ALL + DownloadTagsAll DownloadTags = C.GIT_REMOTE_DOWNLOAD_TAGS_ALL ) type FetchOptions struct { // Callbacks to use for this fetch operation RemoteCallbacks RemoteCallbacks // Whether to perform a prune after the fetch - Prune FetchPrune + Prune FetchPrune // Whether to write the results to FETCH_HEAD. Defaults to // on. Leave this default in order to behave like git. UpdateFetchhead bool @@ -111,7 +111,7 @@ type FetchOptions struct { // downloading all of them. // // The default is to auto-follow tags. - DownloadTags DownloadTags + DownloadTags DownloadTags } type Remote struct { @@ -588,7 +588,7 @@ func (o *Remote) RefspecCount() uint { func populateFetchOptions(options *C.git_fetch_options, opts *FetchOptions) { C.git_fetch_init_options(options, C.GIT_FETCH_OPTIONS_VERSION) if opts == nil { - return; + return } populateRemoteCallbacks(&options.callbacks, &opts.RemoteCallbacks) options.prune = C.git_fetch_prune_t(opts.Prune) @@ -611,7 +611,7 @@ func populatePushOptions(options *C.git_push_options, opts *PushOptions) { // to use for this fetch, use an empty list to use the refspecs from // the configuration; msg specifies what to use for the reflog // entries. Leave "" to use defaults. -func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error { +func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error { var cmsg *C.char = nil if msg != "" { cmsg = C.CString(msg) @@ -624,7 +624,7 @@ func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error defer freeStrarray(&crefspecs) var coptions C.git_fetch_options - populateFetchOptions(&coptions, opts); + populateFetchOptions(&coptions, opts) defer untrackCalbacksPayload(&coptions.callbacks) runtime.LockOSThread() @@ -646,7 +646,7 @@ func (o *Remote) ConnectPush(callbacks *RemoteCallbacks) error { } func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks) error { - var ccallbacks C.git_remote_callbacks; + var ccallbacks C.git_remote_callbacks populateRemoteCallbacks(&ccallbacks, callbacks) runtime.LockOSThread() @@ -729,7 +729,7 @@ func (o *Remote) PruneRefs() bool { } func (o *Remote) Prune(callbacks *RemoteCallbacks) error { - var ccallbacks C.git_remote_callbacks; + var ccallbacks C.git_remote_callbacks populateRemoteCallbacks(&ccallbacks, callbacks) runtime.LockOSThread() diff --git a/remote_test.go b/remote_test.go index 73c637f..dac3dbe 100644 --- a/remote_test.go +++ b/remote_test.go @@ -39,7 +39,7 @@ func TestCertificateCheck(t *testing.T) { remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository") checkFatal(t, err) - options := FetchOptions { + options := FetchOptions{ RemoteCallbacks: RemoteCallbacks{ CertificateCheckCallback: func(cert *Certificate, valid bool, hostname string) ErrorCode { return assertHostname(cert, valid, hostname, t) diff --git a/repository.go b/repository.go index 2e05780..d8e398b 100644 --- a/repository.go +++ b/repository.go @@ -12,11 +12,11 @@ import ( // Repository type Repository struct { - ptr *C.git_repository + ptr *C.git_repository // Remotes represents the collection of remotes and can be // used to add, remove and configure remotes for this // repository. - Remotes RemoteCollection + Remotes RemoteCollection // Submodules represents the collection of submodules and can // be used to add, remove and configure submodules in this // repostiory. @@ -26,7 +26,7 @@ type Repository struct { References ReferenceCollection // Notes represents the collection of notes and can be used to // read, write and delete notes from this repository. - Notes NoteCollection + Notes NoteCollection // Tags represents the collection of tags and can be used to create, // list and iterate tags in this repository. Tags TagsCollection @@ -35,10 +35,10 @@ type Repository struct { func newRepositoryFromC(ptr *C.git_repository) *Repository { repo := &Repository{ptr: ptr} - repo.Remotes.repo = repo + repo.Remotes.repo = repo repo.Submodules.repo = repo repo.References.repo = repo - repo.Notes.repo = repo + repo.Notes.repo = repo repo.Tags.repo = repo runtime.SetFinalizer(repo, (*Repository).Free) From b3e7705c48f038ef335204a2a9e1ee829784c30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 31 Aug 2015 20:24:54 +0200 Subject: [PATCH 04/14] Update vendored libgit2 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index fb84cde..ed38e26 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit fb84cde81e11947add4ff8bb9b4084f7d76e6567 +Subproject commit ed38e26db5435b519d8b796e4b6c2c660fe982b5 From b8283e72771866cae56c9036ace2ff80f125ff50 Mon Sep 17 00:00:00 2001 From: FUJII Ryota Date: Mon, 28 Sep 2015 20:38:04 +0900 Subject: [PATCH 05/14] Add EntryByPath method to Index --- index.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/index.go b/index.go index f4c0c1e..06495b9 100644 --- a/index.go +++ b/index.go @@ -331,6 +331,17 @@ func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { return newIndexEntryFromC(centry), nil } +func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + centry := C.git_index_get_bypath(v.ptr, C.CString(path), C.int(stage)) + if centry == nil { + return nil, MakeGitError(C.GIT_ENOTFOUND) + } + return newIndexEntryFromC(centry), nil +} + func (v *Index) HasConflicts() bool { return C.git_index_has_conflicts(v.ptr) != 0 } From 56cc9e1b0eafb1275be42ca60cfaf78297df8d60 Mon Sep 17 00:00:00 2001 From: FUJII Ryota Date: Fri, 9 Oct 2015 16:28:08 +0900 Subject: [PATCH 06/14] Add support for ignore --- ignore.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 ignore.go diff --git a/ignore.go b/ignore.go new file mode 100644 index 0000000..6b12348 --- /dev/null +++ b/ignore.go @@ -0,0 +1,51 @@ +package git + +/* +#include +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +func (v *Repository) AddIgnoreRule(rules string) error { + crules := C.CString(rules) + defer C.free(unsafe.Pointer(crules)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_ignore_add_rule(v.ptr, crules) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +func (v *Repository) ClearInternalIgnoreRules() error { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_ignore_clear_internal_rules(v.ptr) + if ret < 0 { + return MakeGitError(ret) + } + return nil +} + +func (v *Repository) IsPathIgnored(path string) (bool, error) { + var ignored C.int + + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_ignore_path_is_ignored(&ignored, v.ptr, cpath) + if ret < 0 { + return false, MakeGitError(ret) + } + return ignored == 1, nil +} From 367cd8eb9b84538933774befa76c099298c32c81 Mon Sep 17 00:00:00 2001 From: Calin Seciu Date: Mon, 26 Oct 2015 16:20:18 +0200 Subject: [PATCH 07/14] Update libgit2 to 821131f The API changes are: - `*Remote.Connect` ```go // from: func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks) error // to: func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks, headers []string) error ``` - `*Remote.ConnectFetch` - `headers` was added as above - `*Remote.ConnectPush` - `headers` was added as above --- config.go | 21 +++++++++++++++++++++ git.go | 22 ++++++++++++++++++++-- index.go | 18 ++++++++++++++++++ merge.go | 7 +++++++ remote.go | 40 ++++++++++++++++++++++++++++++++++------ remote_test.go | 8 ++++---- vendor/libgit2 | 2 +- 7 files changed, 105 insertions(+), 13 deletions(-) diff --git a/config.go b/config.go index 9d25e35..73365c8 100644 --- a/config.go +++ b/config.go @@ -12,6 +12,9 @@ import ( type ConfigLevel int const ( + // System-wide on Windows, for compatibility with portable git + ConfigLevelProgramdata ConfigLevel = C.GIT_CONFIG_LEVEL_PROGRAMDATA + // System-wide configuration file; /etc/gitconfig on Linux systems ConfigLevelSystem ConfigLevel = C.GIT_CONFIG_LEVEL_SYSTEM @@ -410,3 +413,21 @@ func ConfigFindXDG() (string, error) { return C.GoString(buf.ptr), nil } + +// ConfigFindProgramdata locate the path to the configuration file in ProgramData. +// +// Look for the file in %PROGRAMDATA%\Git\config used by portable git. +func ConfigFindProgramdata() (string, error) { + var buf C.git_buf + defer C.git_buf_free(&buf) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_config_find_programdata(&buf) + if ret < 0 { + return "", MakeGitError(ret) + } + + return C.GoString(buf.ptr), nil +} diff --git a/git.go b/git.go index 34d58e6..2b2a909 100644 --- a/git.go +++ b/git.go @@ -52,6 +52,7 @@ const ( // No error ErrOk ErrorCode = C.GIT_OK + // Generic error ErrGeneric ErrorCode = C.GIT_ERROR // Requested object could not be found @@ -62,10 +63,12 @@ const ( ErrAmbigious ErrorCode = C.GIT_EAMBIGUOUS // Output buffer too short to hold data ErrBuffs ErrorCode = C.GIT_EBUFS + // GIT_EUSER is a special error that is never generated by libgit2 // code. You can return it from a callback (e.g to stop an iteration) // to know that it was generated by the callback and not by libgit2. ErrUser ErrorCode = C.GIT_EUSER + // Operation not allowed on bare repository ErrBareRepo ErrorCode = C.GIT_EBAREREPO // HEAD refers to branch with no commits @@ -82,12 +85,27 @@ const ( ErrLocked ErrorCode = C.GIT_ELOCKED // Reference value does not match expected ErrModified ErrorCode = C.GIT_EMODIFIED + // Authentication failed + ErrAuth ErrorCode = C.GIT_EAUTH + // Server certificate is invalid + ErrCertificate ErrorCode = C.GIT_ECERTIFICATE + // Patch/merge has already been applied + ErrApplied ErrorCode = C.GIT_EAPPLIED + // The requested peel operation is not possible + ErrPeel ErrorCode = C.GIT_EPEEL + // Unexpected EOF + ErrEOF ErrorCode = C.GIT_EEOF + // Uncommitted changes in index prevented operation + ErrUncommitted ErrorCode = C.GIT_EUNCOMMITTED + // The operation is not valid for a directory + ErrDirectory ErrorCode = C.GIT_EDIRECTORY + // A merge conflict exists and cannot continue + ErrMergeConflict ErrorCode = C.GIT_EMERGECONFLICT + // Internal only ErrPassthrough ErrorCode = C.GIT_PASSTHROUGH // Signals end of iteration with iterator ErrIterOver ErrorCode = C.GIT_ITEROVER - // Authentication failed - ErrAuth ErrorCode = C.GIT_EAUTH ) var ( diff --git a/index.go b/index.go index 06495b9..1875e32 100644 --- a/index.go +++ b/index.go @@ -26,6 +26,24 @@ const ( IndexAddCheckPathspec IndexAddOpts = C.GIT_INDEX_ADD_CHECK_PATHSPEC ) +type IndexStageOpts int + +const ( + // IndexStageAny matches any index stage. + // + // Some index APIs take a stage to match; pass this value to match + // any entry matching the path regardless of stage. + IndexStageAny IndexStageOpts = C.GIT_INDEX_STAGE_ANY + // IndexStageNormal is a normal staged file in the index. + IndexStageNormal IndexStageOpts = C.GIT_INDEX_STAGE_NORMAL + // IndexStageAncestor is the ancestor side of a conflict. + IndexStageAncestor IndexStageOpts = C.GIT_INDEX_STAGE_ANCESTOR + // IndexStageOurs is the "ours" side of a conflict. + IndexStageOurs IndexStageOpts = C.GIT_INDEX_STAGE_OURS + // IndexStageTheirs is the "theirs" side of a conflict. + IndexStageTheirs IndexStageOpts = C.GIT_INDEX_STAGE_THEIRS +) + type Index struct { ptr *C.git_index } diff --git a/merge.go b/merge.go index a52e8f8..53d5a72 100644 --- a/merge.go +++ b/merge.go @@ -81,7 +81,14 @@ func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, e type MergeTreeFlag int const ( + // Detect renames that occur between the common ancestor and the "ours" + // side or the common ancestor and the "theirs" side. This will enable + // the ability to merge between a modified and renamed file. MergeTreeFindRenames MergeTreeFlag = C.GIT_MERGE_TREE_FIND_RENAMES + // If a conflict occurs, exit immediately instead of attempting to + // continue resolving conflicts. The merge operation will fail with + // GIT_EMERGECONFLICT and no index will be returned. + MergeTreeFailOnConflict MergeTreeFlag = C.GIT_MERGE_TREE_FAIL_ON_CONFLICT ) type MergeOptions struct { diff --git a/remote.go b/remote.go index b3aba54..a216513 100644 --- a/remote.go +++ b/remote.go @@ -112,6 +112,9 @@ type FetchOptions struct { // // The default is to auto-follow tags. DownloadTags DownloadTags + + // Headers are extra headers for the fetch operation. + Headers []string } type Remote struct { @@ -157,6 +160,9 @@ type PushOptions struct { RemoteCallbacks RemoteCallbacks PbParallelism uint + + // Headers are extra headers for the push operation. + Headers []string } type RemoteHead struct { @@ -594,6 +600,10 @@ func populateFetchOptions(options *C.git_fetch_options, opts *FetchOptions) { options.prune = C.git_fetch_prune_t(opts.Prune) options.update_fetchhead = cbool(opts.UpdateFetchhead) options.download_tags = C.git_remote_autotag_option_t(opts.DownloadTags) + + options.custom_headers = C.git_strarray{} + options.custom_headers.count = C.size_t(len(opts.Headers)) + options.custom_headers.strings = makeCStringsFromStrings(opts.Headers) } func populatePushOptions(options *C.git_push_options, opts *PushOptions) { @@ -604,6 +614,10 @@ func populatePushOptions(options *C.git_push_options, opts *PushOptions) { options.pb_parallelism = C.uint(opts.PbParallelism) + options.custom_headers = C.git_strarray{} + options.custom_headers.count = C.size_t(len(opts.Headers)) + options.custom_headers.strings = makeCStringsFromStrings(opts.Headers) + populateRemoteCallbacks(&options.callbacks, &opts.RemoteCallbacks) } @@ -626,6 +640,7 @@ func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error var coptions C.git_fetch_options populateFetchOptions(&coptions, opts) defer untrackCalbacksPayload(&coptions.callbacks) + defer freeStrarray(&coptions.custom_headers) runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -637,22 +652,34 @@ func (o *Remote) Fetch(refspecs []string, opts *FetchOptions, msg string) error return nil } -func (o *Remote) ConnectFetch(callbacks *RemoteCallbacks) error { - return o.Connect(ConnectDirectionFetch, callbacks) +func (o *Remote) ConnectFetch(callbacks *RemoteCallbacks, headers []string) error { + return o.Connect(ConnectDirectionFetch, callbacks, headers) } -func (o *Remote) ConnectPush(callbacks *RemoteCallbacks) error { - return o.Connect(ConnectDirectionPush, callbacks) +func (o *Remote) ConnectPush(callbacks *RemoteCallbacks, headers []string) error { + return o.Connect(ConnectDirectionPush, callbacks, headers) } -func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks) error { +// Connect opens a connection to a remote. +// +// The transport is selected based on the URL. The direction argument +// is due to a limitation of the git protocol (over TCP or SSH) which +// starts up a specific binary which can only do the one or the other. +// +// 'headers' are extra HTTP headers to use in this connection. +func (o *Remote) Connect(direction ConnectDirection, callbacks *RemoteCallbacks, headers []string) error { var ccallbacks C.git_remote_callbacks populateRemoteCallbacks(&ccallbacks, callbacks) + cheaders := C.git_strarray{} + cheaders.count = C.size_t(len(headers)) + cheaders.strings = makeCStringsFromStrings(headers) + defer freeStrarray(&cheaders) + runtime.LockOSThread() defer runtime.UnlockOSThread() - if ret := C.git_remote_connect(o.ptr, C.git_direction(direction), &ccallbacks); ret != 0 { + if ret := C.git_remote_connect(o.ptr, C.git_direction(direction), &ccallbacks, &cheaders); ret != 0 { return MakeGitError(ret) } return nil @@ -713,6 +740,7 @@ func (o *Remote) Push(refspecs []string, opts *PushOptions) error { var coptions C.git_push_options populatePushOptions(&coptions, opts) defer untrackCalbacksPayload(&coptions.callbacks) + defer freeStrarray(&coptions.custom_headers) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/remote_test.go b/remote_test.go index dac3dbe..978b803 100644 --- a/remote_test.go +++ b/remote_test.go @@ -58,7 +58,7 @@ func TestRemoteConnect(t *testing.T) { remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository") checkFatal(t, err) - err = remote.ConnectFetch(nil) + err = remote.ConnectFetch(nil, nil) checkFatal(t, err) } @@ -69,7 +69,7 @@ func TestRemoteLs(t *testing.T) { remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository") checkFatal(t, err) - err = remote.ConnectFetch(nil) + err = remote.ConnectFetch(nil, nil) checkFatal(t, err) heads, err := remote.Ls() @@ -87,7 +87,7 @@ func TestRemoteLsFiltering(t *testing.T) { remote, err := repo.Remotes.Create("origin", "https://github.com/libgit2/TestGitRepository") checkFatal(t, err) - err = remote.ConnectFetch(nil) + err = remote.ConnectFetch(nil, nil) checkFatal(t, err) heads, err := remote.Ls("master") @@ -166,7 +166,7 @@ func TestRemotePrune(t *testing.T) { rr, err := repo.Remotes.Lookup("origin") checkFatal(t, err) - err = rr.ConnectFetch(nil) + err = rr.ConnectFetch(nil, nil) checkFatal(t, err) err = rr.Prune(nil) diff --git a/vendor/libgit2 b/vendor/libgit2 index ed38e26..821131f 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit ed38e26db5435b519d8b796e4b6c2c660fe982b5 +Subproject commit 821131fdaee74526d84aaf1c6ceddc2139c551df From 1cdf1d70a2c08b1b87611be11cb448075ea45f2b Mon Sep 17 00:00:00 2001 From: FUJII Ryota Date: Wed, 16 Dec 2015 16:37:50 +0900 Subject: [PATCH 08/14] Fix a memory leak in Index.EntryByPath() --- index.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.go b/index.go index 1875e32..8417b65 100644 --- a/index.go +++ b/index.go @@ -350,10 +350,13 @@ func (v *Index) EntryByIndex(index uint) (*IndexEntry, error) { } func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + runtime.LockOSThread() defer runtime.UnlockOSThread() - centry := C.git_index_get_bypath(v.ptr, C.CString(path), C.int(stage)) + centry := C.git_index_get_bypath(v.ptr, cpath, C.int(stage)) if centry == nil { return nil, MakeGitError(C.GIT_ENOTFOUND) } From 20ab28bfeacbfd0c0b1a83e471de8de5610f9de8 Mon Sep 17 00:00:00 2001 From: FUJII Ryota Date: Mon, 21 Dec 2015 18:19:03 +0900 Subject: [PATCH 09/14] Add Index.Find() and Index.FindPrefix() --- index.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/index.go b/index.go index 8417b65..16e63a1 100644 --- a/index.go +++ b/index.go @@ -363,6 +363,36 @@ func (v *Index) EntryByPath(path string, stage int) (*IndexEntry, error) { return newIndexEntryFromC(centry), nil } +func (v *Index) Find(path string) (uint, error) { + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var pos C.size_t + ret := C.git_index_find(&pos, v.ptr, cpath) + if ret < 0 { + return uint(0), MakeGitError(ret) + } + return uint(pos), nil +} + +func (v *Index) FindPrefix(prefix string) (uint, error) { + cprefix := C.CString(prefix) + defer C.free(unsafe.Pointer(cprefix)) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var pos C.size_t + ret := C.git_index_find_prefix(&pos, v.ptr, cprefix) + if ret < 0 { + return uint(0), MakeGitError(ret) + } + return uint(pos), nil +} + func (v *Index) HasConflicts() bool { return C.git_index_has_conflicts(v.ptr) != 0 } From 1bc7cf60bd05958ad619c22373183afffb913a0c Mon Sep 17 00:00:00 2001 From: Michael Gehring Date: Mon, 4 Jan 2016 14:47:02 +0100 Subject: [PATCH 10/14] Add missing RepositoryOpenExtended arguments Fixes #277 --- repository.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/repository.go b/repository.go index d8e398b..398f91a 100644 --- a/repository.go +++ b/repository.go @@ -62,15 +62,29 @@ func OpenRepository(path string) (*Repository, error) { return newRepositoryFromC(ptr), nil } -func OpenRepositoryExtended(path string) (*Repository, error) { +type RepositoryOpenFlag int + +const ( + RepositoryOpenNoSearch RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_NO_SEARCH + RepositoryOpenCrossFs RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_CROSS_FS + RepositoryOpenBare RepositoryOpenFlag = C.GIT_REPOSITORY_OPEN_BARE +) + +func OpenRepositoryExtended(path string, flags RepositoryOpenFlag, ceiling string) (*Repository, error) { cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) + var cceiling *C.char = nil + if len(ceiling) > 0 { + cceiling = C.CString(ceiling) + defer C.free(unsafe.Pointer(cceiling)) + } + runtime.LockOSThread() defer runtime.UnlockOSThread() var ptr *C.git_repository - ret := C.git_repository_open_ext(&ptr, cpath, 0, nil) + ret := C.git_repository_open_ext(&ptr, cpath, C.uint(flags), cceiling) if ret < 0 { return nil, MakeGitError(ret) } From aa59dccea724221f99ea57a8f803101b786809ef Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 16 Feb 2016 17:22:43 +0100 Subject: [PATCH 11/14] Upgrade to libgit2 to 0f9d15493d5d8ad4353dd7beed52c9567334f6e5 --- blame.go | 6 +++--- diff.go | 6 +++--- merge.go | 10 +++++----- vendor/libgit2 | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/blame.go b/blame.go index c24c934..b07d6bc 100644 --- a/blame.go +++ b/blame.go @@ -58,8 +58,8 @@ func (v *Repository) BlameFile(path string, opts *BlameOptions) (*Blame, error) version: C.GIT_BLAME_OPTIONS_VERSION, flags: C.uint32_t(opts.Flags), min_match_characters: C.uint16_t(opts.MinMatchCharacters), - min_line: C.uint32_t(opts.MinLine), - max_line: C.uint32_t(opts.MaxLine), + min_line: C.size_t(opts.MinLine), + max_line: C.size_t(opts.MaxLine), } if opts.NewestCommit != nil { copts.newest_commit = *opts.NewestCommit.toC() @@ -100,7 +100,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.uint32_t(lineno)) + ptr := C.git_blame_get_hunk_byline(blame.ptr, C.size_t(lineno)) if ptr == nil { return BlameHunk{}, ErrInvalid } diff --git a/diff.go b/diff.go index de56374..565fcee 100644 --- a/diff.go +++ b/diff.go @@ -550,7 +550,7 @@ func diffOptionsToC(opts *DiffOptions) (copts *C.git_diff_options, notifyData *d if opts.NotifyCallback != nil { C._go_git_setup_diff_notify_callbacks(copts) - copts.notify_payload = pointerHandles.Track(notifyData) + copts.payload = pointerHandles.Track(notifyData) } } return @@ -562,8 +562,8 @@ func freeDiffOptions(copts *C.git_diff_options) { freeStrarray(&cpathspec) C.free(unsafe.Pointer(copts.old_prefix)) C.free(unsafe.Pointer(copts.new_prefix)) - if copts.notify_payload != nil { - pointerHandles.Untrack(copts.notify_payload) + if copts.payload != nil { + pointerHandles.Untrack(copts.payload) } } } diff --git a/merge.go b/merge.go index 0b0a8f1..9ca50fd 100644 --- a/merge.go +++ b/merge.go @@ -84,11 +84,11 @@ const ( // Detect renames that occur between the common ancestor and the "ours" // side or the common ancestor and the "theirs" side. This will enable // the ability to merge between a modified and renamed file. - MergeTreeFindRenames MergeTreeFlag = C.GIT_MERGE_TREE_FIND_RENAMES + MergeTreeFindRenames MergeTreeFlag = C.GIT_MERGE_FIND_RENAMES // If a conflict occurs, exit immediately instead of attempting to // continue resolving conflicts. The merge operation will fail with // GIT_EMERGECONFLICT and no index will be returned. - MergeTreeFailOnConflict MergeTreeFlag = C.GIT_MERGE_TREE_FAIL_ON_CONFLICT + MergeTreeFailOnConflict MergeTreeFlag = C.GIT_MERGE_FAIL_ON_CONFLICT ) type MergeOptions struct { @@ -105,7 +105,7 @@ type MergeOptions struct { func mergeOptionsFromC(opts *C.git_merge_options) MergeOptions { return MergeOptions{ Version: uint(opts.version), - TreeFlags: MergeTreeFlag(opts.tree_flags), + TreeFlags: MergeTreeFlag(opts.flags), RenameThreshold: uint(opts.rename_threshold), TargetLimit: uint(opts.target_limit), FileFavor: MergeFileFavor(opts.file_favor), @@ -131,7 +131,7 @@ func (mo *MergeOptions) toC() *C.git_merge_options { } return &C.git_merge_options{ version: C.uint(mo.Version), - tree_flags: C.git_merge_tree_flag_t(mo.TreeFlags), + flags: C.git_merge_flag_t(mo.TreeFlags), rename_threshold: C.uint(mo.RenameThreshold), target_limit: C.uint(mo.TargetLimit), file_favor: C.git_merge_file_favor_t(mo.FileFavor), @@ -374,7 +374,7 @@ func populateCMergeFileOptions(c *C.git_merge_file_options, options MergeFileOpt c.our_label = C.CString(options.OurLabel) c.their_label = C.CString(options.TheirLabel) c.favor = C.git_merge_file_favor_t(options.Favor) - c.flags = C.uint(options.Flags) + c.flags = C.git_merge_file_flag_t(options.Flags) } func freeCMergeFileOptions(c *C.git_merge_file_options) { diff --git a/vendor/libgit2 b/vendor/libgit2 index 821131f..0f9d154 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 821131fdaee74526d84aaf1c6ceddc2139c551df +Subproject commit 0f9d15493d5d8ad4353dd7beed52c9567334f6e5 From 090dc7ee3901d08d46b02d42b4f1fe248ecc3e6c Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Wed, 27 Jan 2016 18:11:12 +0100 Subject: [PATCH 12/14] Use Filemode in TreeBuilder.Insert, and add test coverage for some TreeBuilder methods. --- tree.go | 2 +- tree_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tree.go b/tree.go index 8288176..eba9f3d 100644 --- a/tree.go +++ b/tree.go @@ -149,7 +149,7 @@ func (v *TreeBuilder) Free() { C.git_treebuilder_free(v.ptr) } -func (v *TreeBuilder) Insert(filename string, id *Oid, filemode int) error { +func (v *TreeBuilder) Insert(filename string, id *Oid, filemode Filemode) error { cfilename := C.CString(filename) defer C.free(unsafe.Pointer(cfilename)) diff --git a/tree_test.go b/tree_test.go index 4c6a4ed..fae395a 100644 --- a/tree_test.go +++ b/tree_test.go @@ -20,3 +20,44 @@ func TestTreeEntryById(t *testing.T) { t.Fatalf("entry id %v was not found", id) } } + +func TestTreeBuilderInsert(t *testing.T) { + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + subTree, err := repo.TreeBuilder() + if err != nil { + t.Fatalf("TreeBuilder: %v", err) + } + defer subTree.Free() + + odb, err := repo.Odb() + if err != nil { + t.Fatalf("repo.Odb: %v", err) + } + blobId, err := odb.Write([]byte("hello"), ObjectBlob) + if err != nil { + t.Fatalf("odb.Write: %v", err) + } + if err = subTree.Insert("subfile", blobId, FilemodeBlobExecutable); err != nil { + t.Fatalf("TreeBuilder.Insert: %v", err) + } + treeID, err := subTree.Write() + if err != nil { + t.Fatalf("TreeBuilder.Write: %v", err) + } + + tree, err := repo.LookupTree(treeID) + if err != nil { + t.Fatalf("LookupTree: %v", err) + } + + entry, err := tree.EntryByPath("subfile") + if err != nil { + t.Fatalf("tree.EntryByPath(%q): %v", "subfile", err) + } + + if !entry.Id.Equal(blobId) { + t.Fatalf("got oid %v, want %v", entry.Id, blobId) + } +} From 251d89e1d41037185df0ea89e9aab208efc40d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 19 Feb 2016 13:59:50 +0100 Subject: [PATCH 13/14] Update vendored libgit2 --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index 0f9d154..f596946 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit 0f9d15493d5d8ad4353dd7beed52c9567334f6e5 +Subproject commit f596946f09f3c1e51239a24ff41e27f2c1ffa2b7 From e095c85fd06b5820d2f0098ff3e66b266553dbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Mon, 7 Mar 2016 11:16:07 +0100 Subject: [PATCH 14/14] Update to 785d8c --- vendor/libgit2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/libgit2 b/vendor/libgit2 index f596946..785d8c4 160000 --- a/vendor/libgit2 +++ b/vendor/libgit2 @@ -1 +1 @@ -Subproject commit f596946f09f3c1e51239a24ff41e27f2c1ffa2b7 +Subproject commit 785d8c48ea8725691da3c50e7dae8751523d4c30