Skip to content

Commit

Permalink
feat: use context
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Jan 11, 2025
1 parent 03b3134 commit 66a840e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 23 deletions.
3 changes: 2 additions & 1 deletion cmd/revgrep/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package main

import (
"context"
"flag"
"fmt"
"os"
Expand Down Expand Up @@ -37,7 +38,7 @@ func main() {
checker.Debug = os.Stdout
}

issues, err := checker.Check(os.Stdin, os.Stderr)
issues, err := checker.Check(context.Background(), os.Stdin, os.Stderr)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand Down
48 changes: 30 additions & 18 deletions revgrep.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package revgrep
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -86,9 +87,11 @@ func (i simpleInputIssue) Line() int {
}

// Prepare extracts a patch and changed lines.
func (c *Checker) Prepare() error {
returnErr := c.preparePatch()
func (c *Checker) Prepare(ctx context.Context) error {
returnErr := c.preparePatch(ctx)

c.changes = c.linesChanged()

return returnErr
}

Expand Down Expand Up @@ -119,7 +122,9 @@ func (c *Checker) IsNewIssue(i InputIssue) (hunkPos int, isNew bool) {
if changed || fchanges == nil {
// either file changed or it's a new file
hunkPos := fpos.lineNo
if changed { // existing file changed

// existing file changed
if changed {
hunkPos = fpos.hunkPos
}

Expand All @@ -137,8 +142,8 @@ func (c *Checker) IsNewIssue(i InputIssue) (hunkPos int, isNew bool) {
// all issues are written to writer and an error is returned.
//
// File paths in reader must be relative to current working directory or absolute.
func (c *Checker) Check(reader io.Reader, writer io.Writer) (issues []Issue, err error) {
returnErr := c.Prepare()
func (c *Checker) Check(ctx context.Context, reader io.Reader, writer io.Writer) (issues []Issue, err error) {
returnErr := c.Prepare(ctx)
writeAll := returnErr != nil

// file.go:lineNo:colNo:message
Expand Down Expand Up @@ -240,11 +245,11 @@ func (c *Checker) debugf(format string, s ...interface{}) {
}
}

func (c *Checker) preparePatch() error {
func (c *Checker) preparePatch(ctx context.Context) error {
// Check if patch is supplied, if not, retrieve from VCS
if c.Patch == nil {
var err error
c.Patch, c.NewFiles, err = GitPatch(c.RevisionFrom, c.RevisionTo)
c.Patch, c.NewFiles, err = GitPatch(ctx, c.RevisionFrom, c.RevisionTo)
if err != nil {
return fmt.Errorf("could not read git repo: %w", err)
}
Expand Down Expand Up @@ -287,15 +292,19 @@ func (c *Checker) linesChanged() map[string][]pos {
// it's likey part of a file and not relevant to the patch.
continue
}

if err != nil {
scanErr = err
break
}

line := strings.TrimRight(string(lineB), "\n")

c.debugf(line)

s.lineNo++
s.hunkPos++

switch {
case strings.HasPrefix(line, "+++ ") && len(line) > 4:
if s.changes != nil {
Expand All @@ -304,6 +313,7 @@ func (c *Checker) linesChanged() map[string][]pos {
}
// 6 removes "+++ b/"
s = state{file: line[6:], hunkPos: -1, changes: []pos{}}

case strings.HasPrefix(line, "@@ "):
// @@ -1 +2,4 @@
// chdr ^^^^^^^^^^^^^
Expand All @@ -317,8 +327,10 @@ func (c *Checker) linesChanged() map[string][]pos {
panic(err)
}
s.lineNo = int(cstart) - 1 // -1 as cstart is the next line number

case strings.HasPrefix(line, "-"):
s.lineNo--

case strings.HasPrefix(line, "+"):
s.changes = append(s.changes, pos{lineNo: s.lineNo, hunkPos: s.hunkPos})
}
Expand All @@ -342,15 +354,15 @@ func (c *Checker) linesChanged() map[string][]pos {
// If revisionFrom is set but revisionTo is not,
// untracked files will be included, to exclude untracked files set revisionTo to HEAD~.
// It's incorrect to specify revisionTo without a revisionFrom.
func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) {
func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader, []string, error) {
// check if git repo exists
if err := exec.Command("git", "status", "--porcelain").Run(); err != nil {
if err := exec.CommandContext(ctx, "git", "status", "--porcelain").Run(); err != nil {
// don't return an error, we assume the error is not repo exists
return nil, nil, nil
}

// make a patch for untracked files
ls, err := exec.Command("git", "ls-files", "--others", "--exclude-standard").CombinedOutput()
ls, err := exec.CommandContext(ctx, "git", "ls-files", "--others", "--exclude-standard").CombinedOutput()
if err != nil {
return nil, nil, fmt.Errorf("error executing git ls-files: %w", err)
}
Expand All @@ -376,7 +388,7 @@ func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) {

args = append(args, "--")

patch, errDiff := gitDiff(args...)
patch, errDiff := gitDiff(ctx, args...)
if errDiff != nil {
return nil, nil, errDiff
}
Expand All @@ -389,7 +401,7 @@ func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) {
}

// make a patch for unstaged changes
patch, err := gitDiff("--")
patch, err := gitDiff(ctx, "--")
if err != nil {
return nil, nil, err
}
Expand All @@ -403,18 +415,18 @@ func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) {
}

// check for changes in recent commit
patch, err = gitDiff("HEAD~", "--")
patch, err = gitDiff(ctx, "HEAD~", "--")
if err != nil {
return nil, nil, err
}

return patch, nil, nil
}

func gitDiff(extraArgs ...string) (*bytes.Buffer, error) {
cmd := exec.Command("git", "diff", "--color=never", "--no-ext-diff")
func gitDiff(ctx context.Context, extraArgs ...string) (*bytes.Buffer, error) {
cmd := exec.CommandContext(ctx, "git", "diff", "--color=never", "--no-ext-diff")

if isSupportedByGit(2, 41, 0) {
if isSupportedByGit(ctx, 2, 41, 0) {
cmd.Args = append(cmd.Args, "--default-prefix")
}

Expand Down Expand Up @@ -443,8 +455,8 @@ func readAsError(buff io.Reader) error {
return errors.New(string(output))
}

func isSupportedByGit(major, minor, patch int) bool {
output, err := exec.Command("git", "version").CombinedOutput()
func isSupportedByGit(ctx context.Context, major, minor, patch int) bool {
output, err := exec.CommandContext(ctx, "git", "version").CombinedOutput()
if err != nil {
return false
}
Expand Down
9 changes: 5 additions & 4 deletions revgrep_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package revgrep
import (
"bufio"
"bytes"
"context"
"io"
"os"
"os/exec"
Expand Down Expand Up @@ -114,7 +115,7 @@ func TestCheckerRegexp(t *testing.T) {
Regexp: test.regexp,
}

issues, err := checker.Check(bytes.NewReader([]byte(test.line)), io.Discard)
issues, err := checker.Check(context.Background(), bytes.NewReader([]byte(test.line)), io.Discard)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
Expand Down Expand Up @@ -163,7 +164,7 @@ func TestWholeFiles(t *testing.T) {
WholeFiles: true,
}

issues, err := checker.Check(bytes.NewReader([]byte(test.line)), io.Discard)
issues, err := checker.Check(context.Background(), bytes.NewReader([]byte(test.line)), io.Discard)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand Down Expand Up @@ -216,7 +217,7 @@ func TestChecker_Check_changesWriter(t *testing.T) {
RevisionFrom: test.revFrom,
RevisionTo: test.revTo,
}
_, err := c.Check(bytes.NewBuffer(goVetOutput), &out)
_, err := c.Check(context.Background(), bytes.NewBuffer(goVetOutput), &out)
if err != nil {
t.Errorf("%s: unexpected error: %v", stage, err)
}
Expand Down Expand Up @@ -268,7 +269,7 @@ func TestGitPatchNonGitDir(t *testing.T) {
t.Fatalf("could not chdir: %v", err)
}

patch, newfiles, err := GitPatch("", "")
patch, newfiles, err := GitPatch(context.Background(), "", "")
if err != nil {
t.Errorf("error expected nil, got: %v", err)
}
Expand Down

0 comments on commit 66a840e

Please sign in to comment.