mirror of
1
Fork 0

Merge pull request '[v7.0/forgejo] Fix Issue watching / unwatching on the web ui' (#3585) from algernon/forgejo:backport/v7.0/3562 into v7.0/forgejo

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3585
Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
Earl Warren 2024-05-01 12:26:04 +00:00
commit 61230e72b5
4 changed files with 106 additions and 12 deletions

View File

@ -0,0 +1 @@
Fixed a bug where subscribing to or unsubscribing from an issue in a repository with no code produced an internal server error.

View File

@ -46,7 +46,7 @@ func IssueWatch(ctx *context.Context) {
return return
} }
watch, err := strconv.ParseBool(ctx.Req.PostForm.Get("watch")) watch, err := strconv.ParseBool(ctx.Req.PostFormValue("watch"))
if err != nil { if err != nil {
ctx.ServerError("watch is not bool", err) ctx.ServerError("watch is not bool", err)
return return

View File

@ -36,6 +36,7 @@ import (
"code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/testlogger" "code.gitea.io/gitea/modules/testlogger"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -45,6 +46,7 @@ import (
repo_service "code.gitea.io/gitea/services/repository" repo_service "code.gitea.io/gitea/services/repository"
files_service "code.gitea.io/gitea/services/repository/files" files_service "code.gitea.io/gitea/services/repository/files"
user_service "code.gitea.io/gitea/services/user" user_service "code.gitea.io/gitea/services/user"
wiki_service "code.gitea.io/gitea/services/wiki"
"code.gitea.io/gitea/tests" "code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
@ -652,19 +654,39 @@ func GetHTMLTitle(t testing.TB, session *TestSession, urlStr string) string {
return doc.Find("head title").Text() return doc.Find("head title").Text()
} }
func CreateDeclarativeRepo(t *testing.T, owner *user_model.User, name string, enabledUnits, disabledUnits []unit_model.Type, files []*files_service.ChangeRepoFile) (*repo_model.Repository, string, func()) { type DeclarativeRepoOptions struct {
Name optional.Option[string]
EnabledUnits optional.Option[[]unit_model.Type]
DisabledUnits optional.Option[[]unit_model.Type]
Files optional.Option[[]*files_service.ChangeRepoFile]
WikiBranch optional.Option[string]
AutoInit optional.Option[bool]
}
func CreateDeclarativeRepoWithOptions(t *testing.T, owner *user_model.User, opts DeclarativeRepoOptions) (*repo_model.Repository, string, func()) {
t.Helper() t.Helper()
repoName := name // Not using opts.Name.ValueOrDefault() here to avoid unnecessarily
if repoName == "" { // generating an UUID when a name is specified.
var repoName string
if opts.Name.Has() {
repoName = opts.Name.Value()
} else {
repoName = gouuid.NewString() repoName = gouuid.NewString()
} }
// Create a new repository var autoInit bool
if opts.AutoInit.Has() {
autoInit = opts.AutoInit.Value()
} else {
autoInit = true
}
// Create the repository
repo, err := repo_service.CreateRepository(db.DefaultContext, owner, owner, repo_service.CreateRepoOptions{ repo, err := repo_service.CreateRepository(db.DefaultContext, owner, owner, repo_service.CreateRepoOptions{
Name: repoName, Name: repoName,
Description: "Temporary Repo", Description: "Temporary Repo",
AutoInit: true, AutoInit: autoInit,
Gitignores: "", Gitignores: "",
License: "WTFPL", License: "WTFPL",
Readme: "Default", Readme: "Default",
@ -673,21 +695,32 @@ func CreateDeclarativeRepo(t *testing.T, owner *user_model.User, name string, en
assert.NoError(t, err) assert.NoError(t, err)
assert.NotEmpty(t, repo) assert.NotEmpty(t, repo)
if enabledUnits != nil || disabledUnits != nil { // Populate `enabledUnits` if we have any enabled.
units := make([]repo_model.RepoUnit, len(enabledUnits)) var enabledUnits []repo_model.RepoUnit
for i, unitType := range enabledUnits { if opts.EnabledUnits.Has() {
units[i] = repo_model.RepoUnit{ units := opts.EnabledUnits.Value()
enabledUnits = make([]repo_model.RepoUnit, len(units))
for i, unitType := range units {
enabledUnits[i] = repo_model.RepoUnit{
RepoID: repo.ID, RepoID: repo.ID,
Type: unitType, Type: unitType,
} }
} }
}
err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, units, disabledUnits) // Adjust the repo units according to our parameters.
if opts.EnabledUnits.Has() || opts.DisabledUnits.Has() {
err := repo_service.UpdateRepositoryUnits(db.DefaultContext, repo, enabledUnits, opts.DisabledUnits.ValueOrDefault(nil))
assert.NoError(t, err) assert.NoError(t, err)
} }
// Add files, if any.
var sha string var sha string
if len(files) > 0 { if opts.Files.Has() {
assert.True(t, autoInit, "Files cannot be specified if AutoInit is disabled")
files := opts.Files.Value()
resp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, owner, &files_service.ChangeRepoFilesOptions{ resp, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, owner, &files_service.ChangeRepoFilesOptions{
Files: files, Files: files,
Message: "add files", Message: "add files",
@ -712,7 +745,46 @@ func CreateDeclarativeRepo(t *testing.T, owner *user_model.User, name string, en
sha = resp.Commit.SHA sha = resp.Commit.SHA
} }
// If there's a Wiki branch specified, create a wiki, and a default wiki page.
if opts.WikiBranch.Has() {
// Set the wiki branch in the database first
repo.WikiBranch = opts.WikiBranch.Value()
err := repo_model.UpdateRepositoryCols(db.DefaultContext, repo, "wiki_branch")
assert.NoError(t, err)
// Initialize the wiki
err = wiki_service.InitWiki(db.DefaultContext, repo)
assert.NoError(t, err)
// Add a new wiki page
err = wiki_service.AddWikiPage(db.DefaultContext, owner, repo, "Home", "Welcome to the wiki!", "Add a Home page")
assert.NoError(t, err)
}
// Return the repo, the top commit, and a defer-able function to delete the
// repo.
return repo, sha, func() { return repo, sha, func() {
repo_service.DeleteRepository(db.DefaultContext, owner, repo, false) repo_service.DeleteRepository(db.DefaultContext, owner, repo, false)
} }
} }
func CreateDeclarativeRepo(t *testing.T, owner *user_model.User, name string, enabledUnits, disabledUnits []unit_model.Type, files []*files_service.ChangeRepoFile) (*repo_model.Repository, string, func()) {
t.Helper()
var opts DeclarativeRepoOptions
if name != "" {
opts.Name = optional.Some(name)
}
if enabledUnits != nil {
opts.EnabledUnits = optional.Some(enabledUnits)
}
if disabledUnits != nil {
opts.DisabledUnits = optional.Some(disabledUnits)
}
if files != nil {
opts.Files = optional.Some(files)
}
return CreateDeclarativeRepoWithOptions(t, owner, opts)
}

View File

@ -22,6 +22,7 @@ import (
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/indexer/issues"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/references" "code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
@ -866,3 +867,23 @@ body:
}) })
}) })
} }
func TestIssueUnsubscription(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
defer tests.PrepareTestEnv(t)()
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
repo, _, f := CreateDeclarativeRepoWithOptions(t, user, DeclarativeRepoOptions{
AutoInit: optional.Some(false),
})
defer f()
session := loginUser(t, user.Name)
issueURL := testNewIssue(t, session, user.Name, repo.Name, "Issue title", "Description")
req := NewRequestWithValues(t, "POST", fmt.Sprintf("%s/watch", issueURL), map[string]string{
"_csrf": GetCSRF(t, session, issueURL),
"watch": "0",
})
session.MakeRequest(t, req, http.StatusOK)
})
}