Skip to content

Commit

Permalink
Merge branch 'main' into feature/issue_22890
Browse files Browse the repository at this point in the history
  • Loading branch information
jolheiser authored Mar 9, 2023
2 parents 031f83e + e6df743 commit 29283b1
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 152 deletions.
2 changes: 1 addition & 1 deletion modules/git/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
}

// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
// In most cases, it shouldn't be used. Use AddXxx function instead
// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead
func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
ret := make(TrustedCmdArgs, len(args))
for i, arg := range args {
Expand Down
13 changes: 13 additions & 0 deletions modules/git/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,19 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
return false, err
}

// IsForcePush returns true if a push from oldCommitHash to this is a force push
func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
if oldCommitID == EmptySHA {
return false, nil
}
oldCommit, err := c.repo.GetCommit(oldCommitID)
if err != nil {
return false, err
}
hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID)
return !hasPreviousCommit, err
}

// CommitsBeforeLimit returns num commits before current revision
func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) {
return c.repo.getCommitsBeforeLimit(c.ID, num)
Expand Down
21 changes: 21 additions & 0 deletions modules/git/repo_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,27 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
}

// CommitsBetweenNotBase returns a list that contains commits between [before, last), excluding commits in baseBranch.
// If before is detached (removed by reset + push) it is not included.
func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch string) ([]*Commit, error) {
var stdout []byte
var err error
if before == nil {
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
} else {
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
if err != nil && strings.Contains(err.Error(), "no merge base") {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
}
}
if err != nil {
return nil, err
}
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
}

// CommitsBetweenIDs return commits between twoe commits
func (repo *Repository) CommitsBetweenIDs(last, before string) ([]*Commit, error) {
lastCommit, err := repo.GetCommit(last)
Expand Down
18 changes: 0 additions & 18 deletions modules/repository/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
package repository

import (
"context"
"strings"

repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
)

Expand Down Expand Up @@ -96,19 +94,3 @@ func (opts *PushUpdateOptions) RefName() string {
func (opts *PushUpdateOptions) RepoFullName() string {
return opts.RepoUserName + "/" + opts.RepoName
}

// IsForcePush detect if a push is a force push
func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) {
if !opts.IsUpdateBranch() {
return false, nil
}

output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID).
RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)})
if err != nil {
return false, err
} else if len(output) > 0 {
return true, nil
}
return false, nil
}
27 changes: 16 additions & 11 deletions routers/web/org/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ func Projects(ctx *context.Context) {
pager.AddParam(ctx, "state", "State")
ctx.Data["Page"] = pager

ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["IsShowClosed"] = isShowClosed
ctx.Data["PageIsViewProjects"] = true
ctx.Data["SortType"] = sortType

ctx.HTML(http.StatusOK, tplProjects)
}

func canWriteUnit(ctx *context.Context) bool {
func canWriteProjects(ctx *context.Context) bool {
if ctx.ContextUser.IsOrganization() {
return ctx.Org.CanWriteUnit(ctx, unit.TypeProjects)
}
Expand All @@ -122,7 +122,7 @@ func canWriteUnit(ctx *context.Context) bool {
func NewProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
shared_user.RenderUserHeader(ctx)
ctx.HTML(http.StatusOK, tplProjectsNew)
Expand All @@ -135,7 +135,7 @@ func NewProjectPost(ctx *context.Context) {
shared_user.RenderUserHeader(ctx)

if ctx.HasError() {
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["PageIsViewProjects"] = true
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
ctx.HTML(http.StatusOK, tplProjectsNew)
Expand Down Expand Up @@ -193,7 +193,7 @@ func DeleteProject(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
Expand All @@ -214,7 +214,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)

p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
Expand All @@ -226,13 +226,14 @@ func EditProject(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}

ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
ctx.Data["redirect"] = ctx.FormString("redirect")

ctx.HTML(http.StatusOK, tplProjectsNew)
}
Expand All @@ -243,7 +244,7 @@ func EditProjectPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)

if ctx.HasError() {
Expand All @@ -260,7 +261,7 @@ func EditProjectPost(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
Expand All @@ -273,7 +274,11 @@ func EditProjectPost(ctx *context.Context) {
}

ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
if ctx.FormString("redirect") == "project" {
ctx.Redirect(p.Link())
} else {
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects")
}
}

// ViewProject renders the project board for a project
Expand Down Expand Up @@ -332,7 +337,7 @@ func ViewProject(ctx *context.Context) {
project.RenderedContent = project.Description
ctx.Data["LinkedPRs"] = linkedPrsMap
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["Project"] = project
ctx.Data["IssuesMap"] = issuesMap
ctx.Data["Boards"] = boards
Expand Down
7 changes: 6 additions & 1 deletion routers/web/repo/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
ctx.Data["card_type"] = p.CardType
ctx.Data["redirect"] = ctx.FormString("redirect")

ctx.HTML(http.StatusOK, tplProjectsNew)
}
Expand Down Expand Up @@ -275,7 +276,11 @@ func EditProjectPost(ctx *context.Context) {
}

ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
if ctx.FormString("redirect") == "project" {
ctx.Redirect(p.Link())
} else {
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
}
}

// ViewProject renders the project board for a project
Expand Down
90 changes: 12 additions & 78 deletions services/pull/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,6 @@ import (
issue_service "code.gitea.io/gitea/services/issue"
)

type commitBranchCheckItem struct {
Commit *git.Commit
Checked bool
}

func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
if startCommit.ID.String() == endCommitID {
return nil
}

checkStack := make([]string, 0, 10)
checkStack = append(checkStack, startCommit.ID.String())

for len(checkStack) > 0 {
commitID := checkStack[0]
checkStack = checkStack[1:]

item, ok := commitList[commitID]
if !ok {
continue
}

if item.Commit.ID.String() == endCommitID {
continue
}

if err := item.Commit.LoadBranchName(); err != nil {
return err
}

if item.Commit.Branch == baseBranch {
continue
}

if item.Checked {
continue
}

item.Checked = true

parentNum := item.Commit.ParentCount()
for i := 0; i < parentNum; i++ {
parentCommit, err := item.Commit.Parent(i)
if err != nil {
return err
}
checkStack = append(checkStack, parentCommit.ID.String())
}
}
return nil
}

// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
Expand All @@ -82,47 +30,33 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC
return nil, false, err
}

if err = oldCommit.LoadBranchName(); err != nil {
return nil, false, err
}

if len(oldCommit.Branch) == 0 {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID

return commitIDs, true, err
}

newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return nil, false, err
}

commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
isForcePush, err = newCommit.IsForcePush(oldCommitID)
if err != nil {
return nil, false, err
}

commitIDs = make([]string, 0, len(commits))
commitChecks := make(map[string]*commitBranchCheckItem)
if isForcePush {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID

for _, commit := range commits {
commitChecks[commit.ID.String()] = &commitBranchCheckItem{
Commit: commit,
Checked: false,
}
return commitIDs, isForcePush, err
}

if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
return
// Find commits between new and old commit exclusing base branch commits
commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
if err != nil {
return nil, false, err
}

commitIDs = make([]string, 0, len(commits))
for i := len(commits) - 1; i >= 0; i-- {
commitID := commits[i].ID.String()
if item, ok := commitChecks[commitID]; ok && item.Checked {
commitIDs = append(commitIDs, commitID)
}
commitIDs = append(commitIDs, commits[i].ID.String())
}

return commitIDs, isForcePush, err
Expand Down
9 changes: 7 additions & 2 deletions services/pull/merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
}

func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
if err := git.NewCommand(ctx, "commit").AddArguments(ctx.signArg...).AddOptionFormat("--message=%s", message).
Run(ctx.RunOpts()); err != nil {
cmdCommit := git.NewCommand(ctx, "commit").AddOptionFormat("--message=%s", message)
if ctx.signKeyID == "" {
cmdCommit.AddArguments("--no-gpg-sign")
} else {
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
}
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
}
Expand Down
19 changes: 5 additions & 14 deletions services/pull/merge_prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type mergeContext struct {
doer *user_model.User
sig *git.Signature
committer *git.Signature
signArg git.TrustedCmdArgs
signKeyID string // empty for no-sign, non-empty to sign
env []string
}

Expand Down Expand Up @@ -85,12 +85,10 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
// Determine if we should sign
sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch)
if sign {
mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"-S" + keyID})
mergeCtx.signKeyID = keyID
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
mergeCtx.committer = signer
}
} else {
mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"--no-gpg-sign"})
}

commitTimeStr := time.Now().Format(time.RFC3339)
Expand Down Expand Up @@ -136,18 +134,11 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
return fmt.Errorf("Unable to close .git/info/sparse-checkout file in tmpBasePath: %w", err)
}

gitConfigCommand := func() *git.Command {
return git.NewCommand(ctx, "config", "--local")
}

setConfig := func(key, value string) error {
if err := gitConfigCommand().AddArguments(git.ToTrustedCmdArgs([]string{key, value})...).
if err := git.NewCommand(ctx, "config", "--local").AddDynamicArguments(key, value).
Run(ctx.RunOpts()); err != nil {
if value == "" {
value = "<>"
}
log.Error("git config [%s -> %s ]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git config [%s -> %s ]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
}
ctx.outbuf.Reset()
ctx.errbuf.Reset()
Expand Down
Loading

0 comments on commit 29283b1

Please sign in to comment.