Skip to content

Commit 43995b0

Browse files
committed
feat: merge-base option
1 parent 5d5bf78 commit 43995b0

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

Diff for: patch.go

+40-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import (
1212
"strings"
1313
)
1414

15+
type patchOption struct {
16+
revisionFrom string
17+
revisionTo string
18+
mergeBase string
19+
}
20+
1521
// GitPatch returns a patch from a git repository.
1622
// If no git repository was found and no errors occurred, nil is returned,
1723
// else an error is returned revisionFrom and revisionTo defines the git diff parameters,
@@ -20,7 +26,7 @@ import (
2026
// If revisionFrom is set but revisionTo is not,
2127
// untracked files will be included, to exclude untracked files set revisionTo to HEAD~.
2228
// It's incorrect to specify revisionTo without a revisionFrom.
23-
func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader, []string, error) {
29+
func GitPatch(ctx context.Context, option patchOption) (io.Reader, []string, error) {
2430
// check if git repo exists
2531
if err := exec.CommandContext(ctx, "git", "status", "--porcelain").Run(); err != nil {
2632
// don't return an error, we assume the error is not repo exists
@@ -45,11 +51,23 @@ func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader,
4551
newFiles = append(newFiles, string(file))
4652
}
4753

48-
if revisionFrom != "" {
49-
args := []string{revisionFrom}
54+
if option.mergeBase != "" {
55+
var base string
56+
base, err = getMergeBase(ctx, option.mergeBase)
57+
if err != nil {
58+
return nil, nil, err
59+
}
60+
61+
if base != "" {
62+
option.revisionFrom = base
63+
}
64+
}
65+
66+
if option.revisionFrom != "" {
67+
args := []string{option.revisionFrom}
5068

51-
if revisionTo != "" {
52-
args = append(args, revisionTo)
69+
if option.revisionTo != "" {
70+
args = append(args, option.revisionTo)
5371
}
5472

5573
args = append(args, "--")
@@ -59,7 +77,7 @@ func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader,
5977
return nil, nil, errDiff
6078
}
6179

62-
if revisionTo == "" {
80+
if option.revisionTo == "" {
6381
return patch, newFiles, nil
6482
}
6583

@@ -159,3 +177,19 @@ func isSupportedByGit(ctx context.Context, major, minor, patch int) bool {
159177

160178
return currentMajor*1_000_000_000+currentMinor*1_000_000+currentPatch*1_000 >= major*1_000_000_000+minor*1_000_000+patch*1_000
161179
}
180+
181+
func getMergeBase(ctx context.Context, base string) (string, error) {
182+
cmd := exec.CommandContext(ctx, "git", "merge-base", base, "HEAD")
183+
184+
patch := new(bytes.Buffer)
185+
errBuff := new(bytes.Buffer)
186+
187+
cmd.Stdout = patch
188+
cmd.Stderr = errBuff
189+
190+
if err := cmd.Run(); err != nil {
191+
return "", fmt.Errorf("error executing %q: %w: %w", strings.Join(cmd.Args, " "), err, readAsError(errBuff))
192+
}
193+
194+
return strings.TrimSpace(patch.String()), nil
195+
}

Diff for: patch_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestGitPatch_nonGitDir(t *testing.T) {
2020

2121
t.Cleanup(func() { _ = os.Chdir(wd) })
2222

23-
patch, newFiles, err := GitPatch(context.Background(), "", "")
23+
patch, newFiles, err := GitPatch(context.Background(), patchOption{})
2424
if err != nil {
2525
t.Errorf("error expected nil, got: %v", err)
2626
}

Diff for: revgrep.go

+11-3
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ type Checker struct {
2929
Debug io.Writer
3030
// RevisionFrom check revision starting at, leave blank for auto-detection ignored if patch is set.
3131
RevisionFrom string
32-
// WholeFiles indicates that the user wishes to see all issues that comes up anywhere in any file that has been changed in this revision or patch.
33-
WholeFiles bool
3432
// RevisionTo checks revision finishing at, leave blank for auto-detection ignored if patch is set.
3533
RevisionTo string
34+
// MergeBase checks revision starting at the best common ancestor, leave blank for auto-detection ignored if patch is set.
35+
MergeBase string
36+
// WholeFiles indicates that the user wishes to see all issues that comes up anywhere in any file that has been changed in this revision or patch.
37+
WholeFiles bool
3638
// Regexp to match path, line number, optional column number, and message.
3739
Regexp string
3840
// AbsPath is used to make an absolute path of an issue's filename to be relative in order to match patch file.
@@ -228,8 +230,14 @@ func (c *Checker) loadPatch(ctx context.Context) error {
228230
return nil
229231
}
230232

233+
option := patchOption{
234+
revisionFrom: c.RevisionFrom,
235+
revisionTo: c.RevisionTo,
236+
mergeBase: c.MergeBase,
237+
}
238+
231239
var err error
232-
c.Patch, c.NewFiles, err = GitPatch(ctx, c.RevisionFrom, c.RevisionTo)
240+
c.Patch, c.NewFiles, err = GitPatch(ctx, option)
233241
if err != nil {
234242
return fmt.Errorf("could not read git repo: %w", err)
235243
}

0 commit comments

Comments
 (0)