Skip to content

Commit

Permalink
Add DiffBlobs
Browse files Browse the repository at this point in the history
This lets you diff two arbitrary blobs with arbitrary names.
  • Loading branch information
carlosmn committed Jun 29, 2015
1 parent 86e9917 commit e066d24
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
48 changes: 48 additions & 0 deletions diff.go
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
}
47 changes: 47 additions & 0 deletions diff_test.go
Expand Up @@ -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")
}
}
21 changes: 21 additions & 0 deletions wrapper.c
Expand Up @@ -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;
}
Expand Down

0 comments on commit e066d24

Please sign in to comment.