This commit is contained in:
lye 2014-02-20 00:29:46 -06:00
commit b4f88b75d7
4 changed files with 318 additions and 0 deletions

229
diff.go Normal file
View File

@ -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)
}

37
patch.go Normal file
View File

@ -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)
}

View File

@ -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)

View File

@ -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 */