Skip to content

Commit 29283b1

Browse files
authored
Merge branch 'main' into feature/issue_22890
2 parents 031f83e + e6df743 commit 29283b1

File tree

15 files changed

+104
-152
lines changed

15 files changed

+104
-152
lines changed

modules/git/command.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
179179
}
180180

181181
// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
182-
// In most cases, it shouldn't be used. Use AddXxx function instead
182+
// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead
183183
func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
184184
ret := make(TrustedCmdArgs, len(args))
185185
for i, arg := range args {

modules/git/commit.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,19 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
218218
return false, err
219219
}
220220

221+
// IsForcePush returns true if a push from oldCommitHash to this is a force push
222+
func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
223+
if oldCommitID == EmptySHA {
224+
return false, nil
225+
}
226+
oldCommit, err := c.repo.GetCommit(oldCommitID)
227+
if err != nil {
228+
return false, err
229+
}
230+
hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID)
231+
return !hasPreviousCommit, err
232+
}
233+
221234
// CommitsBeforeLimit returns num commits before current revision
222235
func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) {
223236
return c.repo.getCommitsBeforeLimit(c.ID, num)

modules/git/repo_commit.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,27 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
323323
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
324324
}
325325

326+
// CommitsBetweenNotBase returns a list that contains commits between [before, last), excluding commits in baseBranch.
327+
// If before is detached (removed by reset + push) it is not included.
328+
func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch string) ([]*Commit, error) {
329+
var stdout []byte
330+
var err error
331+
if before == nil {
332+
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
333+
} else {
334+
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
335+
if err != nil && strings.Contains(err.Error(), "no merge base") {
336+
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
337+
// previously it would return the results of git rev-list before last so let's try that...
338+
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
339+
}
340+
}
341+
if err != nil {
342+
return nil, err
343+
}
344+
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
345+
}
346+
326347
// CommitsBetweenIDs return commits between twoe commits
327348
func (repo *Repository) CommitsBetweenIDs(last, before string) ([]*Commit, error) {
328349
lastCommit, err := repo.GetCommit(last)

modules/repository/push.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
package repository
55

66
import (
7-
"context"
87
"strings"
98

10-
repo_model "code.gitea.io/gitea/models/repo"
119
"code.gitea.io/gitea/modules/git"
1210
)
1311

@@ -96,19 +94,3 @@ func (opts *PushUpdateOptions) RefName() string {
9694
func (opts *PushUpdateOptions) RepoFullName() string {
9795
return opts.RepoUserName + "/" + opts.RepoName
9896
}
99-
100-
// IsForcePush detect if a push is a force push
101-
func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) {
102-
if !opts.IsUpdateBranch() {
103-
return false, nil
104-
}
105-
106-
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID).
107-
RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)})
108-
if err != nil {
109-
return false, err
110-
} else if len(output) > 0 {
111-
return true, nil
112-
}
113-
return false, nil
114-
}

routers/web/org/projects.go

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,15 @@ func Projects(ctx *context.Context) {
103103
pager.AddParam(ctx, "state", "State")
104104
ctx.Data["Page"] = pager
105105

106-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
106+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
107107
ctx.Data["IsShowClosed"] = isShowClosed
108108
ctx.Data["PageIsViewProjects"] = true
109109
ctx.Data["SortType"] = sortType
110110

111111
ctx.HTML(http.StatusOK, tplProjects)
112112
}
113113

