diff --git a/CHANGELOG.md b/CHANGELOG.md index 77dc47e32fb5c..358a0e37493b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 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 * SECURITY diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml index 59ab61834070c..8550dd4ef4194 100644 --- a/models/fixtures/repo_unit.yml +++ b/models/fixtures/repo_unit.yml @@ -544,3 +544,16 @@ repo_id: 51 type: 2 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 diff --git a/modules/context/access_log.go b/modules/context/access_log.go index 1a10c4763a818..0560131a38bfe 100644 --- a/modules/context/access_log.go +++ b/modules/context/access_log.go @@ -7,8 +7,8 @@ package context import ( "bytes" "context" - "html/template" "net/http" + "text/template" "time" "code.gitea.io/gitea/modules/log" diff --git a/modules/git/commit.go b/modules/git/commit.go index 061adc1082355..ec2cc8ad81cc7 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -132,7 +132,7 @@ func CommitChangesWithArgs(repoPath string, args []CmdArg, opts CommitChangesOpt if opts.Author != nil { 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}) // No stderr but exit status 1 means nothing to commit. diff --git a/modules/repository/init.go b/modules/repository/init.go index 65072a959948e..c1b97069ffd29 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -319,7 +319,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi cmd := git.NewCommand(ctx, "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) diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index a687eabfba34e..4f2edc2f2a3af 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -767,11 +767,18 @@ func MergePullRequest(ctx *context.APIContext) { } } - manuallMerge := repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged - force := 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 - 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) { ctx.NotFound() } else if errors.Is(err, pull_service.ErrUserNotAllowedToMerge) { @@ -793,7 +800,7 @@ func MergePullRequest(ctx *context.APIContext) { } // handle manually-merged mark - if manuallMerge { + if manuallyMerged { if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { 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))) diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index db6b59471ff47..1b8521dd9295a 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -43,8 +43,8 @@ const ( ) // setCompareContext sets context data. -func setCompareContext(ctx *context.Context, base, head *git.Commit, headOwner, headName string) { - ctx.Data["BaseCommit"] = base +func setCompareContext(ctx *context.Context, before, head *git.Commit, headOwner, headName string) { + ctx.Data["BeforeCommit"] = before ctx.Data["HeadCommit"] = head 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 } - setPathsCompareContext(ctx, base, head, headOwner, headName) + setPathsCompareContext(ctx, before, head, headOwner, headName) setImageCompareContext(ctx) setCsvCompareContext(ctx) } @@ -629,9 +629,8 @@ func PrepareCompareDiff( } baseGitRepo := ctx.Repo.GitRepo - baseCommitID := ci.CompareInfo.BaseCommitID - baseCommit, err := baseGitRepo.GetCommit(baseCommitID) + beforeCommit, err := baseGitRepo.GetCommit(beforeCommitID) if err != nil { ctx.ServerError("GetCommit", err) return false @@ -668,7 +667,7 @@ func PrepareCompareDiff( ctx.Data["Username"] = ci.HeadUser.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 } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 387853677c11d..b2566eaaab747 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -912,11 +912,19 @@ func MergePullRequest(ctx *context.Context) { pr := issue.PullRequest pr.Issue = issue 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 - 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 { case errors.Is(err, pull_service.ErrIsClosed): if issue.IsPull { @@ -948,7 +956,7 @@ func MergePullRequest(ctx *context.Context) { } // handle manually-merged mark - if manualMerge { + if manuallyMerged { if err := pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil { switch { diff --git a/services/automerge/automerge.go b/services/automerge/automerge.go index 49bd1d0c02965..8fec2239a2e1e 100644 --- a/services/automerge/automerge.go +++ b/services/automerge/automerge.go @@ -231,7 +231,7 @@ func handlePull(pullID int64, sha string) { 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) { log.Info("%-v was scheduled to automerge by an unauthorized user", pr) return diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index c1e9cb3197c0b..1e54e7cae376d 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -597,7 +597,7 @@ type MergePullRequestForm struct { MergeMessageField string MergeCommitID string // only used for manually-merged 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"` DeleteBranchAfterMerge bool `json:"delete_branch_after_merge,omitempty"` } diff --git a/services/pull/check.go b/services/pull/check.go index d828ee8cd7fad..f7e9e4a269015 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -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, ...) -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 { if pr.HasMerged { return ErrHasMerged @@ -80,8 +88,8 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce return ErrUserNotAllowedToMerge } - if manuallMerge { - // don't check rules to "auto merge", doer is going to mark this pull as merged manually + if mergeCheckType == MergeCheckTypeManually { + // if doer is doing "manually merge" (mark as merged manually), do not check anything return nil } @@ -103,14 +111,25 @@ func CheckPullMergable(stdCtx context.Context, doer *user_model.User, perm *acce return err } - if !force { - return err + // Now the branch protection check failed, check whether the failure could be skipped (skip by setting err = nil) + + // * when doing Auto Merge (Scheduled Merge After Checks Succeed), skip the branch protection check + if mergeCheckType == MergeCheckTypeAuto { + err = nil + } + + // * if the doer is admin, they could skip the branch protection check + if adminSkipProtectionCheck { + if isRepoAdmin, errCheckAdmin := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); errCheckAdmin != nil { + 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 isRepoAdmin, err2 := access_model.IsUserRepoAdmin(ctx, pr.BaseRepo, doer); err2 != nil { - log.Error("Unable to check if %-v is a repo admin in %-v: %v", doer, pr.BaseRepo, err2) - return err2 - } else if !isRepoAdmin { + // If there is still a branch protection check error, return it + if err != nil { return err } } diff --git a/services/pull/merge.go b/services/pull/merge.go index 2ae23b344712b..3a67919f48b52 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -516,7 +516,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode } sig := pr.Issue.Poster.NewGitSig() 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{ Env: env, Dir: tmpBasePath, @@ -534,7 +534,7 @@ func rawMerge(ctx context.Context, pr *issues_model.PullRequest, doer *user_mode if err := git.NewCommand(ctx, "commit"). AddArguments(signArg). AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email))). - AddArguments("-m").AddDynamicArguments(message). + AddArguments(git.CmdArg("--message=" + message)). Run(&git.RunOpts{ Env: env, 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 { var outbuf, errbuf strings.Builder if signArg == "" { - if err := git.NewCommand(ctx, "commit", "-m").AddDynamicArguments(message). + if err := git.NewCommand(ctx, "commit", git.CmdArg("--message="+message)). Run(&git.RunOpts{ Env: env, 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()) } } 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{ Env: env, Dir: tmpBasePath, diff --git a/services/repository/files/tree.go b/services/repository/files/tree.go index 513b8a2274787..1df1cb582ba90 100644 --- a/services/repository/files/tree.go +++ b/services/repository/files/tree.go @@ -86,6 +86,11 @@ func GetTreeBySHA(ctx context.Context, repo *repo_model.Repository, gitRepo *git if entries[e].IsDir() { copy(treeURL[copyPos:], entries[e].ID.String()) 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 { copy(blobURL[copyPos:], entries[e].ID.String()) tree.Entries[i].URL = string(blobURL) diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl index fceb0801341bd..176de69e5aeec 100644 --- a/templates/org/member/members.tmpl +++ b/templates/org/member/members.tmpl @@ -39,6 +39,7 @@