@@ -12,6 +12,12 @@ import (
12
12
"strings"
13
13
)
14
14
15
+ type patchOption struct {
16
+ revisionFrom string
17
+ revisionTo string
18
+ mergeBase string
19
+ }
20
+
15
21
// GitPatch returns a patch from a git repository.
16
22
// If no git repository was found and no errors occurred, nil is returned,
17
23
// else an error is returned revisionFrom and revisionTo defines the git diff parameters,
@@ -20,7 +26,7 @@ import (
20
26
// If revisionFrom is set but revisionTo is not,
21
27
// untracked files will be included, to exclude untracked files set revisionTo to HEAD~.
22
28
// 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 ) {
24
30
// check if git repo exists
25
31
if err := exec .CommandContext (ctx , "git" , "status" , "--porcelain" ).Run (); err != nil {
26
32
// 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,
45
51
newFiles = append (newFiles , string (file ))
46
52
}
47
53
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 }
50
68
51
- if revisionTo != "" {
52
- args = append (args , revisionTo )
69
+ if option . revisionTo != "" {
70
+ args = append (args , option . revisionTo )
53
71
}
54
72
55
73
args = append (args , "--" )
@@ -59,7 +77,7 @@ func GitPatch(ctx context.Context, revisionFrom, revisionTo string) (io.Reader,
59
77
return nil , nil , errDiff
60
78
}
61
79
62
- if revisionTo == "" {
80
+ if option . revisionTo == "" {
63
81
return patch , newFiles , nil
64
82
}
65
83
@@ -159,3 +177,19 @@ func isSupportedByGit(ctx context.Context, major, minor, patch int) bool {
159
177
160
178
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
161
179
}
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