From 51e7cf0ad4888998e5bb40161bc1516c778cf547 Mon Sep 17 00:00:00 2001 From: Matthew Donoughe Date: Fri, 13 Feb 2015 20:44:29 -0500 Subject: [PATCH 1/8] use git_signature_free --- reference.go | 6 +++--- remote.go | 4 ++-- repository.go | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/reference.go b/reference.go index 46436a6..407334c 100644 --- a/reference.go +++ b/reference.go @@ -37,7 +37,7 @@ func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) defer runtime.UnlockOSThread() csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { @@ -62,7 +62,7 @@ func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Referen defer runtime.UnlockOSThread() csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { @@ -100,7 +100,7 @@ func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) defer C.free(unsafe.Pointer(cname)) csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { diff --git a/remote.go b/remote.go index 2684c20..410f491 100644 --- a/remote.go +++ b/remote.go @@ -605,7 +605,7 @@ func (o *Remote) Fetch(refspecs []string, sig *Signature, msg string) error { var csig *C.git_signature = nil if sig != nil { csig = sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) } var cmsg *C.char = nil @@ -697,7 +697,7 @@ func (o *Remote) Push(refspecs []string, opts *PushOptions, sig *Signature, msg var csig *C.git_signature = nil if sig != nil { csig = sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) } var cmsg *C.char diff --git a/repository.go b/repository.go index 7760c3a..5f51058 100644 --- a/repository.go +++ b/repository.go @@ -211,7 +211,7 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error { defer C.free(unsafe.Pointer(cname)) csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg != "" { @@ -231,7 +231,7 @@ func (v *Repository) SetHead(refname string, sig *Signature, msg string) error { func (v *Repository) SetHeadDetached(id *Oid, sig *Signature, msg string) error { csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg != "" { @@ -254,7 +254,7 @@ func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Sign defer C.free(unsafe.Pointer(cname)) csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { @@ -285,7 +285,7 @@ func (v *Repository) CreateSymbolicReference(name, target string, force bool, si defer C.free(unsafe.Pointer(ctarget)) csig := sig.toC() - defer C.free(unsafe.Pointer(csig)) + defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { From c1df2dcdc16cab82e356940658fd83fdd0a3b5b2 Mon Sep 17 00:00:00 2001 From: Fernando Oliveira Date: Thu, 30 Apr 2015 23:16:12 -0300 Subject: [PATCH 2/8] Add method to check if repo is detached --- repository.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/repository.go b/repository.go index 7fac277..b6c75ef 100644 --- a/repository.go +++ b/repository.go @@ -255,6 +255,20 @@ func (v *Repository) SetHeadDetached(id *Oid, sig *Signature, msg string) error return nil } +func (v *Repository) IsHeadDetached() (bool, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_repository_head_detached(v.ptr) + switch ret { + case 1: + return true, nil + case 0: + return false, nil + } + return false, MakeGitError(ret) +} + func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Signature, msg string) (*Reference, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) From af7739787c8e9e679adf1c6327d2c8310339b726 Mon Sep 17 00:00:00 2001 From: Mike Edgar Date: Sun, 7 Jun 2015 19:20:43 -0400 Subject: [PATCH 3/8] Add error code matching GIT_EAUTH for authentication failures --- git.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/git.go b/git.go index 4f1a65e..a44459f 100644 --- a/git.go +++ b/git.go @@ -87,6 +87,8 @@ const ( ErrPassthrough ErrorCode = C.GIT_PASSTHROUGH // Signals end of iteration with iterator ErrIterOver ErrorCode = C.GIT_ITEROVER + // Authentication failed + ErrAuth ErrorCode = C.GIT_EAUTH ) var ( From 830e1714632ad87a42008327badb9a481ff1c37e Mon Sep 17 00:00:00 2001 From: shinningstar Date: Mon, 8 Jun 2015 22:36:31 +0800 Subject: [PATCH 4/8] Free reference resource allocated by libgit2 during go garbage collecting --- branch.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/branch.go b/branch.go index 22b767e..42e1216 100644 --- a/branch.go +++ b/branch.go @@ -92,7 +92,7 @@ func (repo *Repository) NewBranchIterator(flags BranchType) (*BranchIterator, er func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, msg string) (*Branch, error) { - ref := new(Reference) + var ptr *C.git_reference cBranchName := C.CString(branchName) cForce := cbool(force) @@ -113,11 +113,11 @@ func (repo *Repository) CreateBranch(branchName string, target *Commit, force bo runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.cast_ptr, cForce, cSignature, cmsg) + ret := C.git_branch_create(&ptr, repo.ptr, cBranchName, target.cast_ptr, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } - return ref.Branch(), nil + return newReferenceFromC(ptr, repo).Branch(), nil } func (b *Branch) Delete() error { From c00a05586b63df56a2c619e456229c1c9f785fa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 10 Jun 2015 13:03:53 +0200 Subject: [PATCH 5/8] Make the network code use handles This wasn't ported together with the rest, but it does exhibit the same issues, so let's port it over now. --- clone.go | 12 +++++++----- remote.go | 26 ++++++++++++++++---------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/clone.go b/clone.go index b796b6e..4de4aea 100644 --- a/clone.go +++ b/clone.go @@ -28,18 +28,20 @@ func Clone(url string, path string, options *CloneOptions) (*Repository, error) cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) - var copts C.git_clone_options - populateCloneOptions(&copts, options) - defer freeCheckoutOpts(&copts.checkout_opts) + copts := (*C.git_clone_options)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_clone_options{})))) + populateCloneOptions(copts, options) if len(options.CheckoutBranch) != 0 { copts.checkout_branch = C.CString(options.CheckoutBranch) - defer C.free(unsafe.Pointer(copts.checkout_branch)) } runtime.LockOSThread() defer runtime.UnlockOSThread() - ret := C.git_clone(&repo.ptr, curl, cpath, &copts) + ret := C.git_clone(&repo.ptr, curl, cpath, copts) + freeCheckoutOpts(&copts.checkout_opts) + C.free(unsafe.Pointer(copts.checkout_branch)) + C.free(unsafe.Pointer(copts)) + if ret < 0 { return nil, MakeGitError(ret) } diff --git a/remote.go b/remote.go index 84750d3..b9acc71 100644 --- a/remote.go +++ b/remote.go @@ -129,12 +129,12 @@ func populateRemoteCallbacks(ptr *C.git_remote_callbacks, callbacks *RemoteCallb return } C._go_git_setup_callbacks(ptr) - ptr.payload = unsafe.Pointer(callbacks) + ptr.payload = pointerHandles.Track(callbacks) } //export sidebandProgressCallback func sidebandProgressCallback(_str *C.char, _len C.int, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.SidebandProgressCallback == nil { return 0 } @@ -144,7 +144,7 @@ func sidebandProgressCallback(_str *C.char, _len C.int, data unsafe.Pointer) int //export completionCallback func completionCallback(completion_type C.git_remote_completion_type, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.CompletionCallback == nil { return 0 } @@ -153,7 +153,7 @@ func completionCallback(completion_type C.git_remote_completion_type, data unsaf //export credentialsCallback func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C.char, allowed_types uint, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.CredentialsCallback == nil { return 0 } @@ -166,7 +166,7 @@ func credentialsCallback(_cred **C.git_cred, _url *C.char, _username_from_url *C //export transferProgressCallback func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.TransferProgressCallback == nil { return 0 } @@ -175,7 +175,7 @@ func transferProgressCallback(stats *C.git_transfer_progress, data unsafe.Pointe //export updateTipsCallback func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.UpdateTipsCallback == nil { return 0 } @@ -187,7 +187,7 @@ func updateTipsCallback(_refname *C.char, _a *C.git_oid, _b *C.git_oid, data uns //export certificateCheckCallback func certificateCheckCallback(_cert *C.git_cert, _valid C.int, _host *C.char, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) // if there's no callback set, we need to make sure we fail if the library didn't consider this cert valid if callbacks.CertificateCheckCallback == nil { if _valid == 1 { @@ -228,7 +228,7 @@ func certificateCheckCallback(_cert *C.git_cert, _valid C.int, _host *C.char, da //export packProgressCallback func packProgressCallback(stage C.int, current, total C.uint, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.PackProgressCallback == nil { return 0 @@ -239,7 +239,7 @@ func packProgressCallback(stage C.int, current, total C.uint, data unsafe.Pointe //export pushTransferProgressCallback func pushTransferProgressCallback(current, total C.uint, bytes C.size_t, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.PushTransferProgressCallback == nil { return 0 } @@ -249,7 +249,7 @@ func pushTransferProgressCallback(current, total C.uint, bytes C.size_t, data un //export pushUpdateReferenceCallback func pushUpdateReferenceCallback(refname, status *C.char, data unsafe.Pointer) int { - callbacks := (*RemoteCallbacks)(data) + callbacks, _ := pointerHandles.Get(data).(*RemoteCallbacks) if callbacks.PushUpdateReferenceCallback == nil { return 0 @@ -286,6 +286,12 @@ func (r *Remote) SetCallbacks(callbacks *RemoteCallbacks) error { func (r *Remote) Free() { runtime.SetFinalizer(r, nil) + + callbacks := C.git_remote_get_callbacks(r.ptr) + if callbacks != nil && callbacks.payload != nil { + pointerHandles.Untrack(callbacks.payload) + } + C.git_remote_free(r.ptr) } From 86e9917919afd0f71340c0a2ebc8ee28f2030790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 12 Jun 2015 17:45:11 +0200 Subject: [PATCH 6/8] diff: remove unnecessary args to Hunk and Line ctors --- diff.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/diff.go b/diff.go index 5e03175..aa422fc 100644 --- a/diff.go +++ b/diff.go @@ -94,7 +94,7 @@ type DiffHunk struct { Header string } -func diffHunkFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk) DiffHunk { +func diffHunkFromC(hunk *C.git_diff_hunk) DiffHunk { return DiffHunk{ OldStart: int(hunk.old_start), OldLines: int(hunk.old_lines), @@ -112,7 +112,7 @@ type DiffLine struct { Content string } -func diffLineFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line) DiffLine { +func diffLineFromC(line *C.git_diff_line) DiffLine { return DiffLine{ Origin: DiffLineType(line.origin), OldLineno: int(line.old_lineno), @@ -309,7 +309,7 @@ func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, handle un data.LineCallback = nil if data.HunkCallback != nil { - cb, err := data.HunkCallback(diffHunkFromC(delta, hunk)) + cb, err := data.HunkCallback(diffHunkFromC(hunk)) if err != nil { data.Error = err return -1 @@ -330,7 +330,7 @@ func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.g panic("could not retrieve data for handle") } - err := data.LineCallback(diffLineFromC(delta, hunk, line)) + err := data.LineCallback(diffLineFromC(line)) if err != nil { data.Error = err return -1 From e066d24efba9587a66cf9eb6221b4a38c513c26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Fri, 12 Jun 2015 19:10:00 +0200 Subject: [PATCH 7/8] Add DiffBlobs This lets you diff two arbitrary blobs with arbitrary names. --- diff.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ diff_test.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 21 +++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/diff.go b/diff.go index aa422fc..de56374 100644 --- a/diff.go +++ b/diff.go @@ -5,6 +5,7 @@ package git extern int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLine, void *payload); extern void _go_git_setup_diff_notify_callbacks(git_diff_options* opts); +extern int _go_git_diff_blobs(git_blob *old, const char *old_path, git_blob *new, const char *new_path, git_diff_options *opts, int eachFile, int eachHunk, int eachLine, void *payload); */ import "C" import ( @@ -670,3 +671,50 @@ func (v *Repository) DiffIndexToWorkdir(index *Index, opts *DiffOptions) (*Diff, } return newDiffFromC(diffPtr), nil } + +// DiffBlobs performs a diff between two arbitrary blobs. You can pass +// whatever file names you'd like for them to appear as in the diff. +func DiffBlobs(oldBlob *Blob, oldAsPath string, newBlob *Blob, newAsPath string, opts *DiffOptions, fileCallback DiffForEachFileCallback, detail DiffDetail) error { + data := &diffForEachData{ + FileCallback: fileCallback, + } + + intHunks := C.int(0) + if detail >= DiffDetailHunks { + intHunks = C.int(1) + } + + intLines := C.int(0) + if detail >= DiffDetailLines { + intLines = C.int(1) + } + + handle := pointerHandles.Track(data) + defer pointerHandles.Untrack(handle) + + var oldBlobPtr, newBlobPtr *C.git_blob + if oldBlob != nil { + oldBlobPtr = oldBlob.cast_ptr + } + if newBlob != nil { + newBlobPtr = newBlob.cast_ptr + } + + oldBlobPath := C.CString(oldAsPath) + defer C.free(unsafe.Pointer(oldBlobPath)) + newBlobPath := C.CString(newAsPath) + defer C.free(unsafe.Pointer(newBlobPath)) + + copts, _ := diffOptionsToC(opts) + defer freeDiffOptions(copts) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C._go_git_diff_blobs(oldBlobPtr, oldBlobPath, newBlobPtr, newBlobPath, copts, 1, intHunks, intLines, handle) + if ecode < 0 { + return MakeGitError(ecode) + } + + return nil +} diff --git a/diff_test.go b/diff_test.go index 464fae6..850ed8e 100644 --- a/diff_test.go +++ b/diff_test.go @@ -187,3 +187,50 @@ func createTestTrees(t *testing.T, repo *Repository) (originalTree *Tree, newTre return originalTree, newTree } + +func TestDiffBlobs(t *testing.T) { + repo := createTestRepo(t) + defer cleanupTestRepo(t, repo) + + odb, err := repo.Odb() + checkFatal(t, err) + + id1, err := odb.Write([]byte("hello\nhello\n"), ObjectBlob) + checkFatal(t, err) + + id2, err := odb.Write([]byte("hallo\nhallo\n"), ObjectBlob) + checkFatal(t, err) + + blob1, err := repo.LookupBlob(id1) + checkFatal(t, err) + + blob2, err := repo.LookupBlob(id2) + checkFatal(t, err) + + var files, hunks, lines int + err = DiffBlobs(blob1, "hi", blob2, "hi", nil, + func(delta DiffDelta, progress float64) (DiffForEachHunkCallback, error) { + files++ + return func(hunk DiffHunk) (DiffForEachLineCallback, error) { + hunks++ + return func(line DiffLine) error { + lines++ + return nil + }, nil + }, nil + }, + DiffDetailLines) + + if files != 1 { + t.Fatal("Bad number of files iterated") + } + + if hunks != 1 { + t.Fatal("Bad number of hunks iterated") + } + + // two removals, two additions + if lines != 4 { + t.Fatalf("Bad number of lines iterated") + } +} diff --git a/wrapper.c b/wrapper.c index 938fd17..017168d 100644 --- a/wrapper.c +++ b/wrapper.c @@ -62,6 +62,27 @@ int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLin return git_diff_foreach(diff, fcb, hcb, lcb, payload); } +int _go_git_diff_blobs(git_blob *old, const char *old_path, git_blob *new, const char *new_path, git_diff_options *opts, int eachFile, int eachHunk, int eachLine, void *payload) +{ + git_diff_file_cb fcb = NULL; + git_diff_hunk_cb hcb = NULL; + git_diff_line_cb lcb = NULL; + + if (eachFile) { + fcb = (git_diff_file_cb)&diffForEachFileCb; + } + + if (eachHunk) { + hcb = (git_diff_hunk_cb)&diffForEachHunkCb; + } + + if (eachLine) { + lcb = (git_diff_line_cb)&diffForEachLineCb; + } + + return git_diff_blobs(old, old_path, new, new_path, opts, fcb, hcb, lcb, payload); +} + void _go_git_setup_diff_notify_callbacks(git_diff_options *opts) { opts->notify_cb = (git_diff_notify_cb)diffNotifyCb; } From 4eae20ec279d20948aa5a45e0963ae7c4bcb0712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Wed, 1 Jul 2015 16:00:17 +0200 Subject: [PATCH 8/8] Adjust style --- repository.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/repository.go b/repository.go index c271ea6..996e966 100644 --- a/repository.go +++ b/repository.go @@ -260,13 +260,11 @@ func (v *Repository) IsHeadDetached() (bool, error) { defer runtime.UnlockOSThread() ret := C.git_repository_head_detached(v.ptr) - switch ret { - case 1: - return true, nil - case 0: - return false, nil + if ret < 0 { + return false, MakeGitError(ret) } - return false, MakeGitError(ret) + + return ret != 0, nil } func (v *Repository) CreateReference(name string, id *Oid, force bool, sig *Signature, msg string) (*Reference, error) {