From 367cd8eb9b84538933774befa76c099298c32c81 Mon Sep 17 00:00:00 2001 From: Calin Seciu Date: Mon, 26 Oct 2015 16:20:18 +0200 Subject: 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 --- merge.go | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'merge.go') 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 { -- cgit v1.2.3 From 3b5633de219eec2908723a8e557758cc055d84d1 Mon Sep 17 00:00:00 2001 From: Carlos Martín Nieto Date: Mon, 26 Oct 2015 21:22:22 +0100 Subject: Mention that MergeAnalysis is a bitmask --- merge.go | 3 +++ 1 file changed, 3 insertions(+) (limited to 'merge.go') diff --git a/merge.go b/merge.go index bab53e0..272bf6a 100644 --- a/merge.go +++ b/merge.go @@ -178,6 +178,9 @@ const ( MergePreferenceFastForwardOnly MergePreference = C.GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY ) +// MergeAnalysis returns the possible actions which could be taken by +// a 'git-merge' command. There may be multiple answers, so the first +// return value is a bitmask of MergeAnalysis values. func (r *Repository) MergeAnalysis(theirHeads []*AnnotatedCommit) (MergeAnalysis, MergePreference, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() -- cgit v1.2.3 From 42b11d403d91e25754fe60c63c26371fbb7a89a9 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 7 Jan 2016 18:37:46 -0800 Subject: handles, merge, odb: changes for Go 1.6 pointer passing rules See http://tip.golang.org/cmd/cgo/#hdr-Passing_pointers . --- handles.go | 6 +++--- merge.go | 34 +++++++++++++++++++--------------- odb.go | 5 +++-- 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'merge.go') diff --git a/handles.go b/handles.go index a062231..a855717 100644 --- a/handles.go +++ b/handles.go @@ -52,12 +52,12 @@ func (v *HandleList) Track(pointer interface{}) unsafe.Pointer { v.Unlock() - return unsafe.Pointer(&slot) + return unsafe.Pointer(uintptr(slot)) } // Untrack stops tracking the pointer given by the handle func (v *HandleList) Untrack(handle unsafe.Pointer) { - slot := *(*int)(handle) + slot := int(uintptr(handle)) v.Lock() @@ -69,7 +69,7 @@ func (v *HandleList) Untrack(handle unsafe.Pointer) { // Get retrieves the pointer from the given handle func (v *HandleList) Get(handle unsafe.Pointer) interface{} { - slot := *(*int)(handle) + slot := int(uintptr(handle)) v.RLock() diff --git a/merge.go b/merge.go index 272bf6a..535a5e7 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), @@ -262,10 +262,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)) @@ -321,17 +321,21 @@ type MergeFileInput struct { } // populate a C struct with merge file input, make sure to use freeMergeFileInput to clean up allocs -func populateCMergeFileInput(c *C.git_merge_file_input, input MergeFileInput) { +func populateCMergeFileInput(c *C.git_merge_file_input, input MergeFileInput) *C.char { c.path = C.CString(input.Path) + var toFree *C.char if input.Contents != nil { - c.ptr = (*C.char)(unsafe.Pointer(&input.Contents[0])) + toFree = C.CString(string(input.Contents)) + c.ptr = toFree c.size = C.size_t(len(input.Contents)) } c.mode = C.uint(input.Mode) + return toFree } -func freeCMergeFileInput(c *C.git_merge_file_input) { +func freeCMergeFileInput(c *C.git_merge_file_input, toFree *C.char) { C.free(unsafe.Pointer(c.path)) + C.free(unsafe.Pointer(toFree)) } type MergeFileFlags int @@ -382,12 +386,12 @@ func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInp var cours C.git_merge_file_input var ctheirs C.git_merge_file_input - populateCMergeFileInput(&cancestor, ancestor) - defer freeCMergeFileInput(&cancestor) - populateCMergeFileInput(&cours, ours) - defer freeCMergeFileInput(&cours) - populateCMergeFileInput(&ctheirs, theirs) - defer freeCMergeFileInput(&ctheirs) + t := populateCMergeFileInput(&cancestor, ancestor) + defer freeCMergeFileInput(&cancestor, t) + t = populateCMergeFileInput(&cours, ours) + defer freeCMergeFileInput(&cours, t) + t = populateCMergeFileInput(&ctheirs, theirs) + defer freeCMergeFileInput(&ctheirs, t) var copts *C.git_merge_file_options if options != nil { diff --git a/odb.go b/odb.go index b15851f..8e8fba0 100644 --- a/odb.go +++ b/odb.go @@ -61,12 +61,13 @@ func (v *Odb) Exists(oid *Oid) bool { func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) { oid = new(Oid) - hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data)) + cstr := C.CString(string(data)) + defer C.free(unsafe.Pointer(cstr)) runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(hdr.Data), C.size_t(hdr.Len), C.git_otype(otype)) + ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(cstr), C.size_t(len(data)), C.git_otype(otype)) if ret < 0 { return nil, MakeGitError(ret) -- cgit v1.2.3 From a1f25eafec55509d49dffb4c84f7c5b729e6a85e Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 16 Feb 2016 21:34:43 -0800 Subject: handles, merge: simplify code, don't copy file contents --- handles.go | 14 ++++++-------- merge.go | 65 ++++++++++++++++++++++++++++++-------------------------------- wrapper.c | 23 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 42 deletions(-) (limited to 'merge.go') diff --git a/handles.go b/handles.go index a855717..f5d30f0 100644 --- a/handles.go +++ b/handles.go @@ -10,15 +10,14 @@ type HandleList struct { sync.RWMutex // stores the Go pointers handles []interface{} - // Indicates which indices are in use, and keeps a pointer to slot int variable (the handle) - // in the Go world, so that the Go garbage collector does not free it. - set map[int]*int + // Indicates which indices are in use. + set map[int]bool } func NewHandleList() *HandleList { return &HandleList{ handles: make([]interface{}, 5), - set: make(map[int]*int), + set: make(map[int]bool), } } @@ -26,8 +25,7 @@ func NewHandleList() *HandleList { // list. You must only run this function while holding a write lock. func (v *HandleList) findUnusedSlot() int { for i := 1; i < len(v.handles); i++ { - _, isUsed := v.set[i] - if !isUsed { + if !v.set[i] { return i } } @@ -48,7 +46,7 @@ func (v *HandleList) Track(pointer interface{}) unsafe.Pointer { slot := v.findUnusedSlot() v.handles[slot] = pointer - v.set[slot] = &slot // Keep a pointer to slot in Go world, so it's not freed by GC. + v.set[slot] = true v.Unlock() @@ -73,7 +71,7 @@ func (v *HandleList) Get(handle unsafe.Pointer) interface{} { v.RLock() - if _, ok := v.set[slot]; !ok { + if !v.set[slot] { panic(fmt.Sprintf("invalid pointer handle: %p", handle)) } diff --git a/merge.go b/merge.go index 535a5e7..06f5676 100644 --- a/merge.go +++ b/merge.go @@ -6,6 +6,7 @@ package git extern git_annotated_commit** _go_git_make_merge_head_array(size_t len); extern void _go_git_annotated_commit_array_set(git_annotated_commit** array, git_annotated_commit* ptr, size_t n); extern git_annotated_commit* _go_git_annotated_commit_array_get(git_annotated_commit** array, size_t n); +extern int _go_git_merge_file(git_merge_file_result*, char*, size_t, char*, unsigned int, char*, size_t, char*, unsigned int, char*, size_t, char*, unsigned int, git_merge_file_options*); */ import "C" @@ -85,8 +86,8 @@ const ( ) type MergeOptions struct { - Version uint - TreeFlags MergeTreeFlag + Version uint + TreeFlags MergeTreeFlag RenameThreshold uint TargetLimit uint @@ -98,7 +99,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), @@ -262,10 +263,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)) @@ -320,24 +321,6 @@ type MergeFileInput struct { Contents []byte } -// populate a C struct with merge file input, make sure to use freeMergeFileInput to clean up allocs -func populateCMergeFileInput(c *C.git_merge_file_input, input MergeFileInput) *C.char { - c.path = C.CString(input.Path) - var toFree *C.char - if input.Contents != nil { - toFree = C.CString(string(input.Contents)) - c.ptr = toFree - c.size = C.size_t(len(input.Contents)) - } - c.mode = C.uint(input.Mode) - return toFree -} - -func freeCMergeFileInput(c *C.git_merge_file_input, toFree *C.char) { - C.free(unsafe.Pointer(c.path)) - C.free(unsafe.Pointer(toFree)) -} - type MergeFileFlags int const ( @@ -382,16 +365,26 @@ func freeCMergeFileOptions(c *C.git_merge_file_options) { func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInput, options *MergeFileOptions) (*MergeFileResult, error) { - var cancestor C.git_merge_file_input - var cours C.git_merge_file_input - var ctheirs C.git_merge_file_input + ancestorPath := C.CString(ancestor.Path) + defer C.free(unsafe.Pointer(ancestorPath)) + var ancestorContents *byte + if len(ancestor.Contents) > 0 { + ancestorContents = &ancestor.Contents[0] + } + + oursPath := C.CString(ours.Path) + defer C.free(unsafe.Pointer(oursPath)) + var oursContents *byte + if len(ours.Contents) > 0 { + oursContents = &ours.Contents[0] + } - t := populateCMergeFileInput(&cancestor, ancestor) - defer freeCMergeFileInput(&cancestor, t) - t = populateCMergeFileInput(&cours, ours) - defer freeCMergeFileInput(&cours, t) - t = populateCMergeFileInput(&ctheirs, theirs) - defer freeCMergeFileInput(&ctheirs, t) + theirsPath := C.CString(theirs.Path) + defer C.free(unsafe.Pointer(theirsPath)) + var theirsContents *byte + if len(theirs.Contents) > 0 { + theirsContents = &theirs.Contents[0] + } var copts *C.git_merge_file_options if options != nil { @@ -408,7 +401,11 @@ func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInp defer runtime.UnlockOSThread() var result C.git_merge_file_result - ecode := C.git_merge_file(&result, &cancestor, &cours, &ctheirs, copts) + ecode := C._go_git_merge_file(&result, + (*C.char)(unsafe.Pointer(ancestorContents)), C.size_t(len(ancestor.Contents)), ancestorPath, C.uint(ancestor.Mode), + (*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) if ecode < 0 { return nil, MakeGitError(ecode) } diff --git a/wrapper.c b/wrapper.c index 2b1a180..a0688c0 100644 --- a/wrapper.c +++ b/wrapper.c @@ -141,4 +141,27 @@ int _go_git_tag_foreach(git_repository *repo, void *payload) return git_tag_foreach(repo, (git_tag_foreach_cb)&gitTagForeachCb, payload); } +int _go_git_merge_file(git_merge_file_result* out, char* ancestorContents, size_t ancestorLen, char* ancestorPath, unsigned int ancestorMode, char* oursContents, size_t oursLen, char* oursPath, unsigned int oursMode, char* theirsContents, size_t theirsLen, char* theirsPath, unsigned int theirsMode, git_merge_file_options* copts) { + git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT; + git_merge_file_input ours = GIT_MERGE_FILE_INPUT_INIT; + git_merge_file_input theirs = GIT_MERGE_FILE_INPUT_INIT; + + ancestor.ptr = ancestorContents; + ancestor.size = ancestorLen; + ancestor.path = ancestorPath; + ancestor.mode = ancestorMode; + + ours.ptr = oursContents; + ours.size = oursLen; + ours.path = oursPath; + ours.mode = oursMode; + + theirs.ptr = theirsContents; + theirs.size = theirsLen; + theirs.path = theirsPath; + theirs.mode = theirsMode; + + return git_merge_file(out, &ancestor, &ours, &theirs, copts); +} + /* EOF */ -- cgit v1.2.3 From ddbf1baab1f6d066f2bda591c1e68340845392c8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 16 Feb 2016 21:36:57 -0800 Subject: merge: remove whitespace change --- merge.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'merge.go') diff --git a/merge.go b/merge.go index 06f5676..756c792 100644 --- a/merge.go +++ b/merge.go @@ -265,8 +265,8 @@ func (r *Repository) MergeBases(one, two *Oid) ([]*Oid, error) { oids := make([]*Oid, coids.count) 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)) -- cgit v1.2.3 From aa59dccea724221f99ea57a8f803101b786809ef Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 16 Feb 2016 17:22:43 +0100 Subject: Upgrade to libgit2 to 0f9d15493d5d8ad4353dd7beed52c9567334f6e5 --- blame.go | 6 +++--- diff.go | 6 +++--- merge.go | 10 +++++----- vendor/libgit2 | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'merge.go') 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 -- cgit v1.2.3