114-
func canWriteUnit(ctx *context.Context) bool {
114+
func canWriteProjects(ctx *context.Context) bool {
115115
if ctx.ContextUser.IsOrganization() {
116116
return ctx.Org.CanWriteUnit(ctx, unit.TypeProjects)
117117
}
@@ -122,7 +122,7 @@ func canWriteUnit(ctx *context.Context) bool {
122122
func NewProject(ctx *context.Context) {
123123
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
124124
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
125-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
125+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
126126
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
127127
shared_user.RenderUserHeader(ctx)
128128
ctx.HTML(http.StatusOK, tplProjectsNew)
@@ -135,7 +135,7 @@ func NewProjectPost(ctx *context.Context) {
135135
shared_user.RenderUserHeader(ctx)
136136

137137
if ctx.HasError() {
138-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
138+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
139139
ctx.Data["PageIsViewProjects"] = true
140140
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
141141
ctx.HTML(http.StatusOK, tplProjectsNew)
@@ -193,7 +193,7 @@ func DeleteProject(ctx *context.Context) {
193193
}
194194
return
195195
}
196-
if p.RepoID != ctx.Repo.Repository.ID {
196+
if p.OwnerID != ctx.ContextUser.ID {
197197
ctx.NotFound("", nil)
198198
return
199199
}
@@ -214,7 +214,7 @@ func EditProject(ctx *context.Context) {
214214
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
215215
ctx.Data["PageIsEditProjects"] = true
216216
ctx.Data["PageIsViewProjects"] = true
217-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
217+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
218218
shared_user.RenderUserHeader(ctx)
219219

220220
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
@@ -226,13 +226,14 @@ func EditProject(ctx *context.Context) {
226226
}
227227
return
228228
}
229-
if p.RepoID != ctx.Repo.Repository.ID {
229+
if p.OwnerID != ctx.ContextUser.ID {
230230
ctx.NotFound("", nil)
231231
return
232232
}
233233

234234
ctx.Data["title"] = p.Title
235235
ctx.Data["content"] = p.Description
236+
ctx.Data["redirect"] = ctx.FormString("redirect")
236237

237238
ctx.HTML(http.StatusOK, tplProjectsNew)
238239
}
@@ -243,7 +244,7 @@ func EditProjectPost(ctx *context.Context) {
243244
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
244245
ctx.Data["PageIsEditProjects"] = true
245246
ctx.Data["PageIsViewProjects"] = true
246-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
247+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
247248
shared_user.RenderUserHeader(ctx)
248249

249250
if ctx.HasError() {
@@ -260,7 +261,7 @@ func EditProjectPost(ctx *context.Context) {
260261
}
261262
return
262263
}
263-
if p.RepoID != ctx.Repo.Repository.ID {
264+
if p.OwnerID != ctx.ContextUser.ID {
264265
ctx.NotFound("", nil)
265266
return
266267
}
@@ -273,7 +274,11 @@ func EditProjectPost(ctx *context.Context) {
273274
}
274275

275276
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
276-
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
277+
if ctx.FormString("redirect") == "project" {
278+
ctx.Redirect(p.Link())
279+
} else {
280+
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects")
281+
}
277282
}
278283

279284
// ViewProject renders the project board for a project
@@ -332,7 +337,7 @@ func ViewProject(ctx *context.Context) {
332337
project.RenderedContent = project.Description
333338
ctx.Data["LinkedPRs"] = linkedPrsMap
334339
ctx.Data["PageIsViewProjects"] = true
335-
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
340+
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
336341
ctx.Data["Project"] = project
337342
ctx.Data["IssuesMap"] = issuesMap
338343
ctx.Data["Boards"] = boards

routers/web/repo/projects.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ func EditProject(ctx *context.Context) {
235235
ctx.Data["title"] = p.Title
236236
ctx.Data["content"] = p.Description
237237
ctx.Data["card_type"] = p.CardType
238+
ctx.Data["redirect"] = ctx.FormString("redirect")
238239

239240
ctx.HTML(http.StatusOK, tplProjectsNew)
240241
}
@@ -275,7 +276,11 @@ func EditProjectPost(ctx *context.Context) {
275276
}
276277

277278
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
278-
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
279+
if ctx.FormString("redirect") == "project" {
280+
ctx.Redirect(p.Link())
281+
} else {
282+
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
283+
}
279284
}
280285

281286
// ViewProject renders the project board for a project

services/pull/comment.go

Lines changed: 12 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,58 +14,6 @@ import (
1414
issue_service "code.gitea.io/gitea/services/issue"
1515
)
1616

17-
type commitBranchCheckItem struct {
18-
Commit *git.Commit
19-
Checked bool
20-
}
21-
22-
func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
23-
if startCommit.ID.String() == endCommitID {
24-
return nil
25-
}
26-
27-
checkStack := make([]string, 0, 10)
28-
checkStack = append(checkStack, startCommit.ID.String())
29-
30-
for len(checkStack) > 0 {
31-
commitID := checkStack[0]
32-
checkStack = checkStack[1:]
33-
34-
item, ok := commitList[commitID]
35-
if !ok {
36-
continue
37-
}
38-
39-
if item.Commit.ID.String() == endCommitID {
40-
continue
41-
}
42-
43-
if err := item.Commit.LoadBranchName(); err != nil {
44-
return err
45-
}
46-
47-
if item.Commit.Branch == baseBranch {
48-
continue
49-
}
50-
51-
if item.Checked {
52-
continue
53-
}
54-
55-
item.Checked = true
56-
57-
parentNum := item.Commit.ParentCount()
58-
for i := 0; i < parentNum; i++ {
59-
parentCommit, err := item.Commit.Parent(i)
60-
if err != nil {
61-
return err
62-
}
63-
checkStack = append(checkStack, parentCommit.ID.String())
64-
}
65-
}
66-
return nil
67-
}
68-
6917
// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
7018
// isForcePush will be true if oldCommit isn't on the branch
7119
// Commit on baseBranch will skip
@@ -82,47 +30,33 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC
8230
return nil, false, err
8331
}
8432

85-
if err = oldCommit.LoadBranchName(); err != nil {
86-
return nil, false, err
87-
}
88-
89-
if len(oldCommit.Branch) == 0 {
90-
commitIDs = make([]string, 2)
91-
commitIDs[0] = oldCommitID
92-
commitIDs[1] = newCommitID
93-
94-
return commitIDs, true, err
95-
}
96-
9733
newCommit, err := gitRepo.GetCommit(newCommitID)
9834
if err != nil {
9935
return nil, false, err
10036
}
10137

102-
commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
38+
isForcePush, err = newCommit.IsForcePush(oldCommitID)
10339
if err != nil {
10440
return nil, false, err
10541
}
10642

107-
commitIDs = make([]string, 0, len(commits))
108-
commitChecks := make(map[string]*commitBranchCheckItem)
43+
if isForcePush {
44+
commitIDs = make([]string, 2)
45+
commitIDs[0] = oldCommitID
46+
commitIDs[1] = newCommitID
10947

110-
for _, commit := range commits {
111-
commitChecks[commit.ID.String()] = &commitBranchCheckItem{
112-
Commit: commit,
113-
Checked: false,
114-
}
48+
return commitIDs, isForcePush, err
11549
}
11650

117-
if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
118-
return
51+
// Find commits between new and old commit exclusing base branch commits
52+
commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
53+
if err != nil {
54+
return nil, false, err
11955
}
12056

57+
commitIDs = make([]string, 0, len(commits))
12158
for i := len(commits) - 1; i >= 0; i-- {
122-
commitID := commits[i].ID.String()
123-
if item, ok := commitChecks[commitID]; ok && item.Checked {
124-
commitIDs = append(commitIDs, commitID)
125-
}
59+
commitIDs = append(commitIDs, commits[i].ID.String())
12660
}
12761

12862
return commitIDs, isForcePush, err

services/pull/merge.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
332332
}
333333

334334
func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
335-
if err := git.NewCommand(ctx, "commit").AddArguments(ctx.signArg...).AddOptionFormat("--message=%s", message).
336-
Run(ctx.RunOpts()); err != nil {
335+
cmdCommit := git.NewCommand(ctx, "commit").AddOptionFormat("--message=%s", message)
336+
if ctx.signKeyID == "" {
337+
cmdCommit.AddArguments("--no-gpg-sign")
338+
} else {
339+
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
340+
}
341+
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
337342
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
338343
return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
339344
}

services/pull/merge_prepare.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type mergeContext struct {
2828
doer *user_model.User
2929
sig *git.Signature
3030
committer *git.Signature
31-
signArg git.TrustedCmdArgs
31+
signKeyID string // empty for no-sign, non-empty to sign
3232
env []string
3333
}
3434

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

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

139-
gitConfigCommand := func() *git.Command {
140-
return git.NewCommand(ctx, "config", "--local")
141-
}
142-
143137
setConfig := func(key, value string) error {
144-
if err := gitConfigCommand().AddArguments(git.ToTrustedCmdArgs([]string{key, value})...).
138+
if err := git.NewCommand(ctx, "config", "--local").AddDynamicArguments(key, value).
145139
Run(ctx.RunOpts()); err != nil {
146-
if value == "" {
147-
value = "<>"
148-
}
149-
log.Error("git config [%s -> %s ]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
150-
return fmt.Errorf("git config [%s -> %s ]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
140+
log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
141+
return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
151142
}
152143
ctx.outbuf.Reset()
153144
ctx.errbuf.Reset()

0 commit comments

Comments
 (0)