summaryrefslogtreecommitdiffstats
path: root/modules/git/log_name_status.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/git/log_name_status.go')
-rw-r--r--modules/git/log_name_status.go23
1 files changed, 16 insertions, 7 deletions
diff --git a/modules/git/log_name_status.go b/modules/git/log_name_status.go
index 00a1859f7a..7d83ac7270 100644
--- a/modules/git/log_name_status.go
+++ b/modules/git/log_name_status.go
@@ -18,11 +18,16 @@ import (
)
// LogNameStatusRepo opens git log --raw in the provided repo and returns a stdin pipe, a stdout reader and cancel function
-func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*bufio.Reader, func()) {
+func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, paths ...string) (*bufio.Reader, func()) {
// We often want to feed the commits in order into cat-file --batch, followed by their trees and sub trees as necessary.
// so let's create a batch stdin and stdout
stdoutReader, stdoutWriter := nio.Pipe(buffer.New(32 * 1024))
+
+ // Lets also create a context so that we can absolutely ensure that the command should die when we're done
+ ctx, ctxCancel := context.WithCancel(ctx)
+
cancel := func() {
+ ctxCancel()
_ = stdoutReader.Close()
_ = stdoutWriter.Close()
}
@@ -50,7 +55,7 @@ func LogNameStatusRepo(repository, head, treepath string, paths ...string) (*buf
go func() {
stderr := strings.Builder{}
- err := NewCommand(args...).RunInDirFullPipeline(repository, stdoutWriter, &stderr, nil)
+ err := NewCommandContext(ctx, args...).RunInDirFullPipeline(repository, stdoutWriter, &stderr, nil)
if err != nil {
_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
} else {
@@ -75,8 +80,8 @@ type LogNameStatusRepoParser struct {
}
// NewLogNameStatusRepoParser returns a new parser for a git log raw output
-func NewLogNameStatusRepoParser(repository, head, treepath string, paths ...string) *LogNameStatusRepoParser {
- rd, cancel := LogNameStatusRepo(repository, head, treepath, paths...)
+func NewLogNameStatusRepoParser(ctx context.Context, repository, head, treepath string, paths ...string) *LogNameStatusRepoParser {
+ rd, cancel := LogNameStatusRepo(ctx, repository, head, treepath, paths...)
return &LogNameStatusRepoParser{
treepath: treepath,
paths: paths,
@@ -311,8 +316,11 @@ func WalkGitLog(ctx context.Context, repo *Repository, head *Commit, treepath st
}
}
- g := NewLogNameStatusRepoParser(repo.Path, head.ID.String(), treepath, paths...)
- defer g.Close()
+ g := NewLogNameStatusRepoParser(ctx, repo.Path, head.ID.String(), treepath, paths...)
+ // don't use defer g.Close() here as g may change its value - instead wrap in a func
+ defer func() {
+ g.Close()
+ }()
results := make([]string, len(paths))
remaining := len(paths)
@@ -331,6 +339,7 @@ heaploop:
for {
select {
case <-ctx.Done():
+ g.Close()
return nil, ctx.Err()
default:
}
@@ -380,7 +389,7 @@ heaploop:
remainingPaths = append(remainingPaths, pth)
}
}
- g = NewLogNameStatusRepoParser(repo.Path, lastEmptyParent, treepath, remainingPaths...)
+ g = NewLogNameStatusRepoParser(ctx, repo.Path, lastEmptyParent, treepath, remainingPaths...)
parentRemaining = map[string]bool{}
nextRestart = (remaining * 3) / 4
continue heaploop