diff --git a/diff.go b/diff.go index 308859a..62c1aa7 100644 --- a/diff.go +++ b/diff.go @@ -7,6 +7,8 @@ extern void _go_git_populate_apply_callbacks(git_apply_options *options); 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); +extern int _go_git_diff_buffers(const void *old_buffer, size_t old_len, const char *old_as_path, const void *new_buffer, size_t new_len, const char *new_as_path, const git_diff_options *opts, int eachFile, int eachHunk, int eachLine, void *payload); + */ import "C" import ( @@ -888,6 +890,58 @@ func DiffBlobs(oldBlob *Blob, oldAsPath string, newBlob *Blob, newAsPath string, return nil } +// DiffBuffers performs a diff between two arbitrary buffers. You can pass +// whatever file names you'd like for them to appear as in the diff. +func DiffBuffers(oldBuffer []byte, oldAsPath string, newBufer []byte, newAsPath string, opts *DiffOptions, fileCallback DiffForEachFileCallback, detail DiffDetail) error { + var err error + data := &diffForEachCallbackData{ + fileCallback: fileCallback, + errorTarget: &err, + } + + 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) + + cOldBuffer := C.CBytes(oldBuffer) + defer C.free(unsafe.Pointer(cOldBuffer)) + cNewBuffer := C.CBytes(newBufer) + defer C.free(unsafe.Pointer(cNewBuffer)) + + cOldLen := C.size_t(len(oldBuffer)) + cNewLen := C.size_t(len(newBufer)) + + oldPath := C.CString(oldAsPath) + defer C.free(unsafe.Pointer(oldPath)) + newPath := C.CString(newAsPath) + defer C.free(unsafe.Pointer(newPath)) + + copts := populateDiffOptions(&C.git_diff_options{}, opts, nil, &err) + defer freeDiffOptions(copts) + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C._go_git_diff_buffers(cOldBuffer, cOldLen, oldPath, cNewBuffer, cNewLen, newPath, copts, 1, intHunks, intLines, handle) + if ret == C.int(ErrorCodeUser) && err != nil { + return err + } + if ret < 0 { + return MakeGitError(ret) + } + + return nil +} + // ApplyHunkCallback is a callback that will be made per delta (file) when applying a patch. type ApplyHunkCallback func(*DiffHunk) (apply bool, err error) diff --git a/wrapper.c b/wrapper.c index e999136..e94a68a 100644 --- a/wrapper.c +++ b/wrapper.c @@ -234,6 +234,34 @@ int _go_git_diff_blobs( return git_diff_blobs(old, old_path, new, new_path, opts, fcb, NULL, hcb, lcb, payload); } +int _go_git_diff_buffers( + const void *old_buffer, + size_t old_len, + const char *old_as_path, + const void *new_buffer, + size_t new_len, + const char *new_as_path, + const 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)&diffForEachFileCallback; + if (eachHunk) + hcb = (git_diff_hunk_cb)&diffForEachHunkCallback; + if (eachLine) + lcb = (git_diff_line_cb)&diffForEachLineCallback; + + return git_diff_buffers(old_buffer, old_len, old_as_path, new_buffer, new_len, new_as_path, opts, fcb, NULL, hcb, lcb, payload); +} + + void _go_git_setup_diff_notify_callbacks(git_diff_options *opts) { opts->notify_cb = (git_diff_notify_cb)&diffNotifyCallback;