@@ -12,15 +12,14 @@ import (
12
12
"os"
13
13
"os/exec"
14
14
"strings"
15
- "time"
16
15
16
+ "github.com/Unknwon/com"
17
17
"golang.org/x/net/html/charset"
18
18
"golang.org/x/text/transform"
19
19
20
- "github.com/Unknwon/com "
20
+ "github.com/gogits/git-shell "
21
21
22
22
"github.com/gogits/gogs/modules/base"
23
- "github.com/gogits/gogs/modules/git"
24
23
"github.com/gogits/gogs/modules/log"
25
24
"github.com/gogits/gogs/modules/process"
26
25
)
@@ -80,36 +79,50 @@ func (diff *Diff) NumFiles() int {
80
79
81
80
const DIFF_HEAD = "diff --git "
82
81
83
- func ParsePatch (pid int64 , maxlines int , cmd * exec.Cmd , reader io.Reader ) (* Diff , error ) {
84
- scanner := bufio .NewScanner (reader )
82
+ func ParsePatch (maxlines int , reader io.Reader ) (* Diff , error ) {
85
83
var (
84
+ diff = & Diff {Files : make ([]* DiffFile , 0 )}
85
+
86
86
curFile * DiffFile
87
87
curSection = & DiffSection {
88
88
Lines : make ([]* DiffLine , 0 , 10 ),
89
89
}
90
90
91
91
leftLine , rightLine int
92
- // FIXME: Should use cache in the future.
93
- buf bytes.Buffer
92
+ lineCount int
94
93
)
95
94
96
- diff := & Diff {Files : make ([]* DiffFile , 0 )}
97
- var i int
98
- for scanner .Scan () {
99
- line := scanner .Text ()
95
+ input := bufio .NewReader (reader )
96
+ isEOF := false
97
+ for {
98
+ if isEOF {
99
+ break
100
+ }
100
101
101
- if strings .HasPrefix (line , "+++ " ) || strings .HasPrefix (line , "--- " ) {
102
- continue
102
+ line , err := input .ReadString ('\n' )
103
+ if err != nil {
104
+ if err == io .EOF {
105
+ isEOF = true
106
+ } else {
107
+ return nil , fmt .Errorf ("ReadString: %v" , err )
108
+ }
109
+ }
110
+
111
+ if len (line ) > 0 && line [len (line )- 1 ] == '\n' {
112
+ // Remove line break.
113
+ line = line [:len (line )- 1 ]
103
114
}
104
115
105
- if line == "" {
116
+ if strings .HasPrefix (line , "+++ " ) || strings .HasPrefix (line , "--- " ) {
117
+ continue
118
+ } else if len (line ) == 0 {
106
119
continue
107
120
}
108
121
109
- i = i + 1
122
+ lineCount ++
110
123
111
124
// Diff data too large, we only show the first about maxlines lines
112
- if i >= maxlines {
125
+ if lineCount >= maxlines {
113
126
log .Warn ("Diff data too large" )
114
127
diff .Files = nil
115
128
return diff , nil
@@ -189,17 +202,26 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
189
202
diff .Files = append (diff .Files , curFile )
190
203
191
204
// Check file diff type.
192
- for scanner .Scan () {
205
+ for {
206
+ line , err := input .ReadString ('\n' )
207
+ if err != nil {
208
+ if err == io .EOF {
209
+ isEOF = true
210
+ } else {
211
+ return nil , fmt .Errorf ("ReadString: %v" , err )
212
+ }
213
+ }
214
+
193
215
switch {
194
- case strings .HasPrefix (scanner . Text () , "new file" ):
216
+ case strings .HasPrefix (line , "new file" ):
195
217
curFile .Type = DIFF_FILE_ADD
196
218
curFile .IsCreated = true
197
- case strings .HasPrefix (scanner . Text () , "deleted" ):
219
+ case strings .HasPrefix (line , "deleted" ):
198
220
curFile .Type = DIFF_FILE_DEL
199
221
curFile .IsDeleted = true
200
- case strings .HasPrefix (scanner . Text () , "index" ):
222
+ case strings .HasPrefix (line , "index" ):
201
223
curFile .Type = DIFF_FILE_CHANGE
202
- case strings .HasPrefix (scanner . Text () , "similarity index 100%" ):
224
+ case strings .HasPrefix (line , "similarity index 100%" ):
203
225
curFile .Type = DIFF_FILE_RENAME
204
226
curFile .IsRenamed = true
205
227
curFile .OldName = curFile .Name
@@ -212,6 +234,8 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
212
234
}
213
235
}
214
236
237
+ // FIXME: detect encoding while parsing.
238
+ var buf bytes.Buffer
215
239
for _ , f := range diff .Files {
216
240
buf .Reset ()
217
241
for _ , sec := range f .Sections {
@@ -238,61 +262,55 @@ func ParsePatch(pid int64, maxlines int, cmd *exec.Cmd, reader io.Reader) (*Diff
238
262
return diff , nil
239
263
}
240
264
241
- func GetDiffRange (repoPath , beforeCommitId string , afterCommitId string , maxlines int ) (* Diff , error ) {
265
+ func GetDiffRange (repoPath , beforeCommitID string , afterCommitID string , maxlines int ) (* Diff , error ) {
242
266
repo , err := git .OpenRepository (repoPath )
243
267
if err != nil {
244
268
return nil , err
245
269
}
246
270
247
- commit , err := repo .GetCommit (afterCommitId )
271
+ commit , err := repo .GetCommit (afterCommitID )
248
272
if err != nil {
249
273
return nil , err
250
274
}
251
275
252
- rd , wr := io .Pipe ()
253
276
var cmd * exec.Cmd
254
277
// if "after" commit given
255
- if beforeCommitId == "" {
278
+ if len ( beforeCommitID ) == 0 {
256
279
// First commit of repository.
257
280
if commit .ParentCount () == 0 {
258
- cmd = exec .Command ("git" , "show" , afterCommitId )
281
+ cmd = exec .Command ("git" , "show" , afterCommitID )
259
282
} else {
260
283
c , _ := commit .Parent (0 )
261
- cmd = exec .Command ("git" , "diff" , "-M" , c .ID .String (), afterCommitId )
284
+ cmd = exec .Command ("git" , "diff" , "-M" , c .ID .String (), afterCommitID )
262
285
}
263
286
} else {
264
- cmd = exec .Command ("git" , "diff" , "-M" , beforeCommitId , afterCommitId )
287
+ cmd = exec .Command ("git" , "diff" , "-M" , beforeCommitID , afterCommitID )
265
288
}
266
289
cmd .Dir = repoPath
267
- cmd .Stdout = wr
268
- cmd .Stdin = os .Stdin
269
290
cmd .Stderr = os .Stderr
270
291
271
- done := make (chan error )
272
- go func () {
273
- cmd .Start ()
274
- done <- cmd .Wait ()
275
- wr .Close ()
276
- }()
277
- defer rd .Close ()
278
-
279
- desc := fmt .Sprintf ("GetDiffRange(%s)" , repoPath )
280
- pid := process .Add (desc , cmd )
281
- go func () {
282
- // In case process became zombie.
283
- select {
284
- case <- time .After (5 * time .Minute ):
285
- if errKill := process .Kill (pid ); errKill != nil {
286
- log .Error (4 , "git_diff.ParsePatch(Kill): %v" , err )
287
- }
288
- <- done
289
- // return "", ErrExecTimeout.Error(), ErrExecTimeout
290
- case err = <- done :
291
- process .Remove (pid )
292
- }
293
- }()
292
+ stdout , err := cmd .StdoutPipe ()
293
+ if err != nil {
294
+ return nil , fmt .Errorf ("StdoutPipe: %v" , err )
295
+ }
296
+
297
+ if err = cmd .Start (); err != nil {
298
+ return nil , fmt .Errorf ("Start: %v" , err )
299
+ }
294
300
295
- return ParsePatch (pid , maxlines , cmd , rd )
301
+ pid := process .Add (fmt .Sprintf ("GetDiffRange (%s)" , repoPath ), cmd )
302
+ defer process .Remove (pid )
303
+
304
+ diff , err := ParsePatch (maxlines , stdout )
305
+ if err != nil {
306
+ return nil , fmt .Errorf ("ParsePatch: %v" , err )
307
+ }
308
+
309
+ if err = cmd .Wait (); err != nil {
310
+ return nil , fmt .Errorf ("Wait: %v" , err )
311
+ }
312
+
313
+ return diff , nil
296
314
}
297
315
298
316
func GetDiffCommit (repoPath , commitId string , maxlines int ) (* Diff , error ) {
0 commit comments