Skip to content

Commit d0b334b

Browse files
author
Jesse Ezell
committed
cleanup and refactor diff / patch
1 parent 9acd67e commit d0b334b

File tree

6 files changed

+252
-124
lines changed

6 files changed

+252
-124
lines changed

diff.go

Lines changed: 163 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -12,72 +12,75 @@ import (
1212
)
1313

1414
type DiffFlag int
15+
1516
const (
16-
DiffFlagBinary = DiffFlag(C.GIT_DIFF_FLAG_BINARY)
17-
DiffFlagNotBinary = C.GIT_DIFF_FLAG_NOT_BINARY
18-
DiffFlagValidOid = C.GIT_DIFF_FLAG_VALID_OID
17+
DiffFlagBinary DiffFlag = C.GIT_DIFF_FLAG_BINARY
18+
DiffFlagNotBinary = C.GIT_DIFF_FLAG_NOT_BINARY
19+
DiffFlagValidOid = C.GIT_DIFF_FLAG_VALID_OID
1920
)
2021

2122
type Delta int
23+
2224
const (
23-
DeltaUnmodified = Delta(C.GIT_DELTA_UNMODIFIED)
24-
DeltaAdded = C.GIT_DELTA_ADDED
25-
DeltaDeleted = C.GIT_DELTA_DELETED
26-
DeltaModified = C.GIT_DELTA_MODIFIED
27-
DeltaRenamed = C.GIT_DELTA_RENAMED
28-
DeltaCopied = C.GIT_DELTA_COPIED
29-
DeltaIgnored = C.GIT_DELTA_IGNORED
30-
DeltaUntracked = C.GIT_DELTA_UNTRACKED
31-
DeltaTypeChange = C.GIT_DELTA_TYPECHANGE
25+
DeltaUnmodified Delta = C.GIT_DELTA_UNMODIFIED
26+
DeltaAdded = C.GIT_DELTA_ADDED
27+
DeltaDeleted = C.GIT_DELTA_DELETED
28+
DeltaModified = C.GIT_DELTA_MODIFIED
29+
DeltaRenamed = C.GIT_DELTA_RENAMED
30+
DeltaCopied = C.GIT_DELTA_COPIED
31+
DeltaIgnored = C.GIT_DELTA_IGNORED
32+
DeltaUntracked = C.GIT_DELTA_UNTRACKED
33+
DeltaTypeChange = C.GIT_DELTA_TYPECHANGE
3234
)
3335

3436
type DiffLineType int
37+
3538
const (
36-
DiffLineContext = DiffLineType(C.GIT_DIFF_LINE_CONTEXT)
37-
DiffLineAddition = C.GIT_DIFF_LINE_ADDITION
38-
DiffLineDeletion = C.GIT_DIFF_LINE_DELETION
39-
DiffLineContextEOFNL = C.GIT_DIFF_LINE_CONTEXT_EOFNL
40-
DiffLineAddEOFNL = C.GIT_DIFF_LINE_ADD_EOFNL
41-
DiffLineDelEOFNL = C.GIT_DIFF_LINE_DEL_EOFNL
39+
DiffLineContext DiffLineType = C.GIT_DIFF_LINE_CONTEXT
40+
DiffLineAddition = C.GIT_DIFF_LINE_ADDITION
41+
DiffLineDeletion = C.GIT_DIFF_LINE_DELETION
42+
DiffLineContextEOFNL = C.GIT_DIFF_LINE_CONTEXT_EOFNL
43+
DiffLineAddEOFNL = C.GIT_DIFF_LINE_ADD_EOFNL
44+
DiffLineDelEOFNL = C.GIT_DIFF_LINE_DEL_EOFNL
4245

4346
DiffLineFileHdr = C.GIT_DIFF_LINE_FILE_HDR
4447
DiffLineHunkHdr = C.GIT_DIFF_LINE_HUNK_HDR
45-
DiffLineBinary = C.GIT_DIFF_LINE_BINARY
48+
DiffLineBinary = C.GIT_DIFF_LINE_BINARY
4649
)
4750

