summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--diff.go229
-rw-r--r--patch.go37
-rw-r--r--repository.go31
-rw-r--r--wrapper.c21
4 files changed, 318 insertions, 0 deletions
diff --git a/diff.go b/diff.go
new file mode 100644
index 0000000..d9570c9
--- /dev/null
+++ b/diff.go
@@ -0,0 +1,229 @@
+package git
+
+/*
+#include <git2.h>
+
+extern int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLine, void *payload);
+*/
+import "C"
+import (
+ "runtime"
+ "unsafe"
+)
+
+type DiffFile struct {
+ file C.git_diff_file
+}
+
+func (df *DiffFile) Oid() *Oid {
+ return newOidFromC(&df.file.oid)
+}
+
+func (df *DiffFile) Path() string {
+ return C.GoString(df.file.path)
+}
+
+func (df *DiffFile) Size() int {
+ return int(df.file.size)
+}
+
+func (df *DiffFile) Flags() uint32 {
+ return uint32(df.file.flags)
+}
+
+func (df *DiffFile) Mode() uint16 {
+ return uint16(df.file.mode)
+}
+
+type DiffDelta struct {
+ delta C.git_diff_delta
+}
+
+func (dd *DiffDelta) Status() int {
+ return int(dd.delta.status)
+}
+
+func (dd *DiffDelta) Flags() uint32 {
+ return uint32(dd.delta.flags)
+}
+
+func (dd *DiffDelta) Similarity() uint16 {
+ return uint16(dd.delta.similarity)
+}
+
+func (dd *DiffDelta) OldFile() *DiffFile {
+ return &DiffFile{dd.delta.old_file}
+}
+
+func (dd *DiffDelta) NewFile() *DiffFile {
+ return &DiffFile{dd.delta.new_file}
+}
+
+type DiffHunk struct {
+ hunk C.git_diff_hunk
+ DiffDelta
+}
+
+func (dh *DiffHunk) OldStart() int {
+ return int(dh.hunk.old_start)
+}
+
+func (dh *DiffHunk) OldLines() int {
+ return int(dh.hunk.old_lines)
+}
+
+func (dh *DiffHunk) NewStart() int {
+ return int(dh.hunk.new_start)
+}
+
+func (dh *DiffHunk) NewLines() int {
+ return int(dh.hunk.new_lines)
+}
+
+func (dh *DiffHunk) Header() string {
+ return C.GoStringN(&dh.hunk.header[0], C.int(dh.hunk.header_len))
+}
+
+type DiffLine struct {
+ line C.git_diff_line
+ DiffHunk
+}
+
+func (dl *DiffLine) Origin() byte {
+ return byte(dl.line.origin)
+}
+
+func (dl *DiffLine) OldLineno() int {
+ return int(dl.line.old_lineno)
+}
+
+func (dl *DiffLine) NewLineno() int {
+ return int(dl.line.new_lineno)
+}
+
+func (dl *DiffLine) NumLines() int {
+ return int(dl.line.num_lines)
+}
+
+func (dl *DiffLine) Content() string {
+ return C.GoStringN(dl.line.content, C.int(dl.line.content_len))
+}
+
+func (dl *DiffLine) ContentOffset() int {
+ return int(dl.line.content_offset)
+}
+
+type Diff struct {
+ ptr *C.git_diff
+}
+
+func newDiff(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() {
+ runtime.SetFinalizer(diff, nil)
+ C.git_diff_free(diff.ptr)
+}
+
+func (diff *Diff) forEachFileWrap(ch chan *DiffDelta) {
+ C._go_git_diff_foreach(diff.ptr, 1, 0, 0, unsafe.Pointer(&ch))
+ close(ch)
+}
+
+func (diff *Diff) ForEachFile() chan *DiffDelta {
+ ch := make(chan *DiffDelta, 0)
+ go diff.forEachFileWrap(ch)
+ return ch
+}
+
+//export diffForEachFileCb
+func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, payload unsafe.Pointer) int {
+ ch := *(*chan *DiffDelta)(payload)
+
+ select {
+ case ch <-&DiffDelta{*delta}:
+ case <-ch:
+ return -1
+ }
+
+ return 0
+}
+
+func (diff *Diff) forEachHunkWrap(ch chan *DiffHunk) {
+ C._go_git_diff_foreach(diff.ptr, 0, 1, 0, unsafe.Pointer(&ch))
+ close(ch)
+}
+
+func (diff *Diff) ForEachHunk() chan *DiffHunk {
+ ch := make(chan *DiffHunk, 0)
+ go diff.forEachHunkWrap(ch)
+ return ch
+}
+
+//export diffForEachHunkCb
+func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload unsafe.Pointer) int {
+ ch := *(*chan *DiffHunk)(payload)
+
+ select {
+ case ch <-&DiffHunk{*hunk, DiffDelta{*delta}}:
+ case <-ch:
+ return -1
+ }
+
+ return 0
+}
+
+func (diff *Diff) forEachLineWrap(ch chan *DiffLine) {
+ C._go_git_diff_foreach(diff.ptr, 0, 0, 1, unsafe.Pointer(&ch))
+ close(ch)
+}
+
+func (diff *Diff) ForEachLine() chan *DiffLine {
+ ch := make(chan *DiffLine, 0)
+ go diff.forEachLineWrap(ch)
+ return ch
+}
+
+//export diffForEachLineCb
+func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, payload unsafe.Pointer) int {
+ ch := *(*chan *DiffLine)(payload)
+
+ select {
+ case ch <-&DiffLine{*line, DiffHunk{*hunk, DiffDelta{*delta}}}:
+ case <-ch:
+ return -1
+ }
+
+ return 0
+}
+
+func (diff *Diff) NumDeltas() int {
+ return int(C.git_diff_num_deltas(diff.ptr))
+}
+
+func (diff *Diff) GetDelta(index int) *DiffDelta {
+ ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index))
+ if ptr == nil {
+ return nil
+ }
+
+ return &DiffDelta{*ptr}
+}
+
+func (diff *Diff) Patch(deltaIndex int) *Patch {
+ var patchPtr *C.git_patch
+
+ C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex))
+
+ return newPatch(patchPtr)
+}
diff --git a/patch.go b/patch.go
new file mode 100644
index 0000000..561786e
--- /dev/null
+++ b/patch.go
@@ -0,0 +1,37 @@
+package git
+
+/*
+#include <git2.h>
+*/
+import "C"
+import (
+ "runtime"
+)
+
+type Patch struct {
+ ptr *C.git_patch
+}
+
+func newPatch(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() {
+ runtime.SetFinalizer(patch, nil)
+ C.git_patch_free(patch.ptr)
+}
+
+func (patch *Patch) String() string {
+ var cptr *C.char
+ C.git_patch_to_str(&cptr, patch.ptr)
+ return C.GoString(cptr)
+}
diff --git a/repository.go b/repository.go
index 3a9068d..58d3487 100644
--- a/repository.go
+++ b/repository.go
@@ -146,6 +146,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, LastError()
+ }
+
+ return newReferenceFromC(ptr), nil
+}
+
func (v *Repository) CreateReference(name string, oid *Oid, force bool) (*Reference, error) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
@@ -241,6 +255,23 @@ func (v *Repository) CreateCommit(
return oid, nil
}
+func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree) *Diff {
+ var diffPtr *C.git_diff
+ var oldPtr, newPtr *C.git_tree
+
+ if oldTree != nil {
+ oldPtr = oldTree.gitObject.ptr
+ }
+
+ if newTree != nil {
+ newPtr = newTree.gitObject.ptr
+ }
+
+ C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, nil)
+
+ return newDiff(diffPtr)
+}
+
func (v *Odb) Free() {
runtime.SetFinalizer(v, nil)
C.git_odb_free(v.ptr)
diff --git a/wrapper.c b/wrapper.c
index 2af3974..93331ad 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -24,4 +24,25 @@ int _go_git_odb_foreach(git_odb *db, void *payload)
{
return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload);
}
+
+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);
+}
/* EOF */