Skip to content

Commit a50026e

Browse files
authored
Fix no edit history after editing issue's title and content (#30814)
Fix #30807 reuse functions in services
1 parent 53b5522 commit a50026e

File tree

6 files changed

+56
-105
lines changed

6 files changed

+56
-105
lines changed

models/issues/issue_update.go

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -429,62 +429,6 @@ func UpdateIssueMentions(ctx context.Context, issueID int64, mentions []*user_mo
429429
return nil
430430
}
431431

432-
// UpdateIssueByAPI updates all allowed fields of given issue.
433-
// If the issue status is changed a statusChangeComment is returned
434-
// similarly if the title is changed the titleChanged bool is set to true
435-
func UpdateIssueByAPI(ctx context.Context, issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) {
436-
ctx, committer, err := db.TxContext(ctx)
437-
if err != nil {
438-
return nil, false, err
439-
}
440-
defer committer.Close()
441-
442-
if err := issue.LoadRepo(ctx); err != nil {
443-
return nil, false, fmt.Errorf("loadRepo: %w", err)
444-
}
445-
446-
// Reload the issue
447-
currentIssue, err := GetIssueByID(ctx, issue.ID)
448-
if err != nil {
449-
return nil, false, err
450-
}
451-
452-
if _, err := db.GetEngine(ctx).ID(issue.ID).Cols(
453-
"name", "content", "milestone_id", "priority",
454-
"deadline_unix", "updated_unix", "is_locked").
455-
Update(issue); err != nil {
456-
return nil, false, err
457-
}
458-
459-
titleChanged = currentIssue.Title != issue.Title
460-
if titleChanged {
461-
opts := &CreateCommentOptions{
462-
Type: CommentTypeChangeTitle,
463-
Doer: doer,
464-
Repo: issue.Repo,
465-
Issue: issue,
466-
OldTitle: currentIssue.Title,
467-
NewTitle: issue.Title,
468-
}
469-
_, err := CreateComment(ctx, opts)
470-
if err != nil {
471-
return nil, false, fmt.Errorf("createComment: %w", err)
472-
}
473-
}
474-
475-
if currentIssue.IsClosed != issue.IsClosed {
476-
statusChangeComment, err = doChangeIssueStatus(ctx, issue, doer, false)
477-
if err != nil {
478-
return nil, false, err
479-
}
480-
}
481-
482-
if err := issue.AddCrossReferences(ctx, doer, true); err != nil {
483-
return nil, false, err
484-
}
485-
return statusChangeComment, titleChanged, committer.Commit()
486-
}
487-
488432
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it.
489433
func UpdateIssueDeadline(ctx context.Context, issue *Issue, deadlineUnix timeutil.TimeStamp, doer *user_model.User) (err error) {
490434
// if the deadline hasn't changed do nothing

modules/structs/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ type CreatePullRequestOption struct {
8585
// EditPullRequestOption options when modify pull request
8686
type EditPullRequestOption struct {
8787
Title string `json:"title"`
88-
Body string `json:"body"`
88+
Body *string `json:"body"`
8989
Base string `json:"base"`
9090
Assignee string `json:"assignee"`
9191
Assignees []string `json:"assignees"`

routers/api/v1/repo/issue.go

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import (
2929
"code.gitea.io/gitea/services/context"
3030
"code.gitea.io/gitea/services/convert"
3131
issue_service "code.gitea.io/gitea/services/issue"
32-
notify_service "code.gitea.io/gitea/services/notify"
3332
)
3433

3534
// SearchIssues searches for issues across the repositories that the user has access to
@@ -803,12 +802,19 @@ func EditIssue(ctx *context.APIContext) {
803802
return
804803
}
805804

806-
oldTitle := issue.Title
807805
if len(form.Title) > 0 {
808-
issue.Title = form.Title
806+
err = issue_service.ChangeTitle(ctx, issue, ctx.Doer, form.Title)
807+
if err != nil {
808+
ctx.Error(http.StatusInternalServerError, "ChangeTitle", err)
809+
return
810+
}
809811
}
810812
if form.Body != nil {
811-
issue.Content = *form.Body
813+
err = issue_service.ChangeContent(ctx, issue, ctx.Doer, *form.Body)
814+
if err != nil {
815+
ctx.Error(http.StatusInternalServerError, "ChangeContent", err)
816+
return
817+
}
812818
}
813819
if form.Ref != nil {
814820
err = issue_service.ChangeIssueRef(ctx, issue, ctx.Doer, *form.Ref)
@@ -880,24 +886,14 @@ func EditIssue(ctx *context.APIContext) {
880886
return
881887
}
882888
}
883-
issue.IsClosed = api.StateClosed == api.StateType(*form.State)
884-
}
885-
statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer)
886-
if err != nil {
887-
if issues_model.IsErrDependenciesLeft(err) {
888-
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
889+
if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", api.StateClosed == api.StateType(*form.State)); err != nil {
890+
if issues_model.IsErrDependenciesLeft(err) {
891+
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
892+
return
893+
}
894+
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err)
889895
return
890896
}
891-
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
892-
return
893-
}
894-
895-
if titleChanged {
896-
notify_service.IssueChangeTitle(ctx, ctx.Doer, issue, oldTitle)
897-
}
898-
899-
if statusChangeComment != nil {
900-
notify_service.IssueChangeStatus(ctx, ctx.Doer, "", issue, statusChangeComment, issue.IsClosed)
901897
}
902898

