@@ -18,11 +18,16 @@ import (
18
18
)
19
19
20
20
// LogNameStatusRepo opens git log --raw in the provided repo and returns a stdin pipe, a stdout reader and cancel function
21
- func LogNameStatusRepo (repository , head , treepath string , paths ... string ) (* bufio.Reader , func ()) {
21
+ func LogNameStatusRepo (ctx context. Context , repository , head , treepath string , paths ... string ) (* bufio.Reader , func ()) {
22
22
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
23
23
// so let's create a batch stdin and stdout
24
24
stdoutReader , stdoutWriter := nio .Pipe (buffer .New (32 * 1024 ))
25
+
26
+ // Lets also create a context so that we can absolutely ensure that the command should die when we're done
27
+ ctx , ctxCancel := context .WithCancel (ctx )
28
+
25
29
cancel := func () {
30
+ ctxCancel ()
26
31
_ = stdoutReader .Close ()
27
32
_ = stdoutWriter .Close ()
28
33
}
@@ -50,7 +55,7 @@ func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*buf
50
55
51
56
go func () {
52
57
stderr := strings.Builder {}
53
- err := NewCommand ( args ... ).RunInDirFullPipeline (repository , stdoutWriter , & stderr , nil )
58
+ err := NewCommandContext ( ctx , args ... ).RunInDirFullPipeline (repository , stdoutWriter , & stderr , nil )
54
59
if err != nil {
55
60
_ = stdoutWriter .CloseWithError (ConcatenateError (err , (& stderr ).String ()))
56
61
} else {
@@ -75,8 +80,8 @@ type LogNameStatusRepoParser struct {
75
80
}
76
81
77
82
// NewLogNameStatusRepoParser returns a new parser for a git log raw output
78
- func NewLogNameStatusRepoParser (repository , head , treepath string , paths ... string ) * LogNameStatusRepoParser {
79
- rd , cancel := LogNameStatusRepo (repository , head , treepath , paths ... )
83
+ func NewLogNameStatusRepoParser (ctx context. Context , repository , head , treepath string , paths ... string ) * LogNameStatusRepoParser {
84
+ rd , cancel := LogNameStatusRepo (ctx , repository , head , treepath , paths ... )
80
85
return & LogNameStatusRepoParser {
81
86
treepath : treepath ,
82
87
paths : paths ,
@@ -311,8 +316,11 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
311
316
}
312
317
}
313
318
314
- g := NewLogNameStatusRepoParser (repo .Path , head .ID .String (), treepath , paths ... )
315
- defer g .Close ()
319
+ g := NewLogNameStatusRepoParser (ctx , repo .Path , head .ID .String (), treepath , paths ... )
320
+ // don't use defer g.Close() here as g may change its value - instead wrap in a func
321
+ defer func () {
322
+ g .Close ()
323
+ }()
316
324
317
325
results := make ([]string , len (paths ))
318
326
remaining := len (paths )
@@ -331,6 +339,7 @@ heaploop:
331
339
for {
332
340
select {
333
341
case <- ctx .Done ():
342
+ g .Close ()
334
343
return nil , ctx .Err ()
335
344
default :
336
345
}
@@ -380,7 +389,7 @@ heaploop:
380
389
remainingPaths = append (remainingPaths , pth )
381
390
}
382
391
}
383
- g = NewLogNameStatusRepoParser (repo .Path , lastEmptyParent , treepath , remainingPaths ... )
392
+ g = NewLogNameStatusRepoParser (ctx , repo .Path , lastEmptyParent , treepath , remainingPaths ... )
384
393
parentRemaining = map [string ]bool {}
385
394
nextRestart = (remaining * 3 ) / 4
386
395
continue heaploop
0 commit comments