2
1
forked from adamm/autogits

8 Commits

Author SHA256 Message Date
3d8671a7fe WIP: conflict resolution 2025-07-15 23:24:50 +02:00
c5db1c83a7 PR: detect and rebase project git commits
When project is advanced, and we have other package changes
to same project, the project git changes need to be rebased. The
simplest way of doing this is to skip all the submodule conflicts
and re-create them. This allows the submodules changes to be
mergeable again.
2025-07-15 19:08:05 +02:00
9f0909621b PR: fix timeline fetches
only fetch latest reviews from a user, not all
2025-07-15 11:06:17 +02:00
b3914b04bd Fix logic in crash protection
We must not access review.User object if it is nil
2025-07-11 12:02:37 +02:00
b43a19189e Enable code stream publishing 2025-07-11 12:02:08 +02:00
01b665230e message typo 2025-07-11 12:01:58 +02:00
1a07d4c541 Create Pull Requests to specified branches
instead of always using DefaultBranch. This means that target needs
always gets specified now.
2025-07-11 12:01:43 +02:00
22e44dff47 Don't fail on project git pull request creation. 2025-07-11 12:01:24 +02:00
10 changed files with 226 additions and 54 deletions

View File

@@ -769,6 +769,8 @@ func (e *GitHandlerImpl) GitSubmoduleList(gitPath, commitId string) (submoduleLi
done.Lock() done.Lock()
data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)} data_in, data_out := ChanIO{make(chan byte)}, ChanIO{make(chan byte)}
LogDebug("Getting submodules for:", commitId)
go func() { go func() {
defer done.Unlock() defer done.Unlock()
defer close(data_out.ch) defer close(data_out.ch)
@@ -916,6 +918,16 @@ type GitStatusData struct {
Path string Path string
Status int Status int
States [3]string States [3]string
/*
<sub> A 4 character field describing the submodule state.
"N..." when the entry is not a submodule.
"S<c><m><u>" when the entry is a submodule.
<c> is "C" if the commit changed; otherwise ".".
<m> is "M" if it has tracked changes; otherwise ".".
<u> is "U" if there are untracked changes; otherwise ".".
*/
SubmoduleChanges string
} }
func parseGitStatusHexString(data io.ByteReader) (string, error) { func parseGitStatusHexString(data io.ByteReader) (string, error) {
@@ -938,6 +950,20 @@ func parseGitStatusHexString(data io.ByteReader) (string, error) {
} }
} }
func parseGitStatusString(data io.ByteReader) (string, error) { func parseGitStatusString(data io.ByteReader) (string, error) {
str := make([]byte, 0, 100)
for {
c, err := data.ReadByte()
if err != nil {
return "", errors.New("Unexpected EOF. Expected NUL string term")
}
if c == 0 || c == ' ' {
return string(str), nil
}
str = append(str, c)
}
}
func parseGitStatusStringWithSpace(data io.ByteReader) (string, error) {
str := make([]byte, 0, 100) str := make([]byte, 0, 100)
for { for {
c, err := data.ReadByte() c, err := data.ReadByte()
@@ -978,7 +1004,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err return nil, err
} }
ret.Status = GitStatus_Modified ret.Status = GitStatus_Modified
ret.Path, err = parseGitStatusString(data) ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -988,11 +1014,11 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err return nil, err
} }
ret.Status = GitStatus_Renamed ret.Status = GitStatus_Renamed
ret.Path, err = parseGitStatusString(data) ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ret.States[0], err = parseGitStatusString(data) ret.States[0], err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1002,7 +1028,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err return nil, err
} }
ret.Status = GitStatus_Untracked ret.Status = GitStatus_Untracked
ret.Path, err = parseGitStatusString(data) ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -1012,15 +1038,22 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err return nil, err
} }
ret.Status = GitStatus_Ignored ret.Status = GitStatus_Ignored
ret.Path, err = parseGitStatusString(data) ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
case 'u': case 'u':
var err error var err error
if err = skipGitStatusEntry(data, 7); err != nil { if err = skipGitStatusEntry(data, 2); err != nil {
return nil, err return nil, err
} }
if ret.SubmoduleChanges, err = parseGitStatusString(data); err != nil {
return nil, err
}
if err = skipGitStatusEntry(data, 4); err != nil {
return nil, err
}
if ret.States[0], err = parseGitStatusHexString(data); err != nil { if ret.States[0], err = parseGitStatusHexString(data); err != nil {
return nil, err return nil, err
} }
@@ -1031,7 +1064,7 @@ func parseSingleStatusEntry(data io.ByteReader) (*GitStatusData, error) {
return nil, err return nil, err
} }
ret.Status = GitStatus_Unmerged ret.Status = GitStatus_Unmerged
ret.Path, err = parseGitStatusString(data) ret.Path, err = parseGitStatusStringWithSpace(data)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -555,6 +555,8 @@ func TestGitStatusParse(t *testing.T) {
Path: ".gitmodules", Path: ".gitmodules",
Status: GitStatus_Unmerged, Status: GitStatus_Unmerged,
States: [3]string{"587ec403f01113f2629da538f6e14b84781f70ac59c41aeedd978ea8b1253a76", "d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c", "087b1d5f22dbf0aa4a879fff27fff03568b334c90daa5f2653f4a7961e24ea33"}, States: [3]string{"587ec403f01113f2629da538f6e14b84781f70ac59c41aeedd978ea8b1253a76", "d23eb05d9ca92883ab9f4d28f3ec90c05f667f3a5c8c8e291bd65e03bac9ae3c", "087b1d5f22dbf0aa4a879fff27fff03568b334c90daa5f2653f4a7961e24ea33"},
SubmoduleChanges: "N...",
}, },
}, },
}, },

