Skip to content

Commit

Permalink
feat: merge-base option
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Jan 31, 2025
1 parent 5d5bf78 commit 43995b0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 10 deletions.
46 changes: 40 additions & 6 deletions patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import (
"strings"
)

type patchOption struct {
revisionFrom string
revisionTo string
mergeBase string
}

// 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,
Expand All @@ -20,7 +26,7 @@ import (
// 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(ctx context.Context, revisionFrom, revisionTo string) (io.Reader, []string, error) {
func GitPatch(ctx context.Context, option patchOption) (io.Reader, []string, error) {
// check if git repo exists
if err := exec.CommandContext(ctx, "git", "status", "--porcelain").Run(); err != nil {
// don't return an error, we assume the error is not repo exists
Expand All @@ -45,11 +51,23 @@ func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader,
newFiles = append(newFiles, string(file))
}

if revisionFrom != "" {
args := []string{revisionFrom}
if option.mergeBase != "" {
var base string
base, err = getMergeBase(ctx, option.mergeBase)
if err != nil {
return nil, nil, err
}

if base != "" {
option.revisionFrom = base
}
}

if option.revisionFrom != "" {
args := []string{option.revisionFrom}

if revisionTo != "" {
args = append(args, revisionTo)
if option.revisionTo != "" {
args = append(args, option.revisionTo)
}

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

if revisionTo == "" {
if option.revisionTo == "" {
return patch, newFiles, nil
}

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

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
}

func getMergeBase(ctx context.Context, base string) (string, error) {
cmd := exec.CommandContext(ctx, "git", "merge-base", base, "HEAD")

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

cmd.Stdout = patch
cmd.Stderr = errBuff

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

return strings.TrimSpace(patch.String()), nil
}
2 changes: 1 addition & 1 deletion patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestGitPatch_nonGitDir(t *testing.T) {

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

patch, newFiles, err := GitPatch(context.Background(), "", "")
patch, newFiles, err := GitPatch(context.Background(), patchOption{})
if err != nil {
t.Errorf("error expected nil, got: %v", err)
}
Expand Down
14 changes: 11 additions & 3 deletions revgrep.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ type Checker struct {
Debug io.Writer
// RevisionFrom check revision starting at, leave blank for auto-detection ignored if patch is set.
RevisionFrom string
// 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.
WholeFiles bool
// RevisionTo checks revision finishing at, leave blank for auto-detection ignored if patch is set.
RevisionTo string
// MergeBase checks revision starting at the best common ancestor, leave blank for auto-detection ignored if patch is set.
MergeBase string
// 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.
WholeFiles bool
// Regexp to match path, line number, optional column number, and message.
Regexp string
// AbsPath is used to make an absolute path of an issue's filename to be relative in order to match patch file.
Expand Down Expand Up @@ -228,8 +230,14 @@ func (c *Checker) loadPatch(ctx context.Context) error {
return nil
}

option := patchOption{
revisionFrom: c.RevisionFrom,
revisionTo: c.RevisionTo,
mergeBase: c.MergeBase,
}

var err error
c.Patch, c.NewFiles, err = GitPatch(ctx, c.RevisionFrom, c.RevisionTo)
c.Patch, c.NewFiles, err = GitPatch(ctx, option)
if err != nil {
return fmt.Errorf("could not read git repo: %w", err)
}
Expand Down

0 comments on commit 43995b0

Please sign in to comment.