s
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package gitcmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MergeResult struct {
|
||||
Base string `json:"base"`
|
||||
Head string `json:"head"`
|
||||
MergeCommit *Commit `json:"merge_commit,omitempty"`
|
||||
FastForward bool `json:"fast_forward"`
|
||||
Conflicts []string `json:"conflicts,omitempty"`
|
||||
}
|
||||
|
||||
func (r *Repository) Merge(base, head, message, authorName, authorEmail string, noFF bool) (*MergeResult, error) {
|
||||
baseSHA, err := r.refSHA("refs/heads/" + base)
|
||||
if err != nil || baseSHA == "" {
|
||||
return nil, fmt.Errorf("base branch %q not found", base)
|
||||
}
|
||||
headSHA, err := r.refSHA("refs/heads/" + head)
|
||||
if err != nil || headSHA == "" {
|
||||
return nil, fmt.Errorf("head branch %q not found", head)
|
||||
}
|
||||
|
||||
if !noFF && r.isAncestor(baseSHA, headSHA) {
|
||||
if err := r.updateRef("refs/heads/"+base, headSHA, baseSHA); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hc, err := r.GetCommit(headSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MergeResult{Base: base, Head: head, MergeCommit: hc, FastForward: true}, nil
|
||||
}
|
||||
|
||||
out, _, err := NewCommand("merge-tree", "--write-tree", "-z", "--name-only", "--no-messages").
|
||||
AddDynamicArguments(baseSHA, headSHA).
|
||||
WithDir(r.Path).RunStdString(r.ctx)
|
||||
|
||||
conflict := false
|
||||
if err != nil {
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) && exitErr.ExitCode() == 1 {
|
||||
conflict = true
|
||||
} else {
|
||||
return nil, fmt.Errorf("merge-tree: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
parts := strings.Split(out, "\x00")
|
||||
if len(parts) == 0 || strings.TrimSpace(parts[0]) == "" {
|
||||
return nil, fmt.Errorf("merge-tree: empty output")
|
||||
}
|
||||
mergedTree := strings.TrimSpace(parts[0])
|
||||
|
||||
if conflict {
|
||||
var conflicts []string
|
||||
for i := 1; i < len(parts); i++ {
|
||||
if p := strings.TrimSpace(parts[i]); p != "" {
|
||||
conflicts = append(conflicts, p)
|
||||
}
|
||||
}
|
||||
return &MergeResult{Base: base, Head: head, Conflicts: conflicts}, nil
|
||||
}
|
||||
|
||||
commitSHA, err := r.commitTree(mergedTree, message, authorName, authorEmail, r.Path, baseSHA, headSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.updateRef("refs/heads/"+base, commitSHA, baseSHA); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc, err := r.GetCommit(commitSHA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &MergeResult{Base: base, Head: head, MergeCommit: mc}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user