@@ -18,11 +18,16 @@ import (
1818)
1919
2020// 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 ()) {
2222 // We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
2323 // so let's create a batch stdin and stdout
2424 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+
2529 cancel := func () {
30+ ctxCancel ()
2631 _ = stdoutReader .Close ()
2732 _ = stdoutWriter .Close ()
2833 }
@@ -50,7 +55,7 @@ func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*buf
5055
5156 go func () {
5257 stderr := strings.Builder {}
53- err := NewCommand ( args ... ).RunInDirFullPipeline (repository , stdoutWriter , & stderr , nil )
58+ err := NewCommandContext ( ctx , args ... ).RunInDirFullPipeline (repository , stdoutWriter , & stderr , nil )
5459 if err != nil {
5560 _ = stdoutWriter .CloseWithError (ConcatenateError (err , (& stderr ).String ()))
5661 } else {
@@ -75,8 +80,8 @@ type LogNameStatusRepoParser struct {
7580}
7681
7782// 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 ... )
8085 return & LogNameStatusRepoParser {
8186 treepath : treepath ,
8287 paths : paths ,
@@ -311,8 +316,11 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
311316 }
312317 }
313318
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+ }()
316324
317325 results := make ([]string , len (paths ))
318326 remaining := len (paths )
@@ -331,6 +339,7 @@ heaploop:
331339 for {
332340 select {
333341 case <- ctx .Done ():
342+ g .Close ()
334343 return nil , ctx .Err ()
335344 default :
336345 }
@@ -380,7 +389,7 @@ heaploop:
380389 remainingPaths = append (remainingPaths , pth )
381390 }
382391 }
383- g = NewLogNameStatusRepoParser (repo .Path , lastEmptyParent , treepath , remainingPaths ... )
392+ g = NewLogNameStatusRepoParser (ctx , repo .Path , lastEmptyParent , treepath , remainingPaths ... )
384393 parentRemaining = map [string ]bool {}
385394 nextRestart = (remaining * 3 ) / 4
386395 continue heaploop
0 commit comments