summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--diff.go428
-rw-r--r--diff_test.go96
-rw-r--r--git.go4
-rw-r--r--git_test.go31
-rw-r--r--patch.go48
-rw-r--r--patch_test.go34
-rw-r--r--repository.go14
-rw-r--r--wrapper.c25
8 files changed, 680 insertions, 0 deletions
diff --git a/diff.go b/diff.go
new file mode 100644
index 0000000..6f3f554
--- /dev/null
+++ b/diff.go
@@ -0,0 +1,428 @@
+package git
+
+/*
+#include <git2.h>
+
+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);
+*/
+import "C"
+import (
+ "errors"
+ "runtime"
+ "unsafe"
+)
+
+type DiffFlag int
+
+const (
+ DiffFlagBinary DiffFlag = C.GIT_DIFF_FLAG_BINARY
+ DiffFlagNotBinary = C.GIT_DIFF_FLAG_NOT_BINARY
+ DiffFlagValidOid = C.GIT_DIFF_FLAG_VALID_ID
+)
+
+type Delta int
+
+const (
+ DeltaUnmodified Delta = C.GIT_DELTA_UNMODIFIED
+ DeltaAdded = C.GIT_DELTA_ADDED
+ DeltaDeleted = C.GIT_DELTA_DELETED
+ DeltaModified = C.GIT_DELTA_MODIFIED
+ DeltaRenamed = C.GIT_DELTA_RENAMED
+ DeltaCopied = C.GIT_DELTA_COPIED
+ DeltaIgnored = C.GIT_DELTA_IGNORED
+ DeltaUntracked = C.GIT_DELTA_UNTRACKED
+ DeltaTypeChange = C.GIT_DELTA_TYPECHANGE
+)
+
+type DiffLineType int
+
+const (
+ DiffLineContext DiffLineType = C.GIT_DIFF_LINE_CONTEXT
+ DiffLineAddition = C.GIT_DIFF_LINE_ADDITION
+ DiffLineDeletion = C.GIT_DIFF_LINE_DELETION
+ DiffLineContextEOFNL = C.GIT_DIFF_LINE_CONTEXT_EOFNL
+ DiffLineAddEOFNL = C.GIT_DIFF_LINE_ADD_EOFNL
+ DiffLineDelEOFNL = C.GIT_DIFF_LINE_DEL_EOFNL
+
+ DiffLineFileHdr = C.GIT_DIFF_LINE_FILE_HDR
+ DiffLineHunkHdr = C.GIT_DIFF_LINE_HUNK_HDR
+ DiffLineBinary = C.GIT_DIFF_LINE_BINARY
+)
+
+type DiffFile struct {
+ Path string
+ Oid *Oid
+ Size int
+ Flags DiffFlag
+ Mode uint16
+}
+
+func diffFileFromC(file *C.git_diff_file) DiffFile {
+ return DiffFile{
+ Path: C.GoString(file.path),
+ Oid: newOidFromC(&file.id),
+ Size: int(file.size),
+ Flags: DiffFlag(file.flags),
+ Mode: uint16(file.mode),
+ }
+}
+
+type DiffDelta struct {
+ Status Delta
+ Flags DiffFlag
+ Similarity uint16
+ OldFile DiffFile
+ NewFile DiffFile
+}
+
+func diffDeltaFromC(delta *C.git_diff_delta) DiffDelta {
+ return DiffDelta{
+ Status: Delta(delta.status),
+ Flags: DiffFlag(delta.flags),
+ Similarity: uint16(delta.similarity),
+ OldFile: diffFileFromC(&delta.old_file),
+ NewFile: diffFileFromC(&delta.new_file),
+ }
+}
+
+type DiffHunk struct {
+ OldStart int
+ OldLines int
+ NewStart int
+ NewLines int
+ Header string
+}
+
+func diffHunkFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk) DiffHunk {
+ return DiffHunk{
+ OldStart: int(hunk.old_start),
+ OldLines: int(hunk.old_lines),
+ NewStart: int(hunk.new_start),
+ NewLines: int(hunk.new_lines),
+ Header: C.GoStringN(&hunk.header[0], C.int(hunk.header_len)),
+ }
+}
+
+type DiffLine struct {
+ Origin DiffLineType
+ OldLineno int
+ NewLineno int
+ NumLines int
+ Content string
+}
+
+func diffLineFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line) DiffLine {
+ return DiffLine{
+ Origin: DiffLineType(line.origin),
+ OldLineno: int(line.old_lineno),
+ NewLineno: int(line.new_lineno),
+ NumLines: int(line.num_lines),
+ Content: C.GoStringN(line.content, C.int(line.content_len)),
+ }
+}
+
+type Diff struct {
+ ptr *C.git_diff
+}
+
+func (diff *Diff) NumDeltas() (int, error) {
+ if diff.ptr == nil {
+ return -1, ErrInvalid
+ }
+ return int(C.git_diff_num_deltas(diff.ptr)), nil
+}
+
+func (diff *Diff) GetDelta(index int) (DiffDelta, error) {
+ if diff.ptr == nil {
+ return DiffDelta{}, ErrInvalid
+ }
+ ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index))
+ return diffDeltaFromC(ptr), nil
+}
+
+func newDiffFromC(ptr *C.git_diff) *Diff {
+ if ptr == nil {
+ return nil
+ }
+
+ diff := &Diff{
+ ptr: ptr,
+ }
+
+ runtime.SetFinalizer(diff, (*Diff).Free)
+ return diff
+}
+
+func (diff *Diff) Free() error {
+ if diff.ptr == nil {
+ return ErrInvalid
+ }
+ runtime.SetFinalizer(diff, nil)
+ C.git_diff_free(diff.ptr)
+ diff.ptr = nil
+ return nil
+}
+
+type diffForEachData struct {
+ FileCallback DiffForEachFileCallback
+ HunkCallback DiffForEachHunkCallback
+ LineCallback DiffForEachLineCallback
+ Error error
+}
+
+type DiffForEachFileCallback func(DiffDelta, float64) (DiffForEachHunkCallback, error)
+
+type DiffDetail int
+
+const (
+ DiffDetailFiles DiffDetail = iota
+ DiffDetailHunks
+ DiffDetailLines
+)
+
+func (diff *Diff) ForEach(cbFile DiffForEachFileCallback, detail DiffDetail) error {
+ if diff.ptr == nil {
+ return ErrInvalid
+ }
+
+ intHunks := C.int(0)
+ if detail >= DiffDetailHunks {
+ intHunks = C.int(1)
+ }
+
+ intLines := C.int(0)
+ if detail >= DiffDetailLines {
+ intLines = C.int(1)
+ }
+
+ data := &diffForEachData{
+ FileCallback: cbFile,
+ }
+ ecode := C._go_git_diff_foreach(diff.ptr, 1, intHunks, intLines, unsafe.Pointer(data))
+ if ecode < 0 {
+ return data.Error
+ }
+ return nil
+}
+
+//export diffForEachFileCb
+func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, payload unsafe.Pointer) int {
+ data := (*diffForEachData)(payload)
+
+ data.HunkCallback = nil
+ if data.FileCallback != nil {
+ cb, err := data.FileCallback(diffDeltaFromC(delta), float64(progress))
+ if err != nil {
+ data.Error = err
+ return -1
+ }
+ data.HunkCallback = cb
+ }
+
+ return 0
+}
+
+type DiffForEachHunkCallback func(DiffHunk) (DiffForEachLineCallback, error)
+
+//export diffForEachHunkCb
+func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload unsafe.Pointer) int {
+ data := (*diffForEachData)(payload)
+
+ data.LineCallback = nil
+ if data.HunkCallback != nil {
+ cb, err := data.HunkCallback(diffHunkFromC(delta, hunk))
+ if err != nil {
+ data.Error = err
+ return -1
+ }
+ data.LineCallback = cb
+ }
+
+ return 0
+}
+
+type DiffForEachLineCallback func(DiffLine) error
+
+//export diffForEachLineCb
+func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, payload unsafe.Pointer) int {
+
+ data := (*diffForEachData)(payload)
+
+ err := data.LineCallback(diffLineFromC(delta, hunk, line))
+ if err != nil {
+ data.Error = err
+ return -1
+ }
+
+ return 0
+}
+
+func (diff *Diff) Patch(deltaIndex int) (*Patch, error) {
+ if diff.ptr == nil {
+ return nil, ErrInvalid
+ }
+ var patchPtr *C.git_patch
+
+ ecode := C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex))
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newPatchFromC(patchPtr), nil
+}
+
+type DiffOptionsFlag int
+
+const (
+ DiffNormal DiffOptionsFlag = C.GIT_DIFF_NORMAL
+ DiffReverse = C.GIT_DIFF_REVERSE
+ DiffIncludeIgnored = C.GIT_DIFF_INCLUDE_IGNORED
+ DiffRecurseIgnoredDirs = C.GIT_DIFF_RECURSE_IGNORED_DIRS
+ DiffIncludeUntracked = C.GIT_DIFF_INCLUDE_UNTRACKED
+ DiffRecurseUntracked = C.GIT_DIFF_RECURSE_UNTRACKED_DIRS
+ DiffIncludeUnmodified = C.GIT_DIFF_INCLUDE_UNMODIFIED
+ DiffIncludeTypeChange = C.GIT_DIFF_INCLUDE_TYPECHANGE
+ DiffIncludeTypeChangeTrees = C.GIT_DIFF_INCLUDE_TYPECHANGE_TREES
+ DiffIgnoreFilemode = C.GIT_DIFF_IGNORE_FILEMODE
+ DiffIgnoreSubmodules = C.GIT_DIFF_IGNORE_SUBMODULES
+ DiffIgnoreCase = C.GIT_DIFF_IGNORE_CASE
+
+ DiffDisablePathspecMatch = C.GIT_DIFF_DISABLE_PATHSPEC_MATCH
+ DiffSkipBinaryCheck = C.GIT_DIFF_SKIP_BINARY_CHECK
+ DiffEnableFastUntrackedDirs = C.GIT_DIFF_ENABLE_FAST_UNTRACKED_DIRS
+
+ DiffForceText = C.GIT_DIFF_FORCE_TEXT
+ DiffForceBinary = C.GIT_DIFF_FORCE_BINARY
+
+ DiffIgnoreWhitespace = C.GIT_DIFF_IGNORE_WHITESPACE
+ DiffIgnoreWhitespaceChange = C.GIT_DIFF_IGNORE_WHITESPACE_CHANGE
+ DiffIgnoreWitespaceEol = C.GIT_DIFF_IGNORE_WHITESPACE_EOL
+
+ DiffShowUntrackedContent = C.GIT_DIFF_SHOW_UNTRACKED_CONTENT
+ DiffShowUnmodified = C.GIT_DIFF_SHOW_UNMODIFIED
+ DiffPatience = C.GIT_DIFF_PATIENCE
+ DiffMinimal = C.GIT_DIFF_MINIMAL
+)
+
+type DiffNotifyCallback func(diffSoFar *Diff, deltaToAdd DiffDelta, matchedPathspec string) error
+
+type DiffOptions struct {
+ Flags DiffOptionsFlag
+ IgnoreSubmodules SubmoduleIgnore
+ Pathspec []string
+ NotifyCallback DiffNotifyCallback
+
+ ContextLines uint16
+ InterhunkLines uint16
+ IdAbbrev uint16
+
+ MaxSize int
+
+ OldPrefix string
+ NewPrefix string
+}
+
+func DefaultDiffOptions() (DiffOptions, error) {
+ opts := C.git_diff_options{}
+ ecode := C.git_diff_init_options(&opts, C.GIT_DIFF_OPTIONS_VERSION)
+ if ecode < 0 {
+ return DiffOptions{}, MakeGitError(ecode)
+ }
+
+ return DiffOptions{
+ Flags: DiffOptionsFlag(opts.flags),
+ IgnoreSubmodules: SubmoduleIgnore(opts.ignore_submodules),
+ Pathspec: makeStringsFromCStrings(opts.pathspec.strings, int(opts.pathspec.count)),
+ ContextLines: uint16(opts.context_lines),
+ InterhunkLines: uint16(opts.interhunk_lines),
+ IdAbbrev: uint16(opts.id_abbrev),
+ MaxSize: int(opts.max_size),
+ }, nil
+}
+
+var (
+ ErrDeltaSkip = errors.New("Skip delta")
+)
+
+type diffNotifyData struct {
+ Callback DiffNotifyCallback
+ Diff *Diff
+ Error error
+}
+
+//export diffNotifyCb
+func diffNotifyCb(_diff_so_far unsafe.Pointer, delta_to_add *C.git_diff_delta, matched_pathspec *C.char, payload unsafe.Pointer) int {
+ diff_so_far := (*C.git_diff)(_diff_so_far)
+ data := (*diffNotifyData)(payload)
+ if data != nil {
+ if data.Diff == nil {
+ data.Diff = newDiffFromC(diff_so_far)
+ }
+
+ err := data.Callback(data.Diff, diffDeltaFromC(delta_to_add), C.GoString(matched_pathspec))
+
+ if err == ErrDeltaSkip {
+ return 1
+ } else if err != nil {
+ data.Error = err
+ return -1
+ } else {
+ return 0
+ }
+ }
+ return 0
+}
+
+func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree, opts *DiffOptions) (*Diff, error) {
+ var diffPtr *C.git_diff
+ var oldPtr, newPtr *C.git_tree
+
+ if oldTree != nil {
+ oldPtr = oldTree.cast_ptr
+ }
+
+ if newTree != nil {
+ newPtr = newTree.cast_ptr
+ }
+
+ cpathspec := C.git_strarray{}
+ var copts *C.git_diff_options
+ var notifyData *diffNotifyData
+ if opts != nil {
+ notifyData = &diffNotifyData{
+ Callback: opts.NotifyCallback,
+ }
+ if opts.Pathspec != nil {
+ cpathspec.count = C.size_t(len(opts.Pathspec))
+ cpathspec.strings = makeCStringsFromStrings(opts.Pathspec)
+ defer freeStrarray(&cpathspec)
+ }
+
+ copts = &C.git_diff_options{
+ version: C.GIT_DIFF_OPTIONS_VERSION,
+ flags: C.uint32_t(opts.Flags),
+ ignore_submodules: C.git_submodule_ignore_t(opts.IgnoreSubmodules),
+ pathspec: cpathspec,
+ context_lines: C.uint16_t(opts.ContextLines),
+ interhunk_lines: C.uint16_t(opts.InterhunkLines),
+ id_abbrev: C.uint16_t(opts.IdAbbrev),
+ max_size: C.git_off_t(opts.MaxSize),
+ }
+
+ if opts.NotifyCallback != nil {
+ C._go_git_setup_diff_notify_callbacks(copts)
+ copts.notify_payload = unsafe.Pointer(notifyData)
+ }
+ }
+
+ ecode := C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, copts)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ if notifyData != nil && notifyData.Diff != nil {
+ return notifyData.Diff, nil
+ }
+ return newDiffFromC(diffPtr), nil
+}
diff --git a/diff_test.go b/diff_test.go
new file mode 100644
index 0000000..b688294
--- /dev/null
+++ b/diff_test.go
@@ -0,0 +1,96 @@
+package git
+
+import (
+ "errors"
+ "os"
+ "testing"
+)
+
+func TestDiffTreeToTree(t *testing.T) {
+ repo := createTestRepo(t)
+ defer repo.Free()
+ defer os.RemoveAll(repo.Workdir())
+
+ _, originalTreeId := seedTestRepo(t, repo)
+ originalTree, err := repo.LookupTree(originalTreeId)
+
+ checkFatal(t, err)
+
+ _, newTreeId := updateReadme(t, repo, "file changed\n")
+
+ newTree, err := repo.LookupTree(newTreeId)
+ checkFatal(t, err)
+
+ callbackInvoked := false
+ opts := DiffOptions{
+ NotifyCallback: func(diffSoFar *Diff, delta DiffDelta, matchedPathSpec string) error {
+ callbackInvoked = true
+ return nil
+ },
+ }
+
+ diff, err := repo.DiffTreeToTree(originalTree, newTree, &opts)
+ checkFatal(t, err)
+ if !callbackInvoked {
+ t.Fatal("callback not invoked")
+ }
+
+ if diff == nil {
+ t.Fatal("no diff returned")
+ }
+
+ files := make([]string, 0)
+ hunks := make([]DiffHunk, 0)
+ lines := make([]DiffLine, 0)
+ err = diff.ForEach(func(file DiffDelta, progress float64) (DiffForEachHunkCallback, error) {
+ files = append(files, file.OldFile.Path)
+ return func(hunk DiffHunk) (DiffForEachLineCallback, error) {
+ hunks = append(hunks, hunk)
+ return func(line DiffLine) error {
+ lines = append(lines, line)
+ return nil
+ }, nil
+ }, nil
+ }, DiffDetailLines)
+
+ checkFatal(t, err)
+
+ if len(files) != 1 {
+ t.Fatal("Incorrect number of files in diff")
+ }
+
+ if files[0] != "README" {
+ t.Fatal("File in diff was expected to be README")
+ }
+
+ if len(hunks) != 1 {
+ t.Fatal("Incorrect number of hunks in diff")
+ }
+
+ if hunks[0].OldStart != 1 || hunks[0].NewStart != 1 {
+ t.Fatal("Incorrect hunk")
+ }
+
+ if len(lines) != 2 {
+ t.Fatal("Incorrect number of lines in diff")
+ }
+
+ if lines[0].Content != "foo\n" {
+ t.Fatal("Incorrect lines in diff")
+ }
+
+ if lines[1].Content != "file changed\n" {
+ t.Fatal("Incorrect lines in diff")
+ }
+
+ errTest := errors.New("test error")
+
+ err = diff.ForEach(func(file DiffDelta, progress float64) (DiffForEachHunkCallback, error) {
+ return nil, errTest
+ }, DiffDetailLines)
+
+ if err != errTest {
+ t.Fatal("Expected custom error to be returned")
+ }
+
+}
diff --git a/git.go b/git.go
index 2afbfaa..48ffeee 100644
--- a/git.go
+++ b/git.go
@@ -89,6 +89,10 @@ const (
ErrIterOver = C.GIT_ITEROVER
)
+var (
+ ErrInvalid = errors.New("Invalid state for operation")
+)
+
func init() {
C.git_threads_init()
}
diff --git a/git_test.go b/git_test.go
index f4515a6..cbf3227 100644
--- a/git_test.go
+++ b/git_test.go
@@ -2,6 +2,7 @@ package git
import (
"io/ioutil"
+ "path"
"testing"
"time"
)
@@ -15,6 +16,7 @@ func createTestRepo(t *testing.T) *Repository {
tmpfile := "README"
err = ioutil.WriteFile(path+"/"+tmpfile, []byte("foo\n"), 0644)
+
checkFatal(t, err)
return repo
@@ -55,6 +57,35 @@ func seedTestRepo(t *testing.T, repo *Repository) (*Oid, *Oid) {
return commitId, treeId
}
+func updateReadme(t *testing.T, repo *Repository, content string) (*Oid, *Oid) {
+ loc, err := time.LoadLocation("Europe/Berlin")
+ checkFatal(t, err)
+ sig := &Signature{
+ Name: "Rand Om Hacker",
+ Email: "[email protected]",
+ When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
+ }
+
+ tmpfile := "README"
+ err = ioutil.WriteFile(path.Join(path.Dir(path.Dir(repo.Path())), tmpfile), []byte(content), 0644)
+ checkFatal(t, err)
+
+ idx, err := repo.Index()
+ checkFatal(t, err)
+ err = idx.AddByPath("README")
+ checkFatal(t, err)
+ treeId, err := idx.WriteTree()
+ checkFatal(t, err)
+
+ message := "This is a commit\n"
+ tree, err := repo.LookupTree(treeId)
+ checkFatal(t, err)
+ commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree)
+ checkFatal(t, err)
+
+ return commitId, treeId
+}
+
func TestOidZero(t *testing.T) {
var zeroId Oid
diff --git a/patch.go b/patch.go
new file mode 100644
index 0000000..0665501
--- /dev/null
+++ b/patch.go
@@ -0,0 +1,48 @@
+package git
+
+/*
+#include <git2.h>
+*/
+import "C"
+import (
+ "runtime"
+)
+
+type Patch struct {
+ ptr *C.git_patch
+}
+
+func newPatchFromC(ptr *C.git_patch) *Patch {
+ if ptr == nil {
+ return nil
+ }
+
+ patch := &Patch{
+ ptr: ptr,
+ }
+
+ runtime.SetFinalizer(patch, (*Patch).Free)
+ return patch
+}
+
+func (patch *Patch) Free() error {
+ if patch.ptr == nil {
+ return ErrInvalid
+ }
+ runtime.SetFinalizer(patch, nil)
+ C.git_patch_free(patch.ptr)
+ patch.ptr = nil
+ return nil
+}
+
+func (patch *Patch) String() (string, error) {
+ if patch.ptr == nil {
+ return "", ErrInvalid
+ }
+ var buf C.git_buf
+ ecode := C.git_patch_to_buf(&buf, patch.ptr)
+ if ecode < 0 {
+ return "", MakeGitError(ecode)
+ }
+ return C.GoString(buf.ptr), nil
+}
diff --git a/patch_test.go b/patch_test.go
new file mode 100644
index 0000000..569eac2
--- /dev/null
+++ b/patch_test.go
@@ -0,0 +1,34 @@
+package git
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestPatch(t *testing.T) {
+ repo := createTestRepo(t)
+ defer repo.Free()
+ //defer os.RemoveAll(repo.Workdir())
+
+ _, originalTreeId := seedTestRepo(t, repo)
+ originalTree, err := repo.LookupTree(originalTreeId)
+
+ checkFatal(t, err)
+
+ _, newTreeId := updateReadme(t, repo, "file changed\n")
+
+ newTree, err := repo.LookupTree(newTreeId)
+ checkFatal(t, err)
+
+ diff, err := repo.DiffTreeToTree(originalTree, newTree, nil)
+ checkFatal(t, err)
+
+ patch, err := diff.Patch(0)
+ checkFatal(t, err)
+
+ patchStr, err := patch.String()
+ checkFatal(t, err)
+ if strings.Index(patchStr, "diff --git a/README b/README\nindex 257cc56..820734a 100644\n--- a/README\n+++ b/README\n@@ -1 +1 @@\n-foo\n+file changed") == -1 {
+ t.Fatalf("patch was bad")
+ }
+}
diff --git a/repository.go b/repository.go
index 15a3544..bd6f773 100644
--- a/repository.go
+++ b/repository.go
@@ -162,6 +162,20 @@ func (v *Repository) LookupReference(name string) (*Reference, error) {
return newReferenceFromC(ptr), nil
}
+func (v *Repository) Head() (*Reference, error) {
+ var ptr *C.git_reference
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_repository_head(&ptr, v.ptr)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newReferenceFromC(ptr), nil
+}
+
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))
diff --git a/wrapper.c b/wrapper.c
index b0ca5e5..2fd8fb7 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -43,6 +43,31 @@ void _go_git_refdb_backend_free(git_refdb_backend *backend)
return;
}
+int _go_git_diff_foreach(git_diff *diff, 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_foreach(diff, fcb, hcb, lcb, payload);
+}
+
+void _go_git_setup_diff_notify_callbacks(git_diff_options *opts) {
+ opts->notify_cb = (git_diff_notify_cb)diffNotifyCb;
+}
+
void _go_git_setup_callbacks(git_remote_callbacks *callbacks) {
typedef int (*completion_cb)(git_remote_completion_type type, void *data);
typedef int (*credentials_cb)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data);