903899
// Refetch from database to assign some automatic values

routers/api/v1/repo/pull.go

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -602,12 +602,19 @@ func EditPullRequest(ctx *context.APIContext) {
602602
return
603603
}
604604

605-
oldTitle := issue.Title
606605
if len(form.Title) > 0 {
607-
issue.Title = form.Title
606+
err = issue_service.ChangeTitle(ctx, issue, ctx.Doer, form.Title)
607+
if err != nil {
608+
ctx.Error(http.StatusInternalServerError, "ChangeTitle", err)
609+
return
610+
}
608611
}
609-
if len(form.Body) > 0 {
610-
issue.Content = form.Body
612+
if form.Body != nil {
613+
err = issue_service.ChangeContent(ctx, issue, ctx.Doer, *form.Body)
614+
if err != nil {
615+
ctx.Error(http.StatusInternalServerError, "ChangeContent", err)
616+
return
617+
}
611618
}
612619

613620
// Update or remove deadline if set
@@ -686,24 +693,14 @@ func EditPullRequest(ctx *context.APIContext) {
686693
ctx.Error(http.StatusPreconditionFailed, "MergedPRState", "cannot change state of this pull request, it was already merged")
687694
return
688695
}
689-
issue.IsClosed = api.StateClosed == api.StateType(*form.State)
690-
}
691-
statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer)
692-
if err != nil {
693-
if issues_model.IsErrDependenciesLeft(err) {
694-
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
696+
if err := issue_service.ChangeStatus(ctx, issue, ctx.Doer, "", api.StateClosed == api.StateType(*form.State)); err != nil {
697+
if issues_model.IsErrDependenciesLeft(err) {
698+
ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
699+
return
700+
}
701+
ctx.Error(http.StatusInternalServerError, "ChangeStatus", err)
695702
return
696703
}
697-
ctx.Error(http.StatusInternalServerError, "UpdateIssueByAPI", err)
698-
return
699-
}
700-
701-
if titleChanged {
702-
notify_service.IssueChangeTitle(ctx, ctx.Doer, issue, oldTitle)
703-
}
704-
705-
if statusChangeComment != nil {
706-
notify_service.IssueChangeStatus(ctx, ctx.Doer, "", issue, statusChangeComment, issue.IsClosed)
707704
}
708705

709706
// change pull target branch

tests/integration/api_issue_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,10 @@ func TestAPIEditIssue(t *testing.T) {
194194
issueAfter := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 10})
195195
repoAfter := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issueBefore.RepoID})
196196

197+
// check comment history
198+
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: issueAfter.ID, OldTitle: issueBefore.Title, NewTitle: title})
199+
unittest.AssertExistsAndLoadBean(t, &issues_model.ContentHistory{IssueID: issueAfter.ID, ContentText: body, IsFirstCreated: false})
200+
197201
// check deleted user
198202
assert.Equal(t, int64(500), issueAfter.PosterID)
199203
assert.NoError(t, issueAfter.LoadAttributes(db.DefaultContext))

tests/integration/api_pull_test.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -223,23 +223,33 @@ func TestAPIEditPull(t *testing.T) {
223223

224224
session := loginUser(t, owner10.Name)
225225
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
226+
title := "create a success pr"
226227
req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls", owner10.Name, repo10.Name), &api.CreatePullRequestOption{
227228
Head: "develop",
228229
Base: "master",
229-
Title: "create a success pr",
230+
Title: title,
230231
}).AddTokenAuth(token)
231-
pull := new(api.PullRequest)
232+
apiPull := new(api.PullRequest)
232233
resp := MakeRequest(t, req, http.StatusCreated)
233-
DecodeJSON(t, resp, pull)
234-
assert.EqualValues(t, "master", pull.Base.Name)
234+
DecodeJSON(t, resp, apiPull)
235+
assert.EqualValues(t, "master", apiPull.Base.Name)
235236

236-
req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, pull.Index), &api.EditPullRequestOption{
237+
newTitle := "edit a this pr"
238+
newBody := "edited body"
239+
req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, apiPull.Index), &api.EditPullRequestOption{
237240
Base: "feature/1",
238-
Title: "edit a this pr",
241+
Title: newTitle,
242+
Body: &newBody,
239243
}).AddTokenAuth(token)
240244
resp = MakeRequest(t, req, http.StatusCreated)
241-
DecodeJSON(t, resp, pull)
242-
assert.EqualValues(t, "feature/1", pull.Base.Name)
245+
DecodeJSON(t, resp, apiPull)
246+
assert.EqualValues(t, "feature/1", apiPull.Base.Name)
247+
// check comment history
248+
pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: apiPull.ID})
249+
err := pull.LoadIssue(db.DefaultContext)
250+
assert.NoError(t, err)
251+
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{IssueID: pull.Issue.ID, OldTitle: title, NewTitle: newTitle})
252+
unittest.AssertExistsAndLoadBean(t, &issues_model.ContentHistory{IssueID: pull.Issue.ID, ContentText: newBody, IsFirstCreated: false})
243253

244254
req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d", owner10.Name, repo10.Name, pull.Index), &api.EditPullRequestOption{
245255
Base: "not-exist",

0 commit comments

Comments
 (0)