4851
type DiffFile struct {
49-
Path string
50-
Oid *Oid
51-
Size int
52+
Path string
53+
Oid *Oid
54+
Size int
5255
Flags DiffFlag
53-
Mode uint16
56+
Mode uint16
5457
}
5558

56-
func newDiffFile(file *C.git_diff_file) *DiffFile {
59+
func newDiffFileFromC(file *C.git_diff_file) *DiffFile {
5760
return &DiffFile{
58-
Path: C.GoString(file.path),
59-
Oid: newOidFromC(&file.oid),
60-
Size: int(file.size),
61+
Path: C.GoString(file.path),
62+
Oid: newOidFromC(&file.oid),
63+
Size: int(file.size),
6164
Flags: DiffFlag(file.flags),
62-
Mode: uint16(file.mode),
65+
Mode: uint16(file.mode),
6366
}
6467
}
6568

6669
type DiffDelta struct {
67-
Status Delta
68-
Flags DiffFlag
70+
Status Delta
71+
Flags DiffFlag
6972
Similarity uint16
70-
OldFile *DiffFile
71-
NewFile *DiffFile
73+
OldFile *DiffFile
74+
NewFile *DiffFile
7275
}
7376

74-
func newDiffDelta(delta *C.git_diff_delta) *DiffDelta {
77+
func newDiffDeltaFromC(delta *C.git_diff_delta) *DiffDelta {
7578
return &DiffDelta{
76-
Status: Delta(delta.status),
77-
Flags: DiffFlag(delta.flags),
79+
Status: Delta(delta.status),
80+
Flags: DiffFlag(delta.flags),
7881
Similarity: uint16(delta.similarity),
79-
OldFile: newDiffFile(&delta.old_file),
80-
NewFile: newDiffFile(&delta.new_file),
82+
OldFile: newDiffFileFromC(&delta.old_file),
83+
NewFile: newDiffFileFromC(&delta.new_file),
8184
}
8285
}
8386

@@ -86,46 +89,46 @@ type DiffHunk struct {
8689
OldLines int
8790
NewStart int
8891
NewLines int
89-
Header string
92+
Header string
9093
DiffDelta
9194
}
9295

93-
func newDiffHunk(delta *C.git_diff_delta, hunk *C.git_diff_hunk) *DiffHunk {
96+
func newDiffHunkFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk) *DiffHunk {
9497
return &DiffHunk{
95-
OldStart: int(hunk.old_start),
96-
OldLines: int(hunk.old_lines),
97-
NewStart: int(hunk.new_start),
98-
NewLines: int(hunk.new_lines),
99-
Header: C.GoStringN(&hunk.header[0], C.int(hunk.header_len)),
100-
DiffDelta: *newDiffDelta(delta),
98+
OldStart: int(hunk.old_start),
99+
OldLines: int(hunk.old_lines),
100+
NewStart: int(hunk.new_start),
101+
NewLines: int(hunk.new_lines),
102+
Header: C.GoStringN(&hunk.header[0], C.int(hunk.header_len)),
103+
DiffDelta: *newDiffDeltaFromC(delta),
101104
}
102105
}
103106

104107
type DiffLine struct {
105-
Origin DiffLineType
108+
Origin DiffLineType
106109
OldLineno int
107110
NewLineno int
108-
NumLines int
109-
Content string
111+
NumLines int
112+
Content string
110113
DiffHunk
111114
}
112115

113-
func newDiffLine(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line) *DiffLine {
116+
func newDiffLineFromC(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line) *DiffLine {
114117
return &DiffLine{
115-
Origin: DiffLineType(line.origin),
118+
Origin: DiffLineType(line.origin),
116119
OldLineno: int(line.old_lineno),
117120
NewLineno: int(line.new_lineno),
118-
NumLines: int(line.num_lines),
119-
Content: C.GoStringN(line.content, C.int(line.content_len)),
120-
DiffHunk: *newDiffHunk(delta, hunk),
121+
NumLines: int(line.num_lines),
122+
Content: C.GoStringN(line.content, C.int(line.content_len)),
123+
DiffHunk: *newDiffHunkFromC(delta, hunk),
121124
}
122125
}
123126

124127
type Diff struct {
125128
ptr *C.git_diff
126129
}
127130

128-
func newDiff(ptr *C.git_diff) *Diff {
131+
func newDiffFromC(ptr *C.git_diff) *Diff {
129132
if ptr == nil {
130133
return nil
131134
}
@@ -138,100 +141,165 @@ func newDiff(ptr *C.git_diff) *Diff {
138141
return diff
139142
}
140143

141-
func (diff *Diff) Free() {
144+
func (diff *Diff) Free() error {
145+
if diff.ptr != nil {
146+
return ErrInvalid
147+
}
142148
runtime.SetFinalizer(diff, nil)
143149
C.git_diff_free(diff.ptr)
150+
return nil
144151
}
145152

146-
func (diff *Diff) forEachFileWrap(ch chan *DiffDelta) {
147-
C._go_git_diff_foreach(diff.ptr, 1, 0, 0, unsafe.Pointer(&ch))
148-
close(ch)
153+
type diffForEachFileData struct {
154+
Callback DiffForEachFileCallback
155+
Error error
149156
}
150157

151-
func (diff *Diff) ForEachFile() chan *DiffDelta {
152-
ch := make(chan *DiffDelta, 0)
153-
go diff.forEachFileWrap(ch)
154-
return ch
158+
func (diff *Diff) ForEachFile(cb DiffForEachFileCallback) error {
159+
if diff.ptr != nil {
160+
return ErrInvalid
161+
}
162+
163+
data := &diffForEachFileData{
164+
Callback: cb,
165+
}
166+
ecode := C._go_git_diff_foreach(diff.ptr, 1, 0, 0, unsafe.Pointer(&data))
167+
if ecode < 0 {
168+
return data.Error
169+
}
170+
return nil
155171
}
156172

157173
//export diffForEachFileCb
158174
func diffForEachFileCb(delta *C.git_diff_delta, progress C.float, payload unsafe.Pointer) int {
159-
ch := *(*chan *DiffDelta)(payload)
175+
data := *diffForEachFileData(payload)
160176

161-
select {
162-
case ch <-newDiffDelta(delta):
163-
case <-ch:
177+
err := data.Callback(newDiffDeltaFromC(delta))
178+
if err != nil {
179+
data.Error = err
164180
return -1
165181
}
166182

167183
return 0
168184
}
169185

170-
func (diff *Diff) forEachHunkWrap(ch chan *DiffHunk) {
171-
C._go_git_diff_foreach(diff.ptr, 0, 1, 0, unsafe.Pointer(&ch))
172-
close(ch)
186+
type diffForEachHunkData struct {
187+
Callback DiffForEachHunkCallback
188+
Error error
173189
}
174190

175-
func (diff *Diff) ForEachHunk() chan *DiffHunk {
176-
ch := make(chan *DiffHunk, 0)
177-
go diff.forEachHunkWrap(ch)
178-
return ch
191+
type DiffForEachHunkCallback func(*DiffHunk) error
192+
193+
func (diff *Diff) ForEachHunk(cb DiffForEachHunkCallback) error {
194+
if diff.ptr != nil {
195+
return ErrInvalid
196+
}
197+
data := &diffForEachHunkData{
198+
Callback: cb,
199+
}
200+
ecode := C._go_git_diff_foreach(diff.ptr, 0, 1, 0, unsafe.Pointer(data))
201+
if ecode < 0 {
202+
return data.Error
203+
}
204+
return nil
179205
}
180206

181207
//export diffForEachHunkCb
182208
func diffForEachHunkCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, payload unsafe.Pointer) int {
183-
ch := *(*chan *DiffHunk)(payload)
209+
data := *diffForEachHunkData(payload)
184210

185-
select {
186-
case ch <-newDiffHunk(delta, hunk):
187-
case <-ch:
211+
err := data.Callback(newDiffHunkFromC(delta, hunk))
212+
if err < 0 {
213+
data.Error = err
188214
return -1
189215
}
190216

191217
return 0
192218
}
193219

194-
func (diff *Diff) forEachLineWrap(ch chan *DiffLine) {
195-
C._go_git_diff_foreach(diff.ptr, 0, 0, 1, unsafe.Pointer(&ch))
196-
close(ch)
220+
type diffForEachLineData struct {
221+
Callback DiffForEachLineCallback
222+
Error error
197223
}
198224

199-
func (diff *Diff) ForEachLine() chan *DiffLine {
200-
ch := make(chan *DiffLine, 0)
201-
go diff.forEachLineWrap(ch)
202-
return ch
225+
type DiffForEachLineCallback func(*DiffLine) error
226+
227+
func (diff *Diff) ForEachLine(cb DiffForEachLineCallback) error {
228+
if diff.ptr != nil {
229+
return ErrInvalid
230+
}
231+
232+
data := &diffForEachLineData{
233+
Callback: cb,
234+
}
235+
236+
ecode := C._go_git_diff_foreach(diff.ptr, 0, 0, 1, unsafe.Pointer(data))
237+
if ecode < 0 {
238+
return data.Error
239+
}
240+
return nil
203241
}
204242

205243
//export diffForEachLineCb
206244
func diffForEachLineCb(delta *C.git_diff_delta, hunk *C.git_diff_hunk, line *C.git_diff_line, payload unsafe.Pointer) int {
207-
ch := *(*chan *DiffLine)(payload)
208245

209-
select {
210-
case ch <-newDiffLine(delta, hunk, line):
211-
case <-ch:
246+
data := *diffForEachLineData(payload)
247+
248+
err := data.Callback(newDiffLineFromC(delta, hunk, line))
249+
if err != nil {
250+
data.Error = err
212251
return -1
213252
}
214253

215254
return 0
216255
}
217256

218-
func (diff *Diff) NumDeltas() int {
219-
return int(C.git_diff_num_deltas(diff.ptr))
257+
func (diff *Diff) NumDeltas() (int, error) {
258+
if diff.ptr != nil {
259+
return -1, ErrInvalid
260+
}
261+
return int(C.git_diff_num_deltas(diff.ptr)), nil
220262
}
221263

222-
func (diff *Diff) GetDelta(index int) *DiffDelta {
264+
func (diff *Diff) GetDelta(index int) (*DiffDelta, error) {
265+
if diff.ptr != nil {
266+
return nil, ErrInvalid
267+
}
223268
ptr := C.git_diff_get_delta(diff.ptr, C.size_t(index))
224269
if ptr == nil {
225270
return nil
226271
}
227272

228-
return newDiffDelta(ptr)
273+
return newDiffDeltaFromC(ptr), nil
229274
}
230275

231-
func (diff *Diff) Patch(deltaIndex int) *Patch {
276+
func (diff *Diff) Patch(deltaIndex int) (*Patch, error) {
277+
if diff.ptr != nil {
278+
return nil, ErrInvalid
279+
}
232280
var patchPtr *C.git_patch
233281

234-
C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex))
282+
ecode := C.git_patch_from_diff(&patchPtr, diff.ptr, C.size_t(deltaIndex))
283+
if ecode < 0 {
284+
return nil, MakeGitError(ecode)
285+
}
286+
287+
return newPatchFromC(patchPtr), nil
288+
}
289+
290+
func (v *Repository) DiffTreeToTree(oldTree, newTree *Tree) *Diff {
291+
var diffPtr *C.git_diff
292+
var oldPtr, newPtr *C.git_tree
293+
294+
if oldTree != nil {
295+
oldPtr = oldTree.gitObject.ptr
296+
}
297+
298+
if newTree != nil {
299+
newPtr = newTree.gitObject.ptr
300+
}
301+
302+
C.git_diff_tree_to_tree(&diffPtr, v.ptr, oldPtr, newPtr, nil)
235303

236-
return newPatch(patchPtr)
304+
return newDiff(diffPtr)
237305
}

0 commit comments

Comments
 (0)