Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: golangci/revgrep
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.5.2
Choose a base ref
...
head repository: golangci/revgrep
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.5.3
Choose a head ref
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Apr 9, 2024

  1. Copy the full SHA
    be6d820 View commit details
  2. fix: improve git diff errors

    ldez committed Apr 9, 2024
    Copy the full SHA
    c18688b View commit details
Showing with 59 additions and 39 deletions.
  1. +3 −3 .github/workflows/ci.yml
  2. +2 −2 .github/workflows/go-cross.yml
  3. +1 −3 .golangci.yml
  4. +1 −1 go.mod
  5. +52 −30 revgrep.go
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -13,20 +13,20 @@ jobs:
runs-on: ubuntu-latest
env:
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v1.54.2
GOLANGCI_LINT_VERSION: v1.56.2
CGO_ENABLED: 0

steps:

# https://github.com/marketplace/actions/checkout
- name: Check out code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0

# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}

4 changes: 2 additions & 2 deletions .github/workflows/go-cross.yml
Original file line number Diff line number Diff line change
@@ -23,11 +23,11 @@ jobs:

# https://github.com/marketplace/actions/checkout
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

# https://github.com/marketplace/actions/setup-go-environment
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}

4 changes: 1 addition & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ run:

linters-settings:
govet:
check-shadowing: true
enable-all: true
disable:
- fieldalignment
@@ -47,7 +46,6 @@ linters:
- nestif
- gomnd
- goerr113
# - wrapcheck
- nlreturn
- wsl
- exhaustive
@@ -66,7 +64,7 @@ linters:

issues:
exclude-use-default: false
max-per-linter: 0
max-issues-per-linter: 0
max-same-issues: 0
exclude:
- 'ST1000: at least one file in a package should have a package comment'
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/golangci/revgrep

go 1.19
go 1.21
82 changes: 52 additions & 30 deletions revgrep.go
Original file line number Diff line number Diff line change
@@ -334,10 +334,13 @@ func (c *Checker) linesChanged() map[string][]pos {
return changes
}

// GitPatch returns a patch from a git repository,
// if no git repository was found and no errors occurred, nil is returned, else an error is returned revisionFrom and revisionTo defines the git diff parameters,
// if left blank and there are unstaged changes or untracked files, only those will be returned else only check changes since HEAD~.
// If revisionFrom is set but revisionTo is not, untracked files will be included, to exclude untracked files set revisionTo to HEAD~.
// GitPatch returns a patch from a git repository.
// If no git repository was found and no errors occurred, nil is returned,
// else an error is returned revisionFrom and revisionTo defines the git diff parameters,
// if left blank and there are unstaged changes or untracked files,
// only those will be returned else only check changes since HEAD~.
// 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) {
// check if git repo exists
@@ -356,59 +359,59 @@ func GitPatch(revisionFrom, revisionTo string) (io.Reader, []string, error) {
for _, file := range bytes.Split(ls, []byte{'\n'}) {
if len(file) == 0 || bytes.HasSuffix(file, []byte{'/'}) {
// ls-files was sometimes showing directories when they were ignored
// I couldn't create a test case for this as I couldn't reproduce correctly
// for the moment, just exclude files with trailing /
// I couldn't create a test case for this as I couldn't reproduce correctly for the moment,
// just exclude files with trailing /
continue
}

newFiles = append(newFiles, string(file))
}

var patch bytes.Buffer
if revisionFrom != "" {
cmd := gitDiff(revisionFrom)
args := []string{revisionFrom}

if revisionTo != "" {
cmd.Args = append(cmd.Args, revisionTo)
args = append(args, revisionTo)
}
cmd.Args = append(cmd.Args, "--")

cmd.Stdout = &patch
if err := cmd.Run(); err != nil {
return nil, nil, fmt.Errorf("error executing git diff %q %q: %w", revisionFrom, revisionTo, err)
args = append(args, "--")

patch, errDiff := gitDiff(args...)
if errDiff != nil {
return nil, nil, errDiff
}

if revisionTo == "" {
return &patch, newFiles, nil
return patch, newFiles, nil
}

return &patch, nil, nil
return patch, nil, nil
}

// make a patch for unstaged changes
cmd := gitDiff("--")
cmd.Stdout = &patch
if err := cmd.Run(); err != nil {
return nil, nil, fmt.Errorf("error executing git diff: %w", err)
patch, err := gitDiff("--")
if err != nil {
return nil, nil, err
}

unstaged := patch.Len() > 0

// If there's unstaged changes OR untracked changes (or both), then this is
// a suitable patch
// If there's unstaged changes OR untracked changes (or both),
// then this is a suitable patch
if unstaged || newFiles != nil {
return &patch, newFiles, nil
return patch, newFiles, nil
}

// check for changes in recent commit

cmd = gitDiff("HEAD~", "--")
cmd.Stdout = &patch
if err := cmd.Run(); err != nil {
return nil, nil, fmt.Errorf("error executing git diff HEAD~: %w", err)
patch, err = gitDiff("HEAD~", "--")
if err != nil {
return nil, nil, err
}

return &patch, nil, nil
return patch, nil, nil
}

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

if isSupportedByGit(2, 41, 0) {
@@ -418,7 +421,26 @@ func gitDiff(extraArgs ...string) *exec.Cmd {
cmd.Args = append(cmd.Args, "--relative")
cmd.Args = append(cmd.Args, extraArgs...)

return cmd
patch := new(bytes.Buffer)
errBuff := new(bytes.Buffer)

cmd.Stdout = patch
cmd.Stderr = errBuff

if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("error executing %q: %w: %w", strings.Join(cmd.Args, " "), err, readAsError(errBuff))
}

return patch, nil
}

func readAsError(buff io.Reader) error {
output, err := io.ReadAll(buff)
if err != nil {
return fmt.Errorf("read stderr: %w", err)
}

return errors.New(string(output))
}

func isSupportedByGit(major, minor, patch int) bool {