@@ -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+ }
0 commit comments