From 65a7855713ad3ad74697a0eef9e431debf3d1b26 Mon Sep 17 00:00:00 2001 From: Bill Rich Date: Fri, 2 Sep 2022 11:02:38 -0700 Subject: [PATCH] Split parsing from reader (#774) --- pkg/gitparse/gitparse.go | 184 ++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 89 deletions(-) diff --git a/pkg/gitparse/gitparse.go b/pkg/gitparse/gitparse.go index 09ae120fc..c141a2cc7 100644 --- a/pkg/gitparse/gitparse.go +++ b/pkg/gitparse/gitparse.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "fmt" + "io" "os/exec" "path/filepath" "strconv" @@ -68,10 +69,6 @@ func RepoPath(ctx context.Context, source string, head string) (chan Commit, err return commitChan, err } - outReader := bufio.NewReader(stdOut) - var currentCommit *Commit - var currentDiff *Diff - go func() { scanner := bufio.NewScanner(stdErr) for scanner.Scan() { @@ -80,98 +77,107 @@ func RepoPath(ctx context.Context, source string, head string) (chan Commit, err }() go func() { - defer common.Recover(ctx) - for { - line, err := outReader.ReadBytes([]byte("\n")[0]) - if err != nil && len(line) == 0 { - break - } - switch { - case isCommitLine(line): - // If there is a currentDiff, add it to currentCommit. - if currentDiff != nil && currentDiff.Content.Len() > 0 { - currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) - } - // If there is a currentCommit, send it to the channel. - if currentCommit != nil { - commitChan <- *currentCommit - } - // Create a new currentDiff and currentCommit - currentDiff = &Diff{} - currentCommit = &Commit{ - Message: strings.Builder{}, - } - // Check that the commit line contains a hash and set it. - if len(line) >= 47 { - currentCommit.Hash = string(line[7:47]) - } - case isAuthorLine(line): - currentCommit.Author = string(line[8:]) - case isDateLine(line): - date, err := time.Parse(DateFormat, strings.TrimSpace(string(line[6:]))) - if err != nil { - log.WithError(err).Debug("Could not parse date from git stream.") - } - currentCommit.Date = date - case isDiffLine(line): - // This should never be nil, but check in case the stdin stream is messed up. - if currentDiff != nil && currentDiff.Content.Len() > 0 { - currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) - } - currentDiff = &Diff{} - case isModeLine(line): - // NoOp - case isIndexLine(line): - // NoOp - case isPlusFileLine(line): - currentDiff.PathB = strings.TrimRight(string(line[6:]), "\n") - case isMinusFileLine(line): - // NoOp - case isPlusDiffLine(line): - currentDiff.Content.Write(line[1:]) - case isMinusDiffLine(line): - // NoOp. We only care about additions. - case isMessageLine(line): - currentCommit.Message.Write(line[4:]) - case isBinaryLine(line): - currentDiff.IsBinary = true - currentDiff.PathB = pathFromBinaryLine(line) - case isLineNumberDiffLine(line): - if currentDiff != nil && currentDiff.Content.Len() > 0 { - currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) - } - newDiff := &Diff{ - PathB: currentDiff.PathB, - } - - currentDiff = newDiff - - words := bytes.Split(line, []byte(" ")) - if len(words) >= 3 { - startSlice := bytes.Split(words[2], []byte(",")) - lineStart, err := strconv.Atoi(string(startSlice[0])) - if err == nil { - currentDiff.LineStart = lineStart - } - } - - } - - } - if currentDiff != nil && currentDiff.Content.Len() > 0 { - currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) - } - if currentCommit != nil { - commitChan <- *currentCommit - } + FromReader(ctx, stdOut, commitChan) if err := cmd.Wait(); err != nil { log.WithError(err).Debugf("Error waiting for git command to complete.") } - close(commitChan) }() + return commitChan, nil } +func FromReader(ctx context.Context, stdOut io.Reader, commitChan chan Commit) { + outReader := bufio.NewReader(stdOut) + var currentCommit *Commit + var currentDiff *Diff + + defer common.Recover(ctx) + for { + line, err := outReader.ReadBytes([]byte("\n")[0]) + if err != nil && len(line) == 0 { + break + } + switch { + case isCommitLine(line): + // If there is a currentDiff, add it to currentCommit. + if currentDiff != nil && currentDiff.Content.Len() > 0 { + currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) + } + // If there is a currentCommit, send it to the channel. + if currentCommit != nil { + commitChan <- *currentCommit + } + // Create a new currentDiff and currentCommit + currentDiff = &Diff{} + currentCommit = &Commit{ + Message: strings.Builder{}, + } + // Check that the commit line contains a hash and set it. + if len(line) >= 47 { + currentCommit.Hash = string(line[7:47]) + } + case isAuthorLine(line): + currentCommit.Author = string(line[8:]) + case isDateLine(line): + date, err := time.Parse(DateFormat, strings.TrimSpace(string(line[6:]))) + if err != nil { + log.WithError(err).Debug("Could not parse date from git stream.") + } + currentCommit.Date = date + case isDiffLine(line): + // This should never be nil, but check in case the stdin stream is messed up. + if currentDiff != nil && currentDiff.Content.Len() > 0 { + currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) + } + currentDiff = &Diff{} + case isModeLine(line): + // NoOp + case isIndexLine(line): + // NoOp + case isPlusFileLine(line): + currentDiff.PathB = strings.TrimRight(string(line[6:]), "\n") + case isMinusFileLine(line): + // NoOp + case isPlusDiffLine(line): + currentDiff.Content.Write(line[1:]) + case isMinusDiffLine(line): + // NoOp. We only care about additions. + case isMessageLine(line): + currentCommit.Message.Write(line[4:]) + case isBinaryLine(line): + currentDiff.IsBinary = true + currentDiff.PathB = pathFromBinaryLine(line) + case isLineNumberDiffLine(line): + if currentDiff != nil && currentDiff.Content.Len() > 0 { + currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) + } + newDiff := &Diff{ + PathB: currentDiff.PathB, + } + + currentDiff = newDiff + + words := bytes.Split(line, []byte(" ")) + if len(words) >= 3 { + startSlice := bytes.Split(words[2], []byte(",")) + lineStart, err := strconv.Atoi(string(startSlice[0])) + if err == nil { + currentDiff.LineStart = lineStart + } + } + + } + + } + if currentDiff != nil && currentDiff.Content.Len() > 0 { + currentCommit.Diffs = append(currentCommit.Diffs, *currentDiff) + } + if currentCommit != nil { + commitChan <- *currentCommit + } + close(commitChan) +} + // Date: Tue Aug 10 15:20:40 2021 +0100 func isDateLine(line []byte) bool { if len(line) > 7 && bytes.Equal(line[:5], []byte("Date:")) {