Compare commits

...

8 Commits

Author SHA1 Message Date
John Olheiser
48eb5ac685
Changelog 1.18.5 (#23045)
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2023-02-21 12:14:55 -06:00
Yarden Shoham
8f5b2f1ddf
Return empty url for submodule tree entries (#23043) (#23048)
Backport #23043

Close #22614.

Refer to [Github's
API](https://docs.github.com/en/rest/git/trees?apiVersion=2022-11-28#get-a-tree),
if a tree entry is a submodule, its url will be an empty string.

Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: delvh <leon@kske.dev>
Co-authored-by: John Olheiser <john.olheiser@gmail.com>
2023-02-21 12:35:14 -05:00
John Olheiser
bbfd34575a
Display attachments of review comment when comment content is blank (#23035) (#23046)
Backport #23035

Co-authored-by: sillyguodong <33891828+sillyguodong@users.noreply.github.com>
2023-02-21 11:10:29 -06:00
Kyle D
760cf419ba
Use beforeCommit instead of baseCommit (#22949) (#22996)
Backport #22949
Fixes https://github.com/go-gitea/gitea/issues/22946
Probably related to https://github.com/go-gitea/gitea/issues/19530

Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2023-02-21 10:51:02 -05:00
Jason Song
90982bffa5
Add force_merge to merge request and fix checking mergable (#23010) (#23032)
Backport #23010.

Fix #23000.

The bug was introduced in #22633, and it seems that it has been noticed:
https://github.com/go-gitea/gitea/pull/22633#discussion_r1095395359 .

However, #22633 did nothing wrong, the logic should be "check if they is
admin only when `force` is true".

So we should provide the `ForceMerge` when merging from UI.

After this, an admin can also send a normal merge request with
`ForceMerge` false. So it fixes a potential bug: if the admin doesn't
want to do a force merge, they just see the green "Merge" button and
click it. At the same time, the status of the PR changed, and it
shouldn't be merged now, so the admin could send an unexpected force
merge.

In addition, I updated `ForceMerge *bool` to `ForceMerge bool`, I don't
see the reason to use a pointer.

And fixed the logic of CheckPullMergable to handle auto merge and force
merge correctly.
2023-02-21 09:42:22 -06:00
Yarden Shoham
8fa62be905
Render access log template as text instead of HTML (#23013) (#23025)
Backport #23013

Fix https://github.com/go-gitea/gitea/pull/22906#discussion_r1112106675

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-21 18:04:57 +08:00
wxiaoguang
7b3ffe5745
Fix the Manually Merged form (#23015) (#23017)
Backport #23015

---------

Co-authored-by: Jason Song <i@wolfogre.com>
2023-02-21 18:04:29 +08:00
wxiaoguang
c50d4202ef
Use --message=%s for git commit message (#23028) (#23029)
Backport #23028

This backport is done by manually because the git module is different.
2023-02-21 14:16:25 +08:00
33 changed files with 205 additions and 51 deletions

View File

@ -4,6 +4,19 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io). been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.18.5](https://github.com/go-gitea/gitea/releases/tag/v1.18.5) - 2023-02-21
* ENHANCEMENTS
* Hide 2FA status from other members in organization members list (#22999) (#23023)
* BUGFIXES
* Add force_merge to merge request and fix checking mergable (#23010) (#23032)
* Use `--message=%s` for git commit message (#23028) (#23029)
* Render access log template as text instead of HTML (#23013) (#23025)
* Fix the Manually Merged form (#23015) (#23017)
* Use beforeCommit instead of baseCommit (#22949) (#22996)
* Display attachments of review comment when comment content is blank (#23035) (#23046)
* Return empty url for submodule tree entries (#23043) (#23048)
## [1.18.4](https://github.com/go-gitea/gitea/releases/tag/1.18.4) - 2023-02-20 ## [1.18.4](https://github.com/go-gitea/gitea/releases/tag/1.18.4) - 2023-02-20
* SECURITY * SECURITY

View File

@ -544,3 +544,16 @@
repo_id: 51 repo_id: 51
type: 2 type: 2
created_unix: 946684810 created_unix: 946684810
-
id: 80
repo_id: 31
type: 1
created_unix: 946684810
-
id: 81
repo_id: 31
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810

View File

@ -7,8 +7,8 @@ package context
import ( import (
"bytes" "bytes"
"context" "context"
"html/template"
"net/http" "net/http"
"text/template"
"time" "time"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"

View File

@ -132,7 +132,7 @@ func CommitChangesWithArgs(repoPath string, args []CmdArg, opts CommitChangesOpt
if opts.Author != nil { if opts.Author != nil {
cmd.AddArguments(CmdArg(fmt.Sprintf("--author='%s <%s>'", opts.Author.Name, opts.Author.Email))) cmd.AddArguments(CmdArg(fmt.Sprintf("--author='%s <%s>'", opts.Author.Name, opts.Author.Email)))
} }
cmd.AddArguments("-m").AddDynamicArguments(opts.Message) cmd.AddArguments(CmdArg("--message=" + opts.Message))
_, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath}) _, _, err := cmd.RunStdString(&RunOpts{Dir: repoPath})
// No stderr but exit status 1 means nothing to commit. // No stderr but exit status 1 means nothing to commit.

View File

@ -319,7 +319,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi
cmd := git.NewCommand(ctx, cmd := git.NewCommand(ctx,
"commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)), "commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)),
"-m", "Initial commit", "--message=Initial commit",
) )
sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) sign, keyID, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u)

View File

@ -767,11 +767,18 @@ func MergePullRequest(ctx *context.APIContext) {
} }
} }
manuallMerge := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged manuallyMerged := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged
force := form.ForceMerge != nil && *form.ForceMerge
mergeCheckType := pull_service.MergeCheckTypeGeneral
if form.MergeWhenChecksSucceed {
mergeCheckType = pull_service.MergeCheckTypeAuto
}
if manuallyMerged {
mergeCheckType = pull_service.MergeCheckTypeManually
}
// start with merging by checking // start with merging by checking
if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, manuallMerge, force); err != nil { if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil {
if errors.Is(err, pull_service.ErrIsClosed) { if errors.Is(err, pull_service.ErrIsClosed) {
ctx.NotFound() ctx.NotFound()
} else if errors.Is(err, pull_service.ErrUserNotAllowedToMerge) { } else if errors.Is(err, pull_service.ErrUserNotAllowedToMerge) {
@ -793,7 +800,7 @@ func MergePullRequest(ctx *context.APIContext) {
} }
// handle manually-merged mark // handle manually-merged mark
if manuallMerge { if manuallyMerged {
if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
if models.IsErrInvalidMergeStyle(err) { if models.IsErrInvalidMergeStyle(err) {
ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do))) ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))

View File

@ -43,8 +43,8 @@ const (
) )
// setCompareContext sets context data. // setCompareContext sets context data.
func setCompareContext(ctx *context.Context, base, head *git.Commit, headOwner, headName string) { func setCompareContext(ctx *context.Context, before, head *git.Commit, headOwner, headName string) {
ctx.Data["BaseCommit"] = base ctx.Data["BeforeCommit"] = before
ctx.Data["HeadCommit"] = head ctx.Data["HeadCommit"] = head
ctx.Data["GetBlobByPathForCommit"] = func(commit *git.Commit, path string) *git.Blob { ctx.Data["GetBlobByPathForCommit"] = func(commit *git.Commit, path string) *git.Blob {
@ -59,7 +59,7 @@ func setCompareContext(ctx *context.Context, base, head *git.Commit, headOwner,
return blob return blob
} }
setPathsCompareContext(ctx, base, head, headOwner, headName) setPathsCompareContext(ctx, before, head, headOwner, headName)
setImageCompareContext(ctx) setImageCompareContext(ctx)
setCsvCompareContext(ctx) setCsvCompareContext(ctx)
} }
@ -629,9 +629,8 @@ func PrepareCompareDiff(
} }
baseGitRepo := ctx.Repo.GitRepo baseGitRepo := ctx.Repo.GitRepo
baseCommitID := ci.CompareInfo.BaseCommitID
baseCommit, err := baseGitRepo.GetCommit(baseCommitID) beforeCommit, err := baseGitRepo.GetCommit(beforeCommitID)
if err != nil { if err != nil {
ctx.ServerError("GetCommit", err) ctx.ServerError("GetCommit", err)
return false return false
@ -668,7 +667,7 @@ func PrepareCompareDiff(
ctx.Data["Username"] = ci.HeadUser.Name ctx.Data["Username"] = ci.HeadUser.Name
ctx.Data["Reponame"] = ci.HeadRepo.Name ctx.Data["Reponame"] = ci.HeadRepo.Name
setCompareContext(ctx, baseCommit, headCommit, ci.HeadUser.Name, repo.Name) setCompareContext(ctx, beforeCommit, headCommit, ci.HeadUser.Name, repo.Name)
return false return false
} }

View File

@ -912,11 +912,19 @@ func MergePullRequest(ctx *context.Context) {
pr := issue.PullRequest pr := issue.PullRequest
pr.Issue = issue pr.Issue = issue
pr.Issue.Repo = ctx.Repo.Repository pr.Issue.Repo = ctx.Repo.Repository
manualMerge := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged
forceMerge := form.ForceMerge != nil && *form.ForceMerge manuallyMerged := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged
mergeCheckType := pull_service.MergeCheckTypeGeneral
if form.MergeWhenChecksSucceed {
mergeCheckType = pull_service.MergeCheckTypeAuto
}
if manuallyMerged {
mergeCheckType = pull_service.MergeCheckTypeManually
}
// start with merging by checking // start with merging by checking
if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, manualMerge, forceMerge); err != nil { if err := pull_service.CheckPullMergable(ctx, ctx.Doer, &ctx.Repo.Permission, pr, mergeCheckType, form.ForceMerge); err != nil {
switch { switch {
case errors.Is(err, pull_service.ErrIsClosed): case errors.Is(err, pull_service.ErrIsClosed):
if issue.IsPull { if issue.IsPull {
@ -948,7 +956,7 @@ func MergePullRequest(ctx *context.Context) {
} }
// handle manually-merged mark // handle manually-merged mark
if manualMerge { if manuallyMerged {
if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
switch { switch {

View File

@ -231,7 +231,7 @@ func handlePull(pullID int64, sha string) {
return return
} }
if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, false, false); err != nil { if err := pull_service.CheckPullMergable(ctx, doer, &perm, pr, pull_service.MergeCheckTypeGeneral, false); err != nil {
if errors.Is(pull_service.ErrUserNotAllowedToMerge, err) { if errors.Is(pull_service.ErrUserNotAllowedToMerge, err) {
log.Info("%-v was scheduled to automerge by an unauthorized user", pr) log.Info("%-v was scheduled to automerge by an unauthorized user", pr)
return return

View File

@ -597,7 +597,7 @@ type MergePullRequestForm struct {
MergeMessageField string MergeMessageField string
MergeCommitID string // only used for manually-merged MergeCommitID string // only used for manually-merged
HeadCommitID string `json:"head_commit_id,omitempty"` HeadCommitID string `json:"head_commit_id,omitempty"`
ForceMerge *bool `json:"force_merge,omitempty"` ForceMerge bool `json:"force_merge,omitempty"`
MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed,omitempty"` MergeWhenChecksSucceed bool `json:"merge_when_checks_succeed,omitempty"`
DeleteBranchAfterMerge bool `json:"delete_branch_after_merge,omitempty"` DeleteBranchAfterMerge bool `json:"delete_branch_after_merge,omitempty"`
} }

View File

@ -59,8 +59,16 @@ func AddToTaskQueue(pr *issues_model.PullRequest) {
} }
} }
type MergeCheckType int
const (
MergeCheckTypeGeneral MergeCheckType = iota // general merge checks for "merge", "rebase", "squash", etc
MergeCheckTypeManually // Manually Merged button (mark a PR as merged manually)
MergeCheckTypeAuto // Auto Merge (Scheduled Merge) After Checks Succeed
)
// CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...) // CheckPullMergable check if the pull mergable based on all conditions (branch protection, merge options, ...)
func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, manuallMerge, force bool) error { func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *access_model.Permission, pr *issues_model.PullRequest, mergeCheckType MergeCheckType, adminSkipProtectionCheck bool) error {
return db.WithTx(func(ctx context.Context) error { return db.WithTx(func(ctx context.Context) error {
if pr.HasMerged { if pr.HasMerged {
return ErrHasMerged return ErrHasMerged
@ -80,8 +88,8 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
return ErrUserNotAllowedToMerge return ErrUserNotAllowedToMerge
} }
if manuallMerge { if mergeCheckType == MergeCheckTypeManually {
// don't check rules to "auto merge", doer is going to mark this pull as merged manually // if doer is doing "manually merge" (mark as merged manually), do not check anything
return nil return nil
} }
@ -103,14 +111,25 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce
return err return err
} }
if !force { // Now the branch protection check failed, check whether the failure could be skipped (skip by setting err = nil)
return err
// * when doing Auto Merge (Scheduled Merge After Checks Succeed), skip the branch protection check
if mergeCheckType == MergeCheckTypeAuto {
err = nil
} }
if isRepoAdmin, err2 := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); err2 != nil { // * if the doer is admin, they could skip the branch protection check
log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, err2) if adminSkipProtectionCheck {
return err2 if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil {
} else if !isRepoAdmin { log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, errCheckAdmin)
return errCheckAdmin
} else if isRepoAdmin {
err = nil // repo admin can skip the check, so clear the error
}
}
// If there is still a branch protection check error, return it
if err != nil {
return err return err
} }
} }

View File

@ -516,7 +516,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
} }
sig := pr.Issue.Poster.NewGitSig() sig := pr.Issue.Poster.NewGitSig()
if signArg == "" { if signArg == "" {
if err := git.NewCommand(ctx, "commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)), "-m").AddDynamicArguments(message). if err := git.NewCommand(ctx, "commit", git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email)), git.CmdArg("--message="+message)).
Run(&git.RunOpts{ Run(&git.RunOpts{
Env: env, Env: env,
Dir: tmpBasePath, Dir: tmpBasePath,
@ -534,7 +534,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
if err := git.NewCommand(ctx, "commit"). if err := git.NewCommand(ctx, "commit").
AddArguments(signArg). AddArguments(signArg).
AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email))). AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email))).
AddArguments("-m").AddDynamicArguments(message). AddArguments(git.CmdArg("--message=" + message)).
Run(&git.RunOpts{ Run(&git.RunOpts{
Env: env, Env: env,
Dir: tmpBasePath, Dir: tmpBasePath,
@ -644,7 +644,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode
func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message string, signArg git.CmdArg, tmpBasePath string, env []string) error { func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, message string, signArg git.CmdArg, tmpBasePath string, env []string) error {
var outbuf, errbuf strings.Builder var outbuf, errbuf strings.Builder
if signArg == "" { if signArg == "" {
if err := git.NewCommand(ctx, "commit", "-m").AddDynamicArguments(message). if err := git.NewCommand(ctx, "commit", git.CmdArg("--message="+message)).
Run(&git.RunOpts{ Run(&git.RunOpts{
Env: env, Env: env,
Dir: tmpBasePath, Dir: tmpBasePath,
@ -655,7 +655,7 @@ func commitAndSignNoAuthor(ctx context.Context, pr *issues_model.PullRequest, me
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String()) return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseRepo.FullName(), pr.BaseBranch, err, outbuf.String(), errbuf.String())
} }
} else { } else {
if err := git.NewCommand(ctx, "commit").AddArguments(signArg).AddArguments("-m").AddDynamicArguments(message). if err := git.NewCommand(ctx, "commit").AddArguments(signArg).AddArguments(git.CmdArg("--message=" + message)).
Run(&git.RunOpts{ Run(&git.RunOpts{
Env: env, Env: env,
Dir: tmpBasePath, Dir: tmpBasePath,

View File

@ -86,6 +86,11 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git
if entries[e].IsDir() { if entries[e].IsDir() {
copy(treeURL[copyPos:], entries[e].ID.String()) copy(treeURL[copyPos:], entries[e].ID.String())
tree.Entries[i].URL = string(treeURL) tree.Entries[i].URL = string(treeURL)
} else if entries[e].IsSubModule() {
// In Github Rest API Version=2022-11-28, if a tree entry is a submodule,
// its url will be returned as an empty string.
// So the URL will be set to "" here.
tree.Entries[i].URL = ""
} else { } else {
copy(blobURL[copyPos:], entries[e].ID.String()) copy(blobURL[copyPos:], entries[e].ID.String())
tree.Entries[i].URL = string(blobURL) tree.Entries[i].URL = string(blobURL)

View File

@ -71,7 +71,7 @@
<div id="diff-file-boxes" class="sixteen wide column"> <div id="diff-file-boxes" class="sixteen wide column">
{{range $i, $file := .Diff.Files}} {{range $i, $file := .Diff.Files}}
{{/*notice: the index of Diff.Files should not be used for element ID, because the index will be restarted from 0 when doing load-more for PRs with a lot of files*/}} {{/*notice: the index of Diff.Files should not be used for element ID, because the index will be restarted from 0 when doing load-more for PRs with a lot of files*/}}
{{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}} {{$blobBase := call $.GetBlobByPathForCommit $.BeforeCommit $file.OldName}}
{{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}} {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
{{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}} {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
{{$isCsv := (call $.IsCsvFile $file)}} {{$isCsv := (call $.IsCsvFile $file)}}

View File

@ -399,7 +399,7 @@
{{end}} {{end}}
</span> </span>
</div> </div>
{{if .Content}} {{if or .Content .Attachments}}
<div class="timeline-item comment" id="{{.HashTag}}"> <div class="timeline-item comment" id="{{.HashTag}}">
<div class="content comment-container"> <div class="content comment-container">
<div class="ui top attached header comment-header df ac sb"> <div class="ui top attached header comment-header df ac sb">

View File

@ -129,6 +129,7 @@
<div class="content"> <div class="content">
{{template "repo/pulls/status" .}} {{template "repo/pulls/status" .}}
{{$canAutoMerge := false}} {{$canAutoMerge := false}}
{{$showGeneralMergeForm := false}}
<div class="ui attached merge-section segment {{if not $.LatestCommitStatus}}no-header{{end}}"> <div class="ui attached merge-section segment {{if not $.LatestCommitStatus}}no-header{{end}}">
{{if .Issue.PullRequest.HasMerged}} {{if .Issue.PullRequest.HasMerged}}
<div class="item text"> <div class="item text">
@ -351,6 +352,7 @@
'textAutoMergeButtonWhenSucceed': {{$.locale.Tr "repo.pulls.auto_merge_button_when_succeed"}}, 'textAutoMergeButtonWhenSucceed': {{$.locale.Tr "repo.pulls.auto_merge_button_when_succeed"}},
'textAutoMergeWhenSucceed': {{$.locale.Tr "repo.pulls.auto_merge_when_succeed"}}, 'textAutoMergeWhenSucceed': {{$.locale.Tr "repo.pulls.auto_merge_when_succeed"}},
'textAutoMergeCancelSchedule': {{$.locale.Tr "repo.pulls.auto_merge_cancel_schedule"}}, 'textAutoMergeCancelSchedule': {{$.locale.Tr "repo.pulls.auto_merge_cancel_schedule"}},
'textMergeCommitId': {{$.locale.Tr "repo.pulls.merge_commit_id"}},
'canMergeNow': {{$canMergeNow}}, 'canMergeNow': {{$canMergeNow}},
'allOverridableChecksOk': {{not $notAllOverridableChecksOk}}, 'allOverridableChecksOk': {{not $notAllOverridableChecksOk}},
@ -410,6 +412,7 @@
})(); })();
</script> </script>
{{$showGeneralMergeForm = true}}
<div id="pull-request-merge-form"></div> <div id="pull-request-merge-form"></div>
{{if .ShowMergeInstructions}} {{if .ShowMergeInstructions}}
@ -487,30 +490,21 @@
{{$.locale.Tr "repo.pulls.cannot_auto_merge_helper"}} {{$.locale.Tr "repo.pulls.cannot_auto_merge_helper"}}
</div> </div>
{{end}} {{end}}
{{end}} {{end}}{{/* end if: pull request status */}}
{{if $.StillCanManualMerge}} {{if and $.StillCanManualMerge (not $showGeneralMergeForm)}}
<div class="ui divider"></div> <div class="ui divider"></div>
<div class="ui form manually-merged-fields" style="display: none"> <div class="ui form">
<form action="{{.Link}}/merge" method="post"> <form action="{{.Link}}/merge" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<div class="field"> <div class="field">
<input type="text" name="merge_commit_id" placeholder="{{$.locale.Tr "repo.pulls.merge_commit_id"}}"> <input type="text" name="merge_commit_id" placeholder="{{$.locale.Tr "repo.pulls.merge_commit_id"}}">
</div> </div>
<button class="ui red button" type="submit" name="do" value="manually-merged"> <button class="ui red button" type="submit" name="do" value="manually-merged">
{{$.locale.Tr "repo.pulls.merge_manually"}} {{$.locale.Tr "repo.pulls.merge_manually"}}
</button> </button>
<button class="ui button merge-cancel">
{{$.locale.Tr "cancel"}}
</button>
</form> </form>
</div> </div>
<div class="ui red buttons merge-button">
<button class="ui button" data-do="manually-merged">
{{$.locale.Tr "repo.pulls.merge_manually"}}
</button>
</div>
{{end}} {{end}}
</div> </div>
</div> </div>

View File

@ -1,2 +1,2 @@
#!/usr/bin/env bash #!/usr/bin/env bash
"/home/tris/Projects/go/src/code.gitea.io/gitea/gitea" hook --config='/home/tris/Projects/go/src/code.gitea.io/gitea/custom/conf/app.ini' post-receive "$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive

View File

@ -1,2 +1,2 @@
#!/usr/bin/env bash #!/usr/bin/env bash
"/home/tris/Projects/go/src/code.gitea.io/gitea/gitea" hook --config='/home/tris/Projects/go/src/code.gitea.io/gitea/custom/conf/app.ini' pre-receive "$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive

View File

@ -1,2 +1,2 @@
#!/usr/bin/env bash #!/usr/bin/env bash
"/home/tris/Projects/go/src/code.gitea.io/gitea/gitea" hook --config='/home/tris/Projects/go/src/code.gitea.io/gitea/custom/conf/app.ini' update $1 $2 $3 "$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3

View File

@ -0,0 +1 @@
x•ŽAnÃ0 sÖ+ø<>”l Ð[_ATkIJC>ø÷Õz[,f1·Zç!øKÛÍ€“è<53>L5[,©DÒ‰'<27>:aˆRнe·µÁDlã È:^C<0F>g”lHƒd<C692>æ‡Â>iqr´ßm‡ïs1øÛK<C39B>º­m=?Uæå3oõž˜®<CB9C>òð<C3B2>Ñõ¶¿köß<C3B6>{ª‚@wÔʼ˜û<03>E]

View File

@ -0,0 +1,2 @@
x•ÎA
Â0@Q×9Å\@™NÒ&wž"“L´Ø4Ò¦·×+¸ýðàÇZÊØ€ˆvm<11>`ÉÙ!&ÇuÖŽmò¾÷FKÇl³·aÈê8t¨]¢l;ÆÀHè}g´<67>9'2}´{<7B>*líQ¸}&<26>+Ÿi+unóv¾—0N‡XË ºÁŽ,!Â{Dõ«¿»&ÿ:uI š¬ âú†<N¢¾¨qEo

View File

@ -0,0 +1,3 @@
x•ŽAnÂ0EYűs<01>=v2FB v=D5¶';U<>Tâöř
Ýţ§÷ôóZ묀ş‰€%P(z“—ŁźŠpńDě%8¶!8[Ě/oŇrďR¦1FępŔHS.¦”┞3÷$’á]ëßďEŕ—gŮëÚ´í×{ĺy9ĺµ~<7E>{ ĎŽv°ÖôµżSůŻgn˛<6E>
¨Ľô”_Ŕ­Ŕ2·çĎc6tuI

View File

@ -0,0 +1 @@
c8e31bc7688741a5287fcde4fbb8fc129ca07027

View File

@ -0,0 +1 @@
cfe3b3c1fd36fba04f9183287b106497e1afe986

View File

@ -0,0 +1 @@
8babce967f21b9dfa6987f943b91093dac58a4f0

View File

@ -5,6 +5,7 @@
package integration package integration
import ( import (
"fmt"
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
@ -41,3 +42,80 @@ func TestCompareDefault(t *testing.T) {
selection := htmlDoc.doc.Find(".choose.branch .filter.dropdown") selection := htmlDoc.doc.Find(".choose.branch .filter.dropdown")
assert.Lenf(t, selection.Nodes, 2, "The template has changed") assert.Lenf(t, selection.Nodes, 2, "The template has changed")
} }
// Ensure the comparison matches what we expect
func inspectCompare(t *testing.T, htmlDoc *HTMLDoc, diffCount int, diffChanges []string) {
selection := htmlDoc.doc.Find("#diff-file-boxes").Children()
assert.Lenf(t, selection.Nodes, diffCount, "Expected %v diffed files, found: %v", diffCount, len(selection.Nodes))
for _, diffChange := range diffChanges {
selection = htmlDoc.doc.Find(fmt.Sprintf("[data-new-filename=\"%s\"]", diffChange))
assert.Lenf(t, selection.Nodes, 1, "Expected 1 match for [data-new-filename=\"%s\"], found: %v", diffChange, len(selection.Nodes))
}
}
// Git commit graph for repo20
// * 8babce9 (origin/remove-files-b) Add a dummy file
// * b67e43a Delete test.csv and link_hi
// | * cfe3b3c (origin/remove-files-a) Delete test.csv and link_hi
// |/
// * c8e31bc (origin/add-csv) Add test csv file
// * 808038d (HEAD -> master, origin/master, origin/HEAD) Added test links
func TestCompareBranches(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user2")
// Inderect compare remove-files-b (head) with add-csv (base) branch
//
// 'link_hi' and 'test.csv' are deleted, 'test.txt' is added
req := NewRequest(t, "GET", "/user2/repo20/compare/add-csv...remove-files-b")
resp := session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
diffCount := 3
diffChanges := []string{"link_hi", "test.csv", "test.txt"}
inspectCompare(t, htmlDoc, diffCount, diffChanges)
// Inderect compare remove-files-b (head) with remove-files-a (base) branch
//
// 'link_hi' and 'test.csv' are deleted, 'test.txt' is added
req = NewRequest(t, "GET", "/user2/repo20/compare/remove-files-a...remove-files-b")
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
diffCount = 3
diffChanges = []string{"link_hi", "test.csv", "test.txt"}
inspectCompare(t, htmlDoc, diffCount, diffChanges)
// Inderect compare remove-files-a (head) with remove-files-b (base) branch
//
// 'link_hi' and 'test.csv' are deleted
req = NewRequest(t, "GET", "/user2/repo20/compare/remove-files-b...remove-files-a")
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
diffCount = 2
diffChanges = []string{"link_hi", "test.csv"}
inspectCompare(t, htmlDoc, diffCount, diffChanges)
// Direct compare remove-files-b (head) with remove-files-a (base) branch
//
// 'test.txt' is deleted
req = NewRequest(t, "GET", "/user2/repo20/compare/remove-files-b..remove-files-a")
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc = NewHTMLParser(t, resp.Body)
diffCount = 1
diffChanges = []string{"test.txt"}
inspectCompare(t, htmlDoc, diffCount, diffChanges)
}

View File

@ -18,6 +18,7 @@
<input type="hidden" name="_csrf" :value="csrfToken"> <input type="hidden" name="_csrf" :value="csrfToken">
<input type="hidden" name="head_commit_id" v-model="mergeForm.pullHeadCommitID"> <input type="hidden" name="head_commit_id" v-model="mergeForm.pullHeadCommitID">
<input type="hidden" name="merge_when_checks_succeed" v-model="autoMergeWhenSucceed"> <input type="hidden" name="merge_when_checks_succeed" v-model="autoMergeWhenSucceed">
<input type="hidden" name="force_merge" v-model="forceMerge">
<template v-if="!mergeStyleDetail.hideMergeMessageTexts"> <template v-if="!mergeStyleDetail.hideMergeMessageTexts">
<div class="field"> <div class="field">
@ -28,6 +29,10 @@
</div> </div>
</template> </template>
<div class="field" v-if="mergeStyle === 'manually-merged'">
<input type="text" name="merge_commit_id" :placeholder="mergeForm.textMergeCommitId">
</div>
<button class="ui button" :class="mergeButtonStyleClass" type="submit" name="do" :value="mergeStyle"> <button class="ui button" :class="mergeButtonStyleClass" type="submit" name="do" :value="mergeStyle">
{{ mergeStyleDetail.textDoMerge }} {{ mergeStyleDetail.textDoMerge }}
<template v-if="autoMergeWhenSucceed"> <template v-if="autoMergeWhenSucceed">
@ -123,6 +128,7 @@ export default {
textDoMerge: '', textDoMerge: '',
mergeTitleFieldText: '', mergeTitleFieldText: '',
mergeMessageFieldText: '', mergeMessageFieldText: '',
hideAutoMerge: false,
}, },
mergeStyleAllowedCount: 0, mergeStyleAllowedCount: 0,
@ -134,7 +140,10 @@ export default {
mergeButtonStyleClass() { mergeButtonStyleClass() {
if (this.mergeForm.allOverridableChecksOk) return 'green'; if (this.mergeForm.allOverridableChecksOk) return 'green';
return this.autoMergeWhenSucceed ? 'blue' : 'red'; return this.autoMergeWhenSucceed ? 'blue' : 'red';
} },
forceMerge() {
return this.mergeForm.canMergeNow && !this.mergeForm.allOverridableChecksOk;
},
}, },
watch: { watch: {