package git /* #include extern int _go_git_diff_foreach(git_diff *diff, int eachFile, int eachHunk, int eachLine, void *payload); */ import "C" import ( "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 newDiffFileFromC(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 newDiffDeltaFromC(delta *C.git_diff_delta) *DiffDelta { return &DiffDelta{ Status: Delta(delta.status), Flags: DiffFlag(delta.flags), Similarity: uint16(delta.similarity), OldFile: newDiffFileFromC(&delta.old_file), NewFile: newDiffFileFromC(&delta.new_file), } } type DiffHunk struct { OldStart int OldLines int NewStart int NewLines int Header string DiffDelta } func newDiffHunkFromC(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)), DiffDelta: *newDiffDeltaFromC(delta), } } type DiffLine struct { Origin DiffLineType OldLineno int NewLineno int NumLines int Content string DiffHunk } func newDiffLineFromC(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)), DiffHunk: *newDiffHunkFromC(delta, hunk), } } type Diff struct { ptr *C.git_diff } 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) return nil } type DiffForEachFileCallback func(*DiffDelta) error type diffForEachFileData struct { Callback DiffForEachFileCallback Error error } func (diff *Diff) ForEachFile(cb DiffForEachFileCallback) error { if diff.ptr == nil { return ErrInvalid } data := &diffForEachFileData{ Callback: cb, } ecode := C._go_git_diff_foreach(diff.ptr, 1, 0, 0, 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 := (*diffForEachFileData)(payload) err := data.Callback(newDiffDeltaFromC(delta)) if err != nil { data.Error = err return -1 } return 0 } type diffForEachHunkData struct { Callback DiffForEachHunkCallback Error error } type DiffForEachHunkCallback func(*DiffHunk) error func (diff *Diff) ForEachHunk(cb DiffForEachHunkCallback) error { if diff.ptr == nil { return ErrInvalid } data := &diffForEachHunkData{ Callback: cb, } ecode := C._go_git_diff_foreach(diff.ptr, 0, 1, 0, unsafe.Pointer(data)) if ecode < 0 { return data.Error } return nil } //export diffForEachHunkCb func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload unsafe.Pointer) int { data := (*diffForEachHunkData)(payload) err := data.Callback(newDiffHunkFromC(delta, hunk)) if err != nil { data.Error = err return -1 } return 0 } type diffForEachLineData struct { Callback DiffForEachLineCallback Error error } type DiffForEachLineCallback func(*DiffLine) error func (diff *Diff) ForEachLine(cb DiffForEachLineCallback) error { if diff.ptr == nil { return ErrInvalid } data := &diffForEachLineData{ Callback: cb, } ecode := C._go_git_diff_foreach(diff.ptr, 0, 0, 1, unsafe.Pointer(data)) if ecode < 0 { return data.Error } return nil } //export diffForEachLineCb func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, payload unsafe.Pointer) int { data := (*diffForEachLineData)(payload) err := data.Callback(newDiffLineFromC(delta, hunk, line)) if err != nil { data.Error = err return -1 } return 0 } 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 nil, ErrInvalid } ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index)) if ptr == nil { return nil, nil } return newDiffDeltaFromC(ptr), nil } 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 } func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree) (*Diff, error) { 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 } ecode := C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, nil) if ecode < 0 { return nil, MakeGitError(ecode) } return newDiffFromC(diffPtr), nil }