mirror of
https://github.com/harness/drone.git
synced 2025-05-07 17:51:20 +08:00
Merge branch 'eb/code-225' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#70)
This commit is contained in:
commit
1b04c8f98e
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/harness/gitness/gitrpc/enum"
|
"github.com/harness/gitness/gitrpc/enum"
|
||||||
"github.com/harness/gitness/gitrpc/internal/tempdir"
|
"github.com/harness/gitness/gitrpc/internal/tempdir"
|
||||||
"github.com/harness/gitness/gitrpc/internal/types"
|
"github.com/harness/gitness/gitrpc/internal/types"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
)
|
)
|
||||||
@ -175,7 +176,7 @@ func (g Adapter) CreateTemporaryRepoForPR(
|
|||||||
func runMergeCommand(
|
func runMergeCommand(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pr *types.PullRequest,
|
pr *types.PullRequest,
|
||||||
mergeMethod string,
|
mergeMethod enum.MergeMethod,
|
||||||
cmd *git.Command,
|
cmd *git.Command,
|
||||||
tmpBasePath string,
|
tmpBasePath string,
|
||||||
env []string,
|
env []string,
|
||||||
@ -254,6 +255,7 @@ func (g Adapter) Merge(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pr *types.PullRequest,
|
pr *types.PullRequest,
|
||||||
mergeMethod enum.MergeMethod,
|
mergeMethod enum.MergeMethod,
|
||||||
|
baseBranch string,
|
||||||
trackingBranch string,
|
trackingBranch string,
|
||||||
tmpBasePath string,
|
tmpBasePath string,
|
||||||
mergeMsg string,
|
mergeMsg string,
|
||||||
@ -268,13 +270,14 @@ func (g Adapter) Merge(
|
|||||||
mergeMsg = "Merge commit"
|
mergeMsg = "Merge commit"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stagingBranch := "staging"
|
||||||
// TODO: sign merge commit
|
// TODO: sign merge commit
|
||||||
signArg := "--no-gpg-sign"
|
signArg := "--no-gpg-sign"
|
||||||
|
|
||||||
switch mergeMethod {
|
switch mergeMethod {
|
||||||
case enum.MergeMethodMerge:
|
case enum.MergeMethodMerge:
|
||||||
cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit", trackingBranch)
|
cmd := git.NewCommand(ctx, "merge", "--no-ff", "--no-commit", trackingBranch)
|
||||||
if err := runMergeCommand(ctx, pr, string(mergeMethod), cmd, tmpBasePath, env); err != nil {
|
if err := runMergeCommand(ctx, pr, mergeMethod, cmd, tmpBasePath, env); err != nil {
|
||||||
return fmt.Errorf("unable to merge tracking into base: %w", err)
|
return fmt.Errorf("unable to merge tracking into base: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +287,7 @@ func (g Adapter) Merge(
|
|||||||
case enum.MergeMethodSquash:
|
case enum.MergeMethodSquash:
|
||||||
// Merge with squash
|
// Merge with squash
|
||||||
cmd := git.NewCommand(ctx, "merge", "--squash", trackingBranch)
|
cmd := git.NewCommand(ctx, "merge", "--squash", trackingBranch)
|
||||||
if err := runMergeCommand(ctx, pr, string(mergeMethod), cmd, tmpBasePath, env); err != nil {
|
if err := runMergeCommand(ctx, pr, mergeMethod, cmd, tmpBasePath, env); err != nil {
|
||||||
return fmt.Errorf("unable to merge --squash tracking into base: %v", err)
|
return fmt.Errorf("unable to merge --squash tracking into base: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +314,79 @@ func (g Adapter) Merge(
|
|||||||
pr.HeadBranch, pr.BaseBranch, outbuf.String(), errbuf.String())
|
pr.HeadBranch, pr.BaseBranch, outbuf.String(), errbuf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case enum.MergeMethodRebase:
|
||||||
|
// Checkout head branch
|
||||||
|
if err := git.NewCommand(ctx, "checkout", "-b", stagingBranch, trackingBranch).
|
||||||
|
Run(&git.RunOpts{
|
||||||
|
Dir: tmpBasePath,
|
||||||
|
Stdout: &outbuf,
|
||||||
|
Stderr: &errbuf,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("git checkout base prior to merge post staging rebase [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
}
|
||||||
|
outbuf.Reset()
|
||||||
|
errbuf.Reset()
|
||||||
|
|
||||||
|
// Rebase before merging
|
||||||
|
if err := git.NewCommand(ctx, "rebase", baseBranch).
|
||||||
|
Run(&git.RunOpts{
|
||||||
|
Dir: tmpBasePath,
|
||||||
|
Stdout: &outbuf,
|
||||||
|
Stderr: &errbuf,
|
||||||
|
}); err != nil {
|
||||||
|
// Rebase will leave a REBASE_HEAD file in .git if there is a conflict
|
||||||
|
if _, statErr := os.Stat(filepath.Join(tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil {
|
||||||
|
var commitSha string
|
||||||
|
// TBD git version we will support
|
||||||
|
// failingCommitPath := filepath.Join(tmpBasePath, ".git", "rebase-apply", "original-commit") // Git < 2.26
|
||||||
|
// if _, statErr := os.Stat(failingCommitPath); statErr != nil {
|
||||||
|
// return fmt.Errorf("git rebase staging on to base [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
// }
|
||||||
|
|
||||||
|
failingCommitPath := filepath.Join(tmpBasePath, ".git", "rebase-merge", "stopped-sha") // Git >= 2.26
|
||||||
|
if _, statErr := os.Stat(failingCommitPath); statErr != nil {
|
||||||
|
return fmt.Errorf("git rebase staging on to base [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
commitShaBytes, readErr := os.ReadFile(failingCommitPath)
|
||||||
|
if readErr != nil {
|
||||||
|
// Abandon this attempt to handle the error
|
||||||
|
return fmt.Errorf("git rebase staging on to base [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
}
|
||||||
|
commitSha = strings.TrimSpace(string(commitShaBytes))
|
||||||
|
|
||||||
|
log.Debug().Msgf("RebaseConflict at %s [%s -> %s]: %v\n%s\n%s", commitSha, pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
return &types.MergeConflictsError{
|
||||||
|
Method: mergeMethod,
|
||||||
|
CommitSHA: commitSha,
|
||||||
|
StdOut: outbuf.String(),
|
||||||
|
StdErr: errbuf.String(),
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmt.Errorf("git rebase staging on to base [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
}
|
||||||
|
outbuf.Reset()
|
||||||
|
errbuf.Reset()
|
||||||
|
|
||||||
|
// Checkout base branch again
|
||||||
|
if err := git.NewCommand(ctx, "checkout", baseBranch).
|
||||||
|
Run(&git.RunOpts{
|
||||||
|
Dir: tmpBasePath,
|
||||||
|
Stdout: &outbuf,
|
||||||
|
Stderr: &errbuf,
|
||||||
|
}); err != nil {
|
||||||
|
return fmt.Errorf("git checkout base prior to merge post staging rebase [%s -> %s]: %v\n%s\n%s", pr.HeadBranch, pr.BaseBranch, err, outbuf.String(), errbuf.String())
|
||||||
|
}
|
||||||
|
outbuf.Reset()
|
||||||
|
errbuf.Reset()
|
||||||
|
|
||||||
|
cmd := git.NewCommand(ctx, "merge", "--ff-only", stagingBranch)
|
||||||
|
|
||||||
|
// Prepare merge with commit
|
||||||
|
if err := runMergeCommand(ctx, pr, mergeMethod, cmd, tmpBasePath, env); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("wrong merge method provided: %s", mergeMethod)
|
return fmt.Errorf("wrong merge method provided: %s", mergeMethod)
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ type GitAdapter interface {
|
|||||||
GetRefPath(refName string, refType enum.RefType) (string, error)
|
GetRefPath(refName string, refType enum.RefType) (string, error)
|
||||||
UpdateRef(ctx context.Context, repoPath, refName string, refType enum.RefType, newValue, oldValue string) error
|
UpdateRef(ctx context.Context, repoPath, refName string, refType enum.RefType, newValue, oldValue string) error
|
||||||
CreateTemporaryRepoForPR(ctx context.Context, reposTempPath string, pr *types.PullRequest) (string, error)
|
CreateTemporaryRepoForPR(ctx context.Context, reposTempPath string, pr *types.PullRequest) (string, error)
|
||||||
Merge(ctx context.Context, pr *types.PullRequest, mergeMethod enum.MergeMethod, trackingBranch string,
|
Merge(ctx context.Context, pr *types.PullRequest, mergeMethod enum.MergeMethod, baseBranch, trackingBranch string,
|
||||||
tmpBasePath string, mergeMsg string, env []string, identity *types.Identity) error
|
tmpBasePath string, mergeMsg string, env []string, identity *types.Identity) error
|
||||||
GetMergeBase(ctx context.Context, repoPath, remote, base, head string) (string, string, error)
|
GetMergeBase(ctx context.Context, repoPath, remote, base, head string) (string, string, error)
|
||||||
GetDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) (string, error)
|
GetDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string) (string, error)
|
||||||
|
@ -169,10 +169,19 @@ func (s MergeService) Merge(
|
|||||||
mergeMsg += "\n\n" + strings.TrimSpace(request.Message)
|
mergeMsg += "\n\n" + strings.TrimSpace(request.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = s.adapter.Merge(ctx, pr, enum.MergeMethodFromRPC(request.Method), trackingBranch, tmpBasePath, mergeMsg, env, &types.Identity{
|
if err = s.adapter.Merge(
|
||||||
Name: author.Name,
|
ctx,
|
||||||
Email: author.Email,
|
pr,
|
||||||
}); err != nil {
|
enum.MergeMethodFromRPC(request.Method),
|
||||||
|
baseBranch,
|
||||||
|
trackingBranch,
|
||||||
|
tmpBasePath,
|
||||||
|
mergeMsg,
|
||||||
|
env,
|
||||||
|
&types.Identity{
|
||||||
|
Name: author.Name,
|
||||||
|
Email: author.Email,
|
||||||
|
}); err != nil {
|
||||||
return nil, processGitErrorf(err, "merge failed")
|
return nil, processGitErrorf(err, "merge failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ package types
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/gitrpc/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -29,10 +31,11 @@ var (
|
|||||||
|
|
||||||
// MergeConflictsError represents an error if merging fails with a conflict.
|
// MergeConflictsError represents an error if merging fails with a conflict.
|
||||||
type MergeConflictsError struct {
|
type MergeConflictsError struct {
|
||||||
Method string
|
Method enum.MergeMethod
|
||||||
StdOut string
|
CommitSHA string
|
||||||
StdErr string
|
StdOut string
|
||||||
Err error
|
StdErr string
|
||||||
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsMergeConflictsError(err error) bool {
|
func IsMergeConflictsError(err error) bool {
|
||||||
@ -55,7 +58,7 @@ func (e *MergeConflictsError) Is(target error) bool {
|
|||||||
|
|
||||||
// MergeUnrelatedHistoriesError represents an error if merging fails due to unrelated histories.
|
// MergeUnrelatedHistoriesError represents an error if merging fails due to unrelated histories.
|
||||||
type MergeUnrelatedHistoriesError struct {
|
type MergeUnrelatedHistoriesError struct {
|
||||||
Method string
|
Method enum.MergeMethod
|
||||||
StdOut string
|
StdOut string
|
||||||
StdErr string
|
StdErr string
|
||||||
Err error
|
Err error
|
||||||
|
@ -88,7 +88,7 @@ export const PullRequestActionsBox: React.FC<PullRequestActionsBoxProps> = ({
|
|||||||
method: 'rebase',
|
method: 'rebase',
|
||||||
title: getString('pr.mergeOptions.rebaseAndMerge'),
|
title: getString('pr.mergeOptions.rebaseAndMerge'),
|
||||||
desc: getString('pr.mergeOptions.rebaseAndMergeDesc'),
|
desc: getString('pr.mergeOptions.rebaseAndMergeDesc'),
|
||||||
disabled: true
|
disabled: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
method: 'close',
|
method: 'close',
|
||||||
|
Loading…
Reference in New Issue
Block a user