View File

@@ -603,14 +603,14 @@ func (gitea *GiteaTransport) CreateRepositoryIfNotExist(git Git, org, repoName s
func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) { func (gitea *GiteaTransport) CreatePullRequestIfNotExist(repo *models.Repository, srcId, targetId, title, body string) (*models.PullRequest, error) {
prOptions := models.CreatePullRequestOption{ prOptions := models.CreatePullRequestOption{
Base: repo.DefaultBranch, Base: targetId,
Head: srcId, Head: srcId,
Title: title, Title: title,
Body: body, Body: body,
} }
if pr, err := gitea.client.Repository.RepoGetPullRequestByBaseHead( if pr, err := gitea.client.Repository.RepoGetPullRequestByBaseHead(
repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(repo.DefaultBranch).WithHead(srcId), repository.NewRepoGetPullRequestByBaseHeadParams().WithOwner(repo.Owner.UserName).WithRepo(repo.Name).WithBase(targetId).WithHead(srcId),
gitea.transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
); err == nil { ); err == nil {
return pr.Payload, nil return pr.Payload, nil
@@ -718,20 +718,18 @@ func (gitea *GiteaTransport) AddComment(pr *models.PullRequest, comment string)
} }
func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error) { func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models.TimelineComment, error) {
limit := int64(20)
page := int64(1) page := int64(1)
resCount := limit resCount := 1
retData := []*models.TimelineComment{} retData := []*models.TimelineComment{}
for resCount == limit { for resCount > 0 {
res, err := gitea.client.Issue.IssueGetCommentsAndTimeline( res, err := gitea.client.Issue.IssueGetCommentsAndTimeline(
issue.NewIssueGetCommentsAndTimelineParams(). issue.NewIssueGetCommentsAndTimelineParams().
WithOwner(org). WithOwner(org).
WithRepo(repo). WithRepo(repo).
WithIndex(idx). WithIndex(idx).
WithPage(&page). WithPage(&page),
WithLimit(&limit),
gitea.transport.DefaultAuthentication, gitea.transport.DefaultAuthentication,
) )
@@ -739,11 +737,13 @@ func (gitea *GiteaTransport) GetTimeline(org, repo string, idx int64) ([]*models
return nil, err return nil, err
} }
resCount = int64(len(res.Payload)) resCount = len(res.Payload)
LogDebug("page:", page, "len:", resCount)
page++ page++
retData = append(retData, res.Payload...) retData = append(retData, res.Payload...)
} }
LogDebug("total results:", len(retData))
slices.SortFunc(retData, func(a, b *models.TimelineComment) int { slices.SortFunc(retData, func(a, b *models.TimelineComment) int {
return time.Time(b.Created).Compare(time.Time(a.Created)) return time.Time(b.Created).Compare(time.Time(a.Created))

View File

@@ -121,27 +121,28 @@ func FetchPRSet(user string, gitea GiteaPRTimelineFetcher, org, repo string, num
}, nil }, nil
} }
func (rs *PRSet) Contains(pr *models.PullRequest) bool { func (rs *PRSet) Find(pr *models.PullRequest) (*PRInfo, bool) {
for _, p := range rs.PRs { for _, p := range rs.PRs {
if p.PR.Base.RepoID == pr.Base.RepoID && if p.PR.Base.RepoID == pr.Base.RepoID &&
p.PR.Head.Sha == pr.Head.Sha && p.PR.Head.Sha == pr.Head.Sha &&
p.PR.Base.Name == pr.Base.Name { p.PR.Base.Name == pr.Base.Name {
return true return p, true
} }
} }
return false return nil, false
} }
func (rs *PRSet) AddPR(pr *models.PullRequest) error { func (rs *PRSet) AddPR(pr *models.PullRequest) *PRInfo {
if rs.Contains(pr) { if pr, found := rs.Find(pr); found {
return nil return pr
} }
rs.PRs = append(rs.PRs, &PRInfo{ prinfo := &PRInfo{
PR: pr, PR: pr,
}) }
return nil rs.PRs = append(rs.PRs, prinfo)
return prinfo
} }
func (rs *PRSet) IsPrjGitPR(pr *models.PullRequest) bool { func (rs *PRSet) IsPrjGitPR(pr *models.PullRequest) bool {
@@ -172,6 +173,15 @@ func (rs *PRSet) GetPrjGitPR() (*PRInfo, error) {
return nil, PRSet_PrjGitMissing return nil, PRSet_PrjGitMissing
} }
func (rs *PRSet) NeedRecreatingPrjGit(currentBranchHash string) bool {
pr, err := rs.GetPrjGitPR()
if err != nil {
return true
}
return pr.PR.Base.Sha == currentBranchHash
}
func (rs *PRSet) IsConsistent() bool { func (rs *PRSet) IsConsistent() bool {
prjpr_info, err := rs.GetPrjGitPR() prjpr_info, err := rs.GetPrjGitPR()
if err != nil { if err != nil {
@@ -302,7 +312,7 @@ func (rs *PRSet) IsApproved(gitea GiteaPRChecker, maintainers MaintainershipData
} }
pr.Reviews = r pr.Reviews = r
if !pr.Reviews.IsManualMergeOK() { if !pr.Reviews.IsManualMergeOK() {
LogInfo("Not approved manual merge") LogInfo("Not approved manual merge. PR:", pr.PR.URL)
return false return false
} }
} }

View File

@@ -0,0 +1,48 @@
package common
import (
"errors"
"strings"
)
var UnknownParser error = errors.New("Cannot parse path")
type PRConflictResolver interface {
/*
stage_content -> { merge_base (stage1), head (stage2), merge_head (stage3) }
*/
Resolve(path string, stage_contents [3]string) error
}
var resolvers []PRConflictResolver = []PRConflictResolver{
&submodule_conflict_resolver{},
}
func ResolveMergeConflict(path string, file_contents [3]string) error {
for _, r := range resolvers {
if err := r.Resolve(path, file_contents); err != UnknownParser {
return err
}
}
return UnknownParser
}
type submodule_conflict_resolver struct{}
func (*submodule_conflict_resolver) Resolve(path string, stage [3]string) error {
if path != ".gitmodules" {
return UnknownParser
}
return UnknownParser
}
type changes_file_resolver struct{}
func (*changes_file_resolver) Resolve(path string, stage [3]string) error {
if !strings.HasSuffix(path, ".changes") {
return UnknownParser
}
return UnknownParser
}

View File

@@ -0,0 +1,10 @@
package common_test
import "testing"
func ResolveSubmoduleConflicts(t *testing.T) {
}
func ResolveChangesFileConflict(t *testing.T) {
}

View File

@@ -15,7 +15,23 @@ import (
"src.opensuse.org/autogits/common/gitea-generated/models" "src.opensuse.org/autogits/common/gitea-generated/models"
mock_common "src.opensuse.org/autogits/common/mock" mock_common "src.opensuse.org/autogits/common/mock"
) )
/*
func TestCockpit(t *testing.T) {
common.SetLoggingLevel(common.LogLevelDebug)
gitea := common.AllocateGiteaTransport("https://src.opensuse.org")
tl, err := gitea.GetTimeline("cockpit", "cockpit", 29)
if err != nil {
t.Fatal("Fail to timeline", err)
}
t.Log(tl)
r, err := common.FetchGiteaReviews(gitea, []string{}, "cockpit", "cockpit", 29)
if err != nil {
t.Fatal("Error:", err)
}
t.Error(r)
}
*/
func reviewsToTimeline(reviews []*models.PullReview) []*models.TimelineComment { func reviewsToTimeline(reviews []*models.PullReview) []*models.TimelineComment {
timeline := make([]*models.TimelineComment, len(reviews)) timeline := make([]*models.TimelineComment, len(reviews))
for idx, review := range reviews { for idx, review := range reviews {

View File

@@ -25,26 +25,39 @@ func FetchGiteaReviews(rf GiteaReviewTimelineFetcher, reviewers []string, org, r
return nil, err return nil, err
} }
reviews := make([]*models.PullReview, 0, 10) reviews := make([]*models.PullReview, 0, len(reviewers))
var comments []*models.TimelineComment var comments []*models.TimelineComment
alreadyHaveUserReview := func(user string) bool {
for _, r := range reviews {
if r.User != nil && r.User.UserName == user {
return true
}
}
return false
}
for idx, item := range timeline { for idx, item := range timeline {
if item.Type == TimelineCommentType_Review { if item.Type == TimelineCommentType_Review {
for _, r := range rawReviews { for _, r := range rawReviews {
if r.ID == item.ReviewID { if r.ID == item.ReviewID {
reviews = append(reviews, r) if !alreadyHaveUserReview(r.User.UserName) {
reviews = append(reviews, r)
}
break break
} }
} }
} else if item.Type == TimelineCommentType_Comment { } else if item.Type == TimelineCommentType_Comment {
comments = append(comments, item) comments = append(comments, item)
} else if item.Type == TimelineCommentType_PushPull { } else if item.Type == TimelineCommentType_PushPull {
LogDebug("cut-off", item.Created)
timeline = timeline[0:idx] timeline = timeline[0:idx]
break break
} else { } else {
LogDebug("Unhandled timeline type:", item.Type) LogDebug("Unhandled timeline type:", item.Type)
} }
} }
LogDebug("num comments:", len(comments), "reviews:", len(reviews), len(timeline))
return &PRReviews{ return &PRReviews{
reviews: reviews, reviews: reviews,
@@ -72,6 +85,7 @@ func (r *PRReviews) IsManualMergeOK() bool {
if c.Updated != c.Created { if c.Updated != c.Created {
continue continue
} }
LogDebug("comment:", c.User.UserName, c.Body)
if slices.Contains(r.reviewers, c.User.UserName) { if slices.Contains(r.reviewers, c.User.UserName) {
if bodyCommandManualMergeOK(c.Body) { if bodyCommandManualMergeOK(c.Body) {
return true return true

View File

@@ -315,7 +315,9 @@ func GenerateObsPrjMeta(git common.Git, gitea common.Gitea, pr *models.PullReque
} }
meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha meta.ScmSync = pr.Head.Repo.CloneURL + "?" + strings.Join(urlPkg, "&") + "#" + pr.Head.Sha
meta.Title = fmt.Sprintf("PR#%d to %s", pr.Index, pr.Base.Name) meta.Title = fmt.Sprintf("PR#%d to %s", pr.Index, pr.Base.Name)
meta.PublicFlags = common.Flags{Contents: "<disable/>"} // QE wants it published ... also we should not hardcode it here, since
// it is configurable via the :PullRequest project
// meta.PublicFlags = common.Flags{Contents: "<disable/>"}
meta.Groups = nil meta.Groups = nil
meta.Persons = nil meta.Persons = nil
@@ -459,7 +461,7 @@ func FetchOurLatestActionableReview(gitea common.Gitea, org, repo string, id int
for idx := len(reviews) - 1; idx >= 0; idx-- { for idx := len(reviews) - 1; idx >= 0; idx-- {
review := reviews[idx] review := reviews[idx]
if review.User != nil || review.User.UserName == Username { if review.User == nil || review.User.UserName == Username {
if IsDryRun { if IsDryRun {
// for purposes of moving forward a no-op check // for purposes of moving forward a no-op check
return review, nil return review, nil
@@ -547,7 +549,7 @@ func CleanupPullNotification(gitea common.Gitea, thread *models.NotificationThre
} }
if pr.State != "closed" { if pr.State != "closed" {
common.LogInfo(" ignoring peding PR", thread.Subject.HTMLURL, " state:", pr.State) common.LogInfo(" ignoring pending PR", thread.Subject.HTMLURL, " state:", pr.State)
return false return false
} }

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"path" "path"
"runtime/debug" "runtime/debug"
"slices"
"strings" "strings"
"github.com/opentracing/opentracing-go/log" "github.com/opentracing/opentracing-go/log"
@@ -80,6 +81,9 @@ func AllocatePRProcessor(req *common.PullRequestWebhookEvent, configs common.Aut
} }
common.LogDebug("git path:", git.GetPath()) common.LogDebug("git path:", git.GetPath())
// git.GitExecOrPanic("", "config", "set", "--global", "advice.submoduleMergeConflict", "false")
// git.GitExecOrPanic("", "config", "set", "--global", "advice.mergeConflict", "false")
return &PRProcessor{ return &PRProcessor{
config: config, config: config,
git: git, git: git,
@@ -87,11 +91,6 @@ func AllocatePRProcessor(req *common.PullRequestWebhookEvent, configs common.Aut
} }
func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) ([]string, []string, error) { func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) ([]string, []string, error) {
prjGitPR, err := prset.GetPrjGitPR()
if err != nil {
return nil, nil, err
}
git := pr.git git := pr.git
subList, err := git.GitSubmoduleList(common.DefaultGitPrj, "HEAD") subList, err := git.GitSubmoduleList(common.DefaultGitPrj, "HEAD")
if err != nil { if err != nil {
@@ -113,13 +112,15 @@ func (pr *PRProcessor) SetSubmodulesToMatchPRSet(prset *common.PRSet) ([]string,
revert := false revert := false
if pr.PR.State != "open" { if pr.PR.State != "open" {
// remove PR from PrjGit prjGitPR, err := prset.GetPrjGitPR()
var valid bool if prjGitPR != nil {
if prHead, valid = git.GitSubmoduleCommitId(common.DefaultGitPrj, repo, prjGitPR.PR.MergeBase); !valid { // remove PR from PrjGit
common.LogError("Failed fetching original submodule commit id for repo") var valid bool
return nil, nil, err if prHead, valid = git.GitSubmoduleCommitId(common.DefaultGitPrj, repo, prjGitPR.PR.MergeBase); !valid {
common.LogError("Failed fetching original submodule commit id for repo")
return nil, nil, err
}
} }
revert = true revert = true
} }
@@ -166,9 +167,9 @@ func (pr *PRProcessor) CreatePRjGitPR(prjGitPRbranch string, prset *common.PRSet
common.LogError("Failed to fetch PrjGit repository data.", PrjGitOrg, PrjGitRepo, err) common.LogError("Failed to fetch PrjGit repository data.", PrjGitOrg, PrjGitRepo, err)
return err return err
} }
remoteName, err := git.GitClone(common.DefaultGitPrj, PrjGitBranch, PrjGit.SSHURL) RemoteName, err := git.GitClone(common.DefaultGitPrj, PrjGitBranch, PrjGit.SSHURL)
common.PanicOnError(err) common.PanicOnError(err)
git.GitExecOrPanic(common.DefaultGitPrj, "checkout", "-B", prjGitPRbranch, remoteName+"/"+PrjGitBranch) git.GitExecOrPanic(common.DefaultGitPrj, "checkout", "-B", prjGitPRbranch, RemoteName+"/"+PrjGitBranch)
headCommit, err := git.GitBranchHead(common.DefaultGitPrj, prjGitPRbranch) headCommit, err := git.GitBranchHead(common.DefaultGitPrj, prjGitPRbranch)
if err != nil { if err != nil {
@@ -186,7 +187,7 @@ func (pr *PRProcessor) CreatePRjGitPR(prjGitPRbranch string, prset *common.PRSet
} }
if !common.IsDryRun && headCommit != newHeadCommit { if !common.IsDryRun && headCommit != newHeadCommit {
common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push", remoteName, "+HEAD:"+prjGitPRbranch)) common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push", RemoteName, "+HEAD:"+prjGitPRbranch))
pr, err := Gitea.CreatePullRequestIfNotExist(PrjGit, prjGitPRbranch, PrjGitBranch, pr, err := Gitea.CreatePullRequestIfNotExist(PrjGit, prjGitPRbranch, PrjGitBranch,
"Forwarded PRs: "+strings.Join(title_refs, ", "), "Forwarded PRs: "+strings.Join(title_refs, ", "),
fmt.Sprintf("This is a forwarded pull request by %s\nreferencing the following pull request(s):\n\n", GitAuthor)+strings.Join(refs, ", "), fmt.Sprintf("This is a forwarded pull request by %s\nreferencing the following pull request(s):\n\n", GitAuthor)+strings.Join(refs, ", "),
@@ -199,12 +200,40 @@ func (pr *PRProcessor) CreatePRjGitPR(prjGitPRbranch string, prset *common.PRSet
RemoveDeadline: true, RemoveDeadline: true,
}) })
prset.AddPR(pr) prinfo := prset.AddPR(pr)
prinfo.RemoteName = RemoteName
} }
return nil return nil
} }
func (pr *PRProcessor) RebaseAndSkipSubmoduleCommits(prset *common.PRSet, branch string) error {
git := pr.git
PrjGitPR, err := prset.GetPrjGitPR()
common.PanicOnError(err)
remoteBranch := PrjGitPR.RemoteName + "/" + branch
common.LogDebug("Rebasing on top of", remoteBranch)
for conflict := git.GitExec(common.DefaultGitPrj, "rebase", remoteBranch); conflict != nil; {
statuses, err := git.GitStatus(common.DefaultGitPrj)
if err != nil {
git.GitExecOrPanic(common.DefaultGitPrj, "rebase", "--abort")
common.PanicOnError(err)
}
for _, s := range statuses {
if s.SubmoduleChanges != "S..." {
git.GitExecOrPanic(common.DefaultGitPrj, "rebase", "--abort")
return fmt.Errorf("Unexpected conflict in rebase. %s", s)
}
}
conflict = git.GitExec(common.DefaultGitPrj, "rebase", "--skip")
}
return nil
}
func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error { func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error {
_, _, PrjGitBranch := prset.Config.GetPrjGit()
PrjGitPR, err := prset.GetPrjGitPR() PrjGitPR, err := prset.GetPrjGitPR()
if err != nil { if err != nil {
common.LogError("Updating PrjGitPR but not found?", err) common.LogError("Updating PrjGitPR but not found?", err)
@@ -215,8 +244,16 @@ func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error {
PrjGit := PrjGitPR.PR.Base.Repo PrjGit := PrjGitPR.PR.Base.Repo
prjGitPRbranch := PrjGitPR.PR.Head.Name prjGitPRbranch := PrjGitPR.PR.Head.Name
remoteName, err := git.GitClone(common.DefaultGitPrj, prjGitPRbranch, PrjGit.SSHURL) PrjGitPR.RemoteName, err = git.GitClone(common.DefaultGitPrj, prjGitPRbranch, PrjGit.SSHURL)
common.PanicOnError(err) common.PanicOnError(err)
git.GitExecOrPanic(common.DefaultGitPrj, "fetch", PrjGitPR.RemoteName, PrjGitBranch)
ExpectedMergeCommit, err := git.GitRemoteHead(common.DefaultGitPrj, PrjGitPR.RemoteName, PrjGitBranch)
forcePush := false
if ExpectedMergeCommit != PrjGitPR.PR.MergeBase {
common.PanicOnError(pr.RebaseAndSkipSubmoduleCommits(prset, PrjGitBranch))
forcePush = true
}
headCommit, err := git.GitBranchHead(common.DefaultGitPrj, prjGitPRbranch) headCommit, err := git.GitBranchHead(common.DefaultGitPrj, prjGitPRbranch)
if err != nil { if err != nil {
@@ -234,7 +271,11 @@ func (pr *PRProcessor) UpdatePrjGitPR(prset *common.PRSet) error {
} }
if !common.IsDryRun && headCommit != newHeadCommit { if !common.IsDryRun && headCommit != newHeadCommit {
common.PanicOnError(git.GitExec(common.DefaultGitPrj, "push", remoteName, "+HEAD:"+prjGitPRbranch)) params := []string{"push", PrjGitPR.RemoteName, "+HEAD:" + prjGitPRbranch}
if forcePush {
params = slices.Insert(params, 1, "-f")
}
common.PanicOnError(git.GitExec(common.DefaultGitPrj, params...))
// update PR // update PR
PrjGitTitle := "Forwarded PRs: " + strings.Join(title_refs, ", ") PrjGitTitle := "Forwarded PRs: " + strings.Join(title_refs, ", ")
@@ -314,13 +355,10 @@ func (pr *PRProcessor) Process(req *common.PullRequestWebhookEvent) error {
// make sure that prjgit is consistent and only submodules that are to be *updated* // make sure that prjgit is consistent and only submodules that are to be *updated*
// reset anything that changed that is not part of the prset // reset anything that changed that is not part of the prset
// package removals/additions are *not* counted here // package removals/additions are *not* counted here
org, repo, branch := config.GetPrjGit()
if pr, err := prset.GetPrjGitPR(); err == nil { if pr, err := prset.GetPrjGitPR(); err == nil {
remote, err := git.GitClone(common.DefaultGitPrj, prjGitPRbranch, pr.PR.Base.Repo.CloneURL) common.LogDebug("Submodule parse begin")
common.PanicOnError(err) orig_subs, err := git.GitSubmoduleList(common.DefaultGitPrj, pr.RemoteName+"/"+branch) // merge base must remote branch, checked in prjgit udate
git.GitExecOrPanic(common.DefaultGitPrj, "fetch", remote, pr.PR.MergeBase, pr.PR.Head.Ref)
common.LogDebug("Fetch done")
orig_subs, err := git.GitSubmoduleList(common.DefaultGitPrj, pr.PR.MergeBase)
common.PanicOnError(err) common.PanicOnError(err)
new_subs, err := git.GitSubmoduleList(common.DefaultGitPrj, pr.PR.Head.Sha) new_subs, err := git.GitSubmoduleList(common.DefaultGitPrj, pr.PR.Head.Sha)
common.PanicOnError(err) common.PanicOnError(err)
@@ -357,7 +395,6 @@ func (pr *PRProcessor) Process(req *common.PullRequestWebhookEvent) error {
} }
common.LogDebug(" num of reviewers:", len(prjGitPR.PR.RequestedReviewers)) common.LogDebug(" num of reviewers:", len(prjGitPR.PR.RequestedReviewers))
org, repo, branch := config.GetPrjGit()
maintainers, err := common.FetchProjectMaintainershipData(Gitea, org, repo, branch) maintainers, err := common.FetchProjectMaintainershipData(Gitea, org, repo, branch)
if err != nil { if err != nil {
